diff options
-rw-r--r-- | contrib/sssd.spec.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 35 | ||||
-rw-r--r-- | src/config/SSSDConfig.py | 4 | ||||
-rwxr-xr-x | src/config/SSSDConfigTest.py | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-simple.conf | 5 | ||||
-rw-r--r-- | src/man/sssd-simple.5.xml | 124 | ||||
-rw-r--r-- | src/man/sssd.conf.5.xml | 7 | ||||
-rw-r--r-- | src/providers/simple/simple_access.c | 160 | ||||
-rw-r--r-- | src/providers/simple/simple_access.h | 36 | ||||
-rw-r--r-- | src/tests/simple_access-tests.c | 173 |
10 files changed, 542 insertions, 5 deletions
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index 63f55c5c..16e2b407 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -253,6 +253,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 @@ -301,6 +302,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 aa7fccb9..9da383b5 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 2697c71b..c9e08caf 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 ef761a2b..4e9d0914 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 00000000..13fbeb9e --- /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 00000000..260d15ab --- /dev/null +++ b/src/man/sssd-simple.5.xml @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.4//EN" +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> +<reference> +<title>SSSD Manual pages</title> +<refentry> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" /> + + <refmeta> + <refentrytitle>sssd-simple</refentrytitle> + <manvolnum>5</manvolnum> + <refmiscinfo class="manual">File Formats and Conventions</refmiscinfo> + </refmeta> + + <refnamediv id='name'> + <refname>sssd-simple</refname> + <refpurpose>the configuration file for SSSD's 'simple' access-control + provider</refpurpose> + </refnamediv> + + <refsect1 id='description'> + <title>DESCRIPTION</title> + <para> + This manual page describes the configuration of the simple + access-control provider for + <citerefentry> + <refentrytitle>sssd</refentrytitle> + <manvolnum>8</manvolnum> + </citerefentry>. + For a detailed syntax reference, refer to the + <quote>FILE FORMAT</quote> section of the + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page. + </para> + <para> + The simple access provider grants or denies access based on an + access or deny list of user names. Here to following rules apply: + <itemizedlist> + <listitem> + <para>If both lists are empty, access is granted</para> + </listitem> + <listitem> + <para>If simple_allow_users is set, only users from this + list are allowed access.</para> + <para>This setting supersedes the simple_deny_users list + (which would be redundant).</para> + </listitem> + <listitem> + <para>If the simple_allow_users list is empty, users are + allowed access unless they appear in the + simple_deny_users list</para> + </listitem> + </itemizedlist> + </para> + </refsect1> + + <refsect1 id='file-format'> + <title>CONFIGURATION OPTIONS</title> + <para>Refer to the section <quote>DOMAIN SECTIONS</quote> of the + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle> + <manvolnum>5</manvolnum> + </citerefentry> manual page for details on the configuration of an + SSSD domain. + <variablelist> + <varlistentry> + <term>simple_allow_users (string)</term> + <listitem> + <para> + Comma separated list of users who are allowed to log + in. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>simple_deny_users (string)</term> + <listitem> + <para> + Comma separated list of users who are rejected if + simple_allow_users is not set. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + <para> + Please note that it is an configuration error if both, + simple_allow_users and simple_deny_users, are defined. + </para> + </refsect1> + + <refsect1 id='example'> + <title>EXAMPLE</title> + <para> + The following example assumes that SSSD is correctly + configured and example.com is one of the domains in the + <replaceable>[sssd]</replaceable> section. This examples shows only + the simple access provider-specific options. + </para> + <para> +<programlisting> + [domain/example.com] + access_provider = simple + simple_allow_users = user1, user2 +</programlisting> + </para> + </refsect1> + + <refsect1 id='see_also'> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>sssd.conf</refentrytitle><manvolnum>5</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>sssd</refentrytitle><manvolnum>8</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> +</reference> diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 6303fcbc..daf61afc 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -565,6 +565,13 @@ <quote>deny</quote> always deny access. </para> <para> + <quote>simple</quote> access control based on access + or deny lists. See <citerefentry> + <refentrytitle>sssd-simple</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for more + information on configuring the simple access module. + </para> + <para> Default: <quote>permit</quote> </para> </listitem> diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c new file mode 100644 index 00000000..4d6135fa --- /dev/null +++ b/src/providers/simple/simple_access.c @@ -0,0 +1,160 @@ +/* + SSSD + + Simple access control + + Copyright (C) Sumit Bose <sbose@redhat.com> 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 <http://www.gnu.org/licenses/>. +*/ + +#include <errno.h> + +#include <security/pam_modules.h> + +#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 00000000..0aac42a5 --- /dev/null +++ b/src/providers/simple/simple_access.h @@ -0,0 +1,36 @@ +/* + SSSD + + Simple access control + + Copyright (C) Sumit Bose <sbose@redhat.com> 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 <http://www.gnu.org/licenses/>. +*/ + +#ifndef __SIMPLE_ACCESS_H__ +#define __SIMPLE_ACCESS_H__ + +#include <stdlib.h> + +#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 00000000..f1d3775a --- /dev/null +++ b/src/tests/simple_access-tests.c @@ -0,0 +1,173 @@ +/* + SSSD + + Simple access module -- Tests + + Authors: + Sumit Bose <sbose@redhat.com> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <popt.h> +#include <check.h> + +#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); +} + |