From 0321925b89b1ed3cae29c796da6e4fd622fa54df Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 25 Feb 2010 17:30:47 +0100 Subject: [PATCH] Add simple access provider --- contrib/sssd.spec.in | 2 + src/Makefile.am | 35 +++++- src/config/SSSDConfig.py | 4 + src/config/SSSDConfigTest.py | 1 + src/config/etc/sssd.api.d/sssd-simple.conf | 5 + src/man/sssd-simple.5.xml | 124 ++++++++++++++++++++ src/man/sssd.conf.5.xml | 7 + src/providers/simple/simple_access.c | 160 +++++++++++++++++++++++++ src/providers/simple/simple_access.h | 36 ++++++ src/tests/simple_access-tests.c | 173 ++++++++++++++++++++++++++++ 10 files changed, 542 insertions(+), 5 deletions(-) create mode 100644 src/config/etc/sssd.api.d/sssd-simple.conf create mode 100644 src/man/sssd-simple.5.xml create mode 100644 src/providers/simple/simple_access.c create mode 100644 src/providers/simple/simple_access.h create mode 100644 src/tests/simple_access-tests.c diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index 324131a..60c1986 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -252,6 +252,7 @@ rm -f \ $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_proxy.la \ $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_krb5.la \ $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ipa.la \ + $RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_simple.la \ $RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.la \ $RPM_BUILD_ROOT/%{python_sitearch}/pysss.la @@ -300,6 +301,7 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man5/sssd-ipa.5* %{_mandir}/man5/sssd-krb5.5* %{_mandir}/man5/sssd-ldap.5* +%{_mandir}/man5/sssd-simple.5* %{_mandir}/man8/sssd.8* %{_mandir}/man8/sss_groupadd.8* %{_mandir}/man8/sss_groupdel.8* diff --git a/src/Makefile.am b/src/Makefile.am index aa7fccb..9da383b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -75,7 +75,8 @@ if HAVE_CHECK fail_over-tests \ find_uid-tests \ auth-tests \ - ipa_ldap_opt-tests + ipa_ldap_opt-tests \ + simple_access-tests endif check_PROGRAMS = \ @@ -90,7 +91,8 @@ sssdlib_LTLIBRARIES = \ libsss_ldap.la \ libsss_krb5.la \ libsss_proxy.la \ - libsss_ipa.la + libsss_ipa.la \ + libsss_simple.la ldblib_LTLIBRARIES = \ memberof.la @@ -324,6 +326,7 @@ dist_noinst_HEADERS = \ providers/fail_over.h \ providers/providers.h \ providers/child_common.h \ + providers/simple/simple_access.h \ providers/krb5/krb5_auth.h \ providers/krb5/krb5_common.h \ providers/krb5/krb5_utils.h \ @@ -635,6 +638,17 @@ ipa_ldap_opt_tests_LDADD = \ $(CHECK_LIBS) \ libsss_test_common.la +simple_access_tests_SOURCES = \ + tests/simple_access-tests.c \ + providers/simple/simple_access.c \ + $(SSSD_UTIL_OBJ) +simple_access_tests_CFLAGS = \ + $(AM_CFLAGS) \ + $(CHECK_CFLAGS) +simple_access_tests_LDADD = \ + $(SSSD_LIBS) \ + $(CHECK_LIBS) + endif stress_tests_SOURCES = \ @@ -721,6 +735,16 @@ libsss_proxy_la_LDFLAGS = \ -version-info 1:0:0 \ -module +libsss_simple_la_SOURCES = \ + providers/simple/simple_access.c +libsss_simple_la_CFLAGS = \ + $(AM_CFLAGS) +libsss_simple_la_LIBADD = \ + $(PAM_LIBS) +libsss_simple_la_LDFLAGS = \ + -version-info 1:0:0 \ + -module + libsss_krb5_la_SOURCES = \ util/find_uid.c \ providers/child_common.c \ @@ -860,8 +884,8 @@ XSLTPROC_FLAGS = --catalogs --xinclude --nonet dist_man_MANS = man/sss_useradd.8 man/sss_userdel.8 man/sss_usermod.8 \ man/sss_groupadd.8 man/sss_groupdel.8 man/sss_groupmod.8 \ man/sssd.8 man/sssd.conf.5 man/sssd-ldap.5 man/sssd-krb5.5 \ - man/sssd-ipa.5 man/sssd_krb5_locator_plugin.8 \ - man/sss_groupshow.8 man/pam_sss.8 + man/sssd-ipa.5 man/sssd-simple.5 \ + man/sssd_krb5_locator_plugin.8 man/sss_groupshow.8 man/pam_sss.8 SUFFIXES = .1.xml .1 .3.xml .3 .5.xml .5 .8.xml .8 .1.xml.1: @@ -901,7 +925,8 @@ dist_sssdapiplugin_DATA = \ config/etc/sssd.api.d/sssd-krb5.conf \ config/etc/sssd.api.d/sssd-ldap.conf \ config/etc/sssd.api.d/sssd-local.conf \ - config/etc/sssd.api.d/sssd-proxy.conf + config/etc/sssd.api.d/sssd-proxy.conf \ + config/etc/sssd.api.d/sssd-simple.conf installsssddirs:: mkdir -p \ diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index 2697c71..c9e08ca 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -144,6 +144,10 @@ option_strings = { # [provider/ldap/auth] 'ldap_pwd_policy' : _('Policy to evaluate the password expiration'), + # [provider/simple/access] + 'simple_allow_users' : _('Comma separated list of allowed users'), + 'simple_deny_users' : _('Comma separated list of prohibited users'), + # [provider/local/id] 'default_shell' : _('Default shell, /bin/bash'), 'base_directory' : _('Base for home directories'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index ef761a2..4e9d091 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -629,6 +629,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'ldap': ['id', 'auth', 'chpass'], 'krb5': ['auth', 'chpass'], 'proxy': ['id', 'auth'], + 'simple': ['access'], 'permit': ['access'], 'deny': ['access']} diff --git a/src/config/etc/sssd.api.d/sssd-simple.conf b/src/config/etc/sssd.api.d/sssd-simple.conf new file mode 100644 index 0000000..13fbeb9 --- /dev/null +++ b/src/config/etc/sssd.api.d/sssd-simple.conf @@ -0,0 +1,5 @@ +[provider/simple] + +[provider/simple/access] +simple_allow_users = str, None, false +simple_deny_users = str, None, false diff --git a/src/man/sssd-simple.5.xml b/src/man/sssd-simple.5.xml new file mode 100644 index 0000000..260d15a --- /dev/null +++ b/src/man/sssd-simple.5.xml @@ -0,0 +1,124 @@ + + + +SSSD Manual pages + + + + + sssd-simple + 5 + File Formats and Conventions + + + + sssd-simple + the configuration file for SSSD's 'simple' access-control + provider + + + + DESCRIPTION + + This manual page describes the configuration of the simple + access-control provider for + + sssd + 8 + . + For a detailed syntax reference, refer to the + FILE FORMAT section of the + + sssd.conf + 5 + manual page. + + + The simple access provider grants or denies access based on an + access or deny list of user names. Here to following rules apply: + + + If both lists are empty, access is granted + + + If simple_allow_users is set, only users from this + list are allowed access. + This setting supersedes the simple_deny_users list + (which would be redundant). + + + If the simple_allow_users list is empty, users are + allowed access unless they appear in the + simple_deny_users list + + + + + + + CONFIGURATION OPTIONS + Refer to the section DOMAIN SECTIONS of the + + sssd.conf + 5 + manual page for details on the configuration of an + SSSD domain. + + + simple_allow_users (string) + + + Comma separated list of users who are allowed to log + in. + + + + + + simple_deny_users (string) + + + Comma separated list of users who are rejected if + simple_allow_users is not set. + + + + + + + Please note that it is an configuration error if both, + simple_allow_users and simple_deny_users, are defined. + + + + + EXAMPLE + + The following example assumes that SSSD is correctly + configured and example.com is one of the domains in the + [sssd] section. This examples shows only + the simple access provider-specific options. + + + + [domain/example.com] + access_provider = simple + simple_allow_users = user1, user2 + + + + + + SEE ALSO + + + sssd.conf5 + , + + sssd8 + + + + + diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 6303fcb..daf61af 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -565,6 +565,13 @@ deny always deny access. + simple access control based on access + or deny lists. See + sssd-simple + 5 for more + information on configuring the simple access module. + + Default: permit diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c new file mode 100644 index 0000000..4d6135f --- /dev/null +++ b/src/providers/simple/simple_access.c @@ -0,0 +1,160 @@ +/* + SSSD + + Simple access control + + Copyright (C) Sumit Bose 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include + +#include "util/util.h" +#include "providers/dp_backend.h" +#include "db/sysdb.h" +#include "providers/simple/simple_access.h" + +#define CONFDB_SIMPLE_ALLOW_USERS "simple_allow_users" +#define CONFDB_SIMPLE_DENY_USERS "simple_deny_users" + +errno_t simple_access_check(struct simple_ctx *ctx, const char *username, + bool *access_granted) +{ + int i; + + *access_granted = false; + if (ctx->allow_users != NULL) { + for(i = 0; ctx->allow_users[i] != NULL; i++) { + if (strcmp(username, ctx->allow_users[i]) == 0) { + DEBUG(9, ("User [%s] found in allow list, access granted.\n", + username)); + *access_granted = true; + return EOK; + } + } + } else { + *access_granted = true; + if (ctx->deny_users != NULL) { + for(i = 0; ctx->deny_users[i] != NULL; i++) { + if (strcmp(username, ctx->deny_users[i]) == 0) { + DEBUG(9, ("User [%s] found in deny list, access denied.\n", + username)); + *access_granted = false; + return EOK; + } + } + } + } + + return EOK; +} + +void simple_access_handler(struct be_req *be_req) +{ + int ret; + bool access_granted = false; + struct pam_data *pd; + struct simple_ctx *ctx; + + pd = talloc_get_type(be_req->req_data, struct pam_data); + + pd->pam_status = PAM_SYSTEM_ERR; + + if (pd->cmd != SSS_PAM_ACCT_MGMT) { + DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd)); + pd->pam_status = PAM_MODULE_UNKNOWN; + goto done; + } + + ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, + struct simple_ctx); + + ret = simple_access_check(ctx, pd->user, &access_granted); + if (ret != EOK) { + pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + + if (access_granted) { + pd->pam_status = PAM_SUCCESS; + } else { + pd->pam_status = PAM_PERM_DENIED; + } + +done: + be_req->fn(be_req, DP_ERR_OK, pd->pam_status, NULL); +} + +struct bet_ops simple_access_ops = { + .handler = simple_access_handler, + .finalize = NULL +}; + +int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops, + void **pvt_data) +{ + int ret = EINVAL; + struct simple_ctx *ctx; + + ctx = talloc_zero(bectx, struct simple_ctx); + if (ctx == NULL) { + DEBUG(1, ("talloc_zero failed.\n")); + return ENOMEM; + } + + ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path, + CONFDB_SIMPLE_ALLOW_USERS, + &ctx->allow_users); + if (ret != EOK) { + if (ret == ENOENT) { + DEBUG(9, ("Allow user list is empty.\n")); + ctx->allow_users = NULL; + } else { + DEBUG(1, ("confdb_get_string_as_list failed.\n")); + goto failed; + } + } + + ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path, + CONFDB_SIMPLE_DENY_USERS, + &ctx->deny_users); + if (ret != EOK) { + if (ret == ENOENT) { + DEBUG(9, ("Deny user list is empty.\n")); + ctx->deny_users = NULL; + } else { + DEBUG(1, ("confdb_get_string_as_list failed.\n")); + goto failed; + } + } + + if (ctx->allow_users != NULL && ctx->deny_users != NULL) { + DEBUG(1, ("Access and deny list are defined, only one is allowed.\n")); + ret = EINVAL; + goto failed; + } + + + *ops = &simple_access_ops; + *pvt_data = ctx; + + return EOK; + +failed: + talloc_free(ctx); + return ret; +} diff --git a/src/providers/simple/simple_access.h b/src/providers/simple/simple_access.h new file mode 100644 index 0000000..0aac42a --- /dev/null +++ b/src/providers/simple/simple_access.h @@ -0,0 +1,36 @@ +/* + SSSD + + Simple access control + + Copyright (C) Sumit Bose 2010 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef __SIMPLE_ACCESS_H__ +#define __SIMPLE_ACCESS_H__ + +#include + +#include "util/util.h" + +struct simple_ctx { + char **allow_users; + char **deny_users; +}; + +errno_t simple_access_check(struct simple_ctx *ctx, const char *username, + bool *access_granted); +#endif /* __SIMPLE_ACCESS_H__ */ diff --git a/src/tests/simple_access-tests.c b/src/tests/simple_access-tests.c new file mode 100644 index 0000000..f1d3775 --- /dev/null +++ b/src/tests/simple_access-tests.c @@ -0,0 +1,173 @@ +/* + SSSD + + Simple access module -- Tests + + Authors: + Sumit Bose + + Copyright (C) 2010 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#include "providers/simple/simple_access.h" + +const char *ulist_1[] = {"u1", "u2", NULL}; + +struct simple_ctx *ctx = NULL; + +void setup_simple(void) +{ + fail_unless(ctx == NULL, "Simple context already initialized."); + ctx = talloc_zero(NULL, struct simple_ctx); + fail_unless(ctx != NULL, "Cannot create simple context."); +} + +void teardown_simple(void) +{ + int ret; + fail_unless(ctx != NULL, "Simple context already freed."); + ret = talloc_free(ctx); + ctx = NULL; + fail_unless(ret == 0, "Connot free simple context."); +} + +START_TEST(test_both_empty) +{ + int ret; + bool access_granted = false; + + ctx->allow_users = NULL; + ctx->deny_users = NULL; + + ret = simple_access_check(ctx, "u1", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == true, "Access denied " + "while both lists are empty."); +} +END_TEST + +START_TEST(test_allow_empty) +{ + int ret; + bool access_granted = true; + + ctx->allow_users = NULL; + ctx->deny_users = discard_const(ulist_1); + + ret = simple_access_check(ctx, "u1", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == false, "Access granted " + "while user is in deny list."); + + ret = simple_access_check(ctx, "u3", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == true, "Access denied " + "while user is not in deny list."); +} +END_TEST + +START_TEST(test_deny_empty) +{ + int ret; + bool access_granted = false; + + ctx->allow_users = discard_const(ulist_1); + ctx->deny_users = NULL; + + ret = simple_access_check(ctx, "u1", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == true, "Access denied " + "while user is in allow list."); + + ret = simple_access_check(ctx, "u3", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == false, "Access granted " + "while user is not in allow list."); +} +END_TEST + +START_TEST(test_both_set) +{ + int ret; + bool access_granted = false; + + ctx->allow_users = discard_const(ulist_1); + ctx->deny_users = discard_const(ulist_1); + + ret = simple_access_check(ctx, "u1", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == true, "Access denied " + "while user is in allow list."); + + ret = simple_access_check(ctx, "u3", &access_granted); + fail_unless(ret == EOK, "access_simple_check failed."); + fail_unless(access_granted == false, "Access granted " + "while user is not in allow list."); +} +END_TEST + +Suite *access_simple_suite (void) +{ + Suite *s = suite_create("access_simple"); + + TCase *tc_allow_deny = tcase_create("allow/deny"); + tcase_add_checked_fixture(tc_allow_deny, setup_simple, teardown_simple); + tcase_add_test(tc_allow_deny, test_both_empty); + tcase_add_test(tc_allow_deny, test_allow_empty); + tcase_add_test(tc_allow_deny, test_deny_empty); + tcase_add_test(tc_allow_deny, test_both_set); + suite_add_tcase(s, tc_allow_deny); + + return s; +} + +int main(int argc, const char *argv[]) +{ + int opt; + poptContext pc; + int number_failed; + + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_MAIN_OPTS + { NULL } + }; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + + Suite *s = access_simple_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_ENV); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + -- 1.6.6.1