From e13d8a12513bfba1531cc867fbf687ff8673241f Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov Date: Thu, 10 Dec 2020 19:45:08 +0100 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 6b3b4b0bf945814e8886b900dcda18de25f38bb4 Author: Sumit Bose Date: Thu Dec 12 13:10:16 2019 +0100 certmap: mention special regex characters in man page Since some of the matching rules use regular expressions some characters must be escaped so that they can be used a ordinary characters in the rules. Related to https://pagure.io/SSSD/sssd/issue/4127 Reviewed-by: Michal Židek (cherry picked from commit 21cb9fb28db1f2eb4ee770eb029bfe20233e4392) commit 451410e72514bd68e4b56b1a42c97ade6783e74b Author: Sumit Bose Date: Tue Nov 27 16:42:38 2018 +0100 test: add certificate without KU to certmap tests Make sure there is a test for a certificate without key-usage (KU) Related to https://bugzilla.redhat.com/show_bug.cgi?id=1660899 Reviewed-by: Jakub Hrozek (cherry picked from commit e1734ba828470d00370c44c95da56822fdcc104d) commit e7966dfa40b9a7fcde79a07f146ae5283a7bc8e5 Author: Sumit Bose Date: Mon Nov 26 12:03:13 2018 +0100 certmap: allow missing KU in OpenSSL version Make sure a missing key-usage (KU) is not treated as an error and is handled equally in the NSS and OpenSSL implementation Related to https://bugzilla.redhat.com/show_bug.cgi?id=1660899 Reviewed-by: Jakub Hrozek (cherry picked from commit aef8e49b7ee2e7743d6981070d61bc89b7c8fcfb) commit 6e9e6673916b61197df8a809f56c73d8bdbb868c Author: Alexey Tikhonov Date: Mon Jan 7 17:04:34 2019 +0100 CONFIG: validator rules & test Add support of 'certmap' config section to validator rules Resolves: https://pagure.io/SSSD/sssd/issue/3845 Reviewed-by: Jakub Hrozek (cherry picked from commit 8e9e8011ce17860bec67a572e4c11a9178c03b8e) commit eec9d72a242b2b05369f0eb89c4ebcda26d59802 Author: Sumit Bose Date: Fri Sep 7 22:26:21 2018 +0200 intg: add Smartcard authentication tests Two test for Smartcard authentication of a local user, i.e. a user managed by the files provider, are added. One for a successful authentication, the other for a failed authentication with a wrong PIN. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked with fixes from commit 657f3b89bca9adfb13f0867c91f1d76845d2d6dd) commit cc2840fbb494ac686e9a3ae0016827a44d14769f Author: Sumit Bose Date: Fri Sep 7 22:17:47 2018 +0200 test_ca: set a password/PIN to nss databases To make sure the PIN is properly checked during tests the NSS databases need a password. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit a45a410dc7fa7cf84bcac541e693ee8781e25431) commit 0a989c62b4a3b73f23d9b6956ac81afaed9901f7 Author: Sumit Bose Date: Mon Sep 10 22:03:55 2018 +0200 test_ca: test library only for readable On Debian libraries typically do not have the execute-bit set so it is better to only check for readability. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 91aea762d02731193eb66a00b930ff1fe8bc5ab8) commit 5a47b213b11cbf74dad47594d1826985f6b68f22 Author: Sumit Bose Date: Fri Sep 7 22:16:50 2018 +0200 PAM: use better PAM error code for failed Smartcard authentication If the user enters a wrong PIN the PAM responder currently returns PAM_USER_UNKNOWN better is PAM_AUTH_ERR. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 442ae7b1d0704cdd667d4f1ba4c165ce3f3ffed4) commit b6907d7cd5ab7568971ddb48f3932f106e86fe06 Author: Sumit Bose Date: Mon Sep 3 18:38:42 2018 +0200 doc: add certificate mapping section to man page Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked with fixes from commit 0c739e969a617bdb4c06cdfd63772bf6d283c518) commit d75b196312c4cec767c196c663ff969b6aebcd6b Author: Sumit Bose Date: Mon Jul 9 18:56:26 2018 +0200 PAM: add certificate matching rules from all domains Currently the PAM responder only reads the certificate mapping and matching rules from the first domain. To support Smartcard authentication for local and remote users all configured domains must be taken into account. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit d42f44d54453d3ddb54875374c1b61dc1e7cd821) commit 167ab7206913c17617a8e5ada7567d91f8ed6e11 Author: Sumit Bose Date: Mon Jul 9 18:45:21 2018 +0200 responder: make sure SSS_DP_CERT is passed to files provider Currently the files provider is only contacted once in a while to update the full cache with fresh data from the passwd file. To allow rule based certificate mapping the lookup by certificate request must be always send to the file provider so that it can evaluate the rules and add the certificate to cached entry of the matching user. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 9fdc5f1d87a133885e6a22810a7eb980c60dcb55) commit 69def7a3e81313a30ceae937f9cde5d62e999c3d Author: Sumit Bose Date: Mon Jul 9 18:37:46 2018 +0200 files: add support for Smartcard authentication To support certificate based authentication the files provider must be able to map a certificate to a user during a BE_REQ_BY_CERT request. Additionally the authentication request should be handled by the PAM responder code which is responsible for the local Smartcard authentication. To be consistent with the other backend an authentication handler is added to the files provider which unconditionally returns the offline error code telling the PAM responder to handle the authentication if it has access to the needed credentials. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 275eeed24adc31f3df51cf278f509a4be76a3a3c) commit e96ba56ea8037d58e1335f7dacd3b19919bc4135 Author: Sumit Bose Date: Fri Jul 6 15:17:10 2018 +0200 confdb: add special handling for rules for the files provider To make the configuration more simple there are some special assumption for local users, i.e. user managed by the files provider. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 9386ef605ffbc03abe2bc273efddbc099441fe3b) commit d304f5a9e60f7f6eb915a10067ee2e5e5f14c369 Author: Sumit Bose Date: Tue Jul 3 11:31:12 2018 +0200 sysdb: sysdb_certmap_add() handle domains more flexible sysdb_ldb_msg_attr_to_certmap_info() creates an empty list if there are no domains defined, sysdb_certmap_add() should be able to handle both a missing or an empty domains list. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 06f7005d38d164879b727708feff80004b422f91) commit 53befb320c2b60a420a2588425fd5004ceec791a Author: Sumit Bose Date: Mon Jul 2 12:20:53 2018 +0200 AD/LDAP: read certificate mapping rules from config file Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 15301db1dc1e5e2aafc1805a30e3b28756218c9b) commit 670a1ca6b7b22bb3a1079111528ee7e4aafd97e5 Author: Sumit Bose Date: Mon Jul 2 10:38:54 2018 +0200 confdb: add confdb_certmap_to_sysdb() Add a function to write certificate mapping and matching rules from the config database to the cache of a domain. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked with fixes from commit d9cc38008a51a8a5189904f175e4d10cbde4a974) commit 14c15cc6db16726419fbf6df76b5c83aec49192a Author: Sumit Bose Date: Fri Jun 29 18:13:59 2018 +0200 sysdb: add attr_map attribute to sysdb_ldb_msg_attr_to_certmap_info() Allow more flexible attribute mapping in sysdb_ldb_msg_attr_to_certmap_info() Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 0bf709ad348ca115443bd21e4e369abd5d7698c4) commit f867c2a293651043072afe1dd7a8a78a05e5fe4d Author: Sumit Bose Date: Tue Jul 3 11:30:07 2018 +0200 sysdb_ldb_msg_attr_to_certmap_info: set SSS_CERTMAP_MIN_PRIO Make sure that priority is always set. Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit d1dd7f7703b4f40d2fbb830e28969b31b8a1673e) commit 8ef2cc11008ef86f4dfcbc267c797bf8ee265455 Author: Sumit Bose Date: Fri Jun 29 17:49:50 2018 +0200 sysdb: extract sysdb_ldb_msg_attr_to_certmap_info() call Related to https://pagure.io/SSSD/sssd/issue/3500 Reviewed-by: Jakub Hrozek (cherry picked from commit 7c619ae08f05a7595d15cf11b64461a7d19cfaa7) --- Makefile.am | 2 + configure.ac | 1 + contrib/sssd.spec.in | 1 + src/confdb/confdb.c | 158 +++++++++++++ src/confdb/confdb.h | 23 ++ src/config/cfg_rules.ini | 10 + src/db/sysdb.h | 5 + src/db/sysdb_certmap.c | 223 +++++++++++------- src/external/cwrap.m4 | 5 + src/external/intgcheck.m4 | 1 + src/external/test_ca.m4 | 2 +- src/lib/certmap/sss_cert_content_crypto.c | 22 +- src/lib/certmap/sss_cert_content_nss.c | 21 +- src/man/sss-certmap.5.xml | 9 + src/man/sssd.conf.5.xml | 149 ++++++++++++ src/providers/ad/ad_init.c | 16 ++ src/providers/files/files_auth.c | 69 ++++++ src/providers/files/files_certmap.c | 186 +++++++++++++++ src/providers/files/files_id.c | 20 ++ src/providers/files/files_init.c | 29 +++ src/providers/files/files_private.h | 17 ++ src/providers/ldap/ldap_init.c | 16 ++ src/responder/common/responder_dp.c | 20 +- src/responder/pam/pamsrv.h | 2 +- src/responder/pam/pamsrv_cmd.c | 6 +- src/responder/pam/pamsrv_p11.c | 77 +++--- src/tests/cmocka/test_certmap.c | 45 ++++ src/tests/cmocka/test_config_check.c | 16 +- src/tests/intg/test_pam_responder.py | 109 ++++++++- src/tests/test_CA/Makefile.am | 24 +- src/tests/test_CA/SSSD_test_cert_0004.config | 11 + src/tests/test_CA/SSSD_test_cert_key_0004.pem | 28 +++ 32 files changed, 1170 insertions(+), 153 deletions(-) create mode 100644 src/providers/files/files_auth.c create mode 100644 src/providers/files/files_certmap.c create mode 100644 src/tests/test_CA/SSSD_test_cert_0004.config create mode 100644 src/tests/test_CA/SSSD_test_cert_key_0004.pem diff --git a/Makefile.am b/Makefile.am index 718041634..77f5faf6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4094,6 +4094,8 @@ libsss_proxy_la_LDFLAGS = \ libsss_files_la_SOURCES = \ src/providers/files/files_init.c \ src/providers/files/files_id.c \ + src/providers/files/files_auth.c \ + src/providers/files/files_certmap.c \ src/providers/files/files_ops.c \ src/util/inotify.c \ $(NULL) diff --git a/configure.ac b/configure.ac index 5154918b1..89abddef4 100644 --- a/configure.ac +++ b/configure.ac @@ -488,6 +488,7 @@ AM_CONDITIONAL([HAVE_CHECK], [test x$have_check != x]) AM_CHECK_CMOCKA AM_CHECK_UID_WRAPPER AM_CHECK_NSS_WRAPPER +AM_CHECK_PAM_WRAPPER AM_CHECK_TEST_CA # Check if the user wants SSSD to be compiled with systemtap probes diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index 10b5bd56c..52a77ae7a 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -236,6 +236,7 @@ BuildRequires: selinux-policy-targeted BuildRequires: libcmocka-devel >= 1.0.0 BuildRequires: uid_wrapper BuildRequires: nss_wrapper +BuildRequires: pam_wrapper # Test CA requires openssl independent if SSSD is build with NSS or openssl, # openssh is needed for ssh-keygen and NSS builds need nss-tools for certutil. diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c index e55f88e4e..97de6d3b1 100644 --- a/src/confdb/confdb.c +++ b/src/confdb/confdb.c @@ -2209,3 +2209,161 @@ done: talloc_free(tmp_ctx); return ret; } + +static errno_t certmap_local_check(struct ldb_message *msg) +{ + const char *rule_name; + const char *tmp_str; + int ret; + + rule_name = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_NAME, NULL); + if (rule_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Certficate mapping rule [%s] has no name.", + ldb_dn_get_linearized(msg->dn)); + return EINVAL; + } + + tmp_str = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_DOMAINS, NULL); + if (tmp_str != NULL) { + DEBUG(SSSDBG_CONF_SETTINGS, + "Option [%s] is ignored for local certmap rules.\n", + CONFDB_CERTMAP_DOMAINS); + } + + tmp_str = ldb_msg_find_attr_as_string(msg, CONFDB_CERTMAP_MAPRULE, NULL); + if (tmp_str != NULL) { + if (tmp_str[0] != '(' || tmp_str[strlen(tmp_str) - 1] != ')') { + DEBUG(SSSDBG_CONF_SETTINGS, + "Mapping rule must be in braces (...).\n"); + return EINVAL; + } + DEBUG(SSSDBG_TRACE_ALL, "Using [%s] mapping rule of [%s].\n", + tmp_str, ldb_dn_get_linearized(msg->dn)); + return EOK; + } + + tmp_str = talloc_asprintf(msg, "(%s)", rule_name); + if (tmp_str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + return ENOMEM; + } + ret = ldb_msg_add_string(msg, CONFDB_CERTMAP_MAPRULE, tmp_str); + if (ret != LDB_SUCCESS) { + talloc_free(discard_const(tmp_str)); + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n"); + return EIO; + } + + DEBUG(SSSDBG_TRACE_ALL, "Using [%s] as mapping rule for [%s].\n", + tmp_str, ldb_dn_get_linearized(msg->dn)); + + return EOK; +} + +static errno_t confdb_get_all_certmaps(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + struct sss_domain_info *dom, + struct certmap_info ***_certmap_list) +{ + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_dn *dn = NULL; + struct ldb_result *res = NULL; + /* The attributte order is important, because it is used in + * sysdb_ldb_msg_attr_to_certmap_info and must match + * enum certmap_info_member. */ + static const char *attrs[] = { CONFDB_CERTMAP_NAME, + CONFDB_CERTMAP_MAPRULE, + CONFDB_CERTMAP_MATCHRULE, + CONFDB_CERTMAP_PRIORITY, + CONFDB_CERTMAP_DOMAINS, + NULL}; + struct certmap_info **certmap_list = NULL; + size_t c; + int ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", dom->name, + CONFDB_CERTMAP_BASEDN); + if (dn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_ONELEVEL, + attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + + certmap_list = talloc_zero_array(tmp_ctx, struct certmap_info *, + res->count + 1); + if (certmap_list == NULL) { + ret = ENOMEM; + goto done; + } + + for (c = 0; c < res->count; c++) { + if (is_files_provider(dom)) { + ret = certmap_local_check(res->msgs[c]); + if (ret != EOK) { + DEBUG(SSSDBG_CONF_SETTINGS, + "Invalid certificate mapping [%s] for local user, " + "ignored.\n", ldb_dn_get_linearized(res->msgs[c]->dn)); + continue; + } + } + ret = sysdb_ldb_msg_attr_to_certmap_info(certmap_list, res->msgs[c], + attrs, &certmap_list[c]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_ldb_msg_attr_to_certmap_info failed.\n"); + goto done; + } + } + + *_certmap_list = talloc_steal(mem_ctx, certmap_list); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +int confdb_certmap_to_sysdb(struct confdb_ctx *cdb, + struct sss_domain_info *dom) +{ + int ret; + TALLOC_CTX *tmp_ctx; + struct certmap_info **certmap_list; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + ret = confdb_get_all_certmaps(tmp_ctx, cdb, dom, &certmap_list); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "confdb_get_all_certmaps failed.\n"); + goto done; + } + + ret = sysdb_update_certmap(dom->sysdb, certmap_list, false /* TODO */); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_certmap failed.\n"); + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index d3e71be86..b0d52ba49 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -267,6 +267,14 @@ #define CONFDB_KCM_SOCKET "socket_path" #define CONFDB_KCM_DB "ccache_storage" /* Undocumented on purpose */ +/* Certificate mapping rules */ +#define CONFDB_CERTMAP_BASEDN "cn=certmap,cn=config" +#define CONFDB_CERTMAP_NAME "cn" +#define CONFDB_CERTMAP_MAPRULE "maprule" +#define CONFDB_CERTMAP_MATCHRULE "matchrule" +#define CONFDB_CERTMAP_DOMAINS "domains" +#define CONFDB_CERTMAP_PRIORITY "priority" + /* Prompting */ #define CONFDB_PC_CONF_ENTRY "config/prompting" #define CONFDB_PC_TYPE_PASSWORD "password" @@ -681,6 +689,21 @@ int confdb_get_sub_sections(TALLOC_CTX *mem_ctx, const char *section, char ***sections, int *num_sections); + +/** + * @brief Convenience function to write the certificate mapping and matching + * rules from the configuration database to the cache of a domain + * + * @param[in] cdb The connection object to the confdb + * @param[in] dom Target domain where to rules should be written to + * + * @return 0 - Successfully retrieved the entry (or used the default) + * @return ENOMEM - There was insufficient memory to complete the operation + * @return EINVAL - Typically internal processing error + */ +int confdb_certmap_to_sysdb(struct confdb_ctx *cdb, + struct sss_domain_info *dom); + /** * @} */ diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 997ba5aec..79e366875 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -17,6 +17,7 @@ section_re = ^secrets/kcm$ section_re = ^domain/[^/\@]\+$ section_re = ^domain/[^/\@]\+/[^/\@]\+$ section_re = ^application/[^/\@]\+$ +section_re = ^certmap/[^/\@]\+/[^/\@]\+$ [rule/allowed_sssd_options] @@ -765,3 +766,12 @@ option = use_fully_qualified_names [rule/sssd_checks] validator = sssd_checks + +[rule/allowed_certmap_options] +validator = ini_allowed_options +section_re = ^certmap/[^/\@]\+/[^/\@]\+$ + +option = matchrule +option = maprule +option = priority +option = domains diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 018ec22ab..a2bc8ed3b 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -737,6 +737,11 @@ errno_t sysdb_update_certmap(struct sysdb_ctx *sysdb, struct certmap_info **certmaps, bool user_name_hint); +errno_t sysdb_ldb_msg_attr_to_certmap_info(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + const char **attr_map, + struct certmap_info **certmap); + errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct certmap_info ***certmaps, bool *user_name_hint); diff --git a/src/db/sysdb_certmap.c b/src/db/sysdb_certmap.c index eda20f5a7..4cc5b5b41 100644 --- a/src/db/sysdb_certmap.c +++ b/src/db/sysdb_certmap.c @@ -22,6 +22,7 @@ #include "util/util.h" #include "db/sysdb_private.h" +#include "lib/certmap/sss_certmap.h" static errno_t sysdb_create_certmap_container(struct sysdb_ctx *sysdb, bool user_name_hint) @@ -153,7 +154,7 @@ static errno_t sysdb_certmap_add(struct sysdb_ctx *sysdb, } } - if (certmap->domains != NULL) { + if (certmap->domains != NULL && certmap->domains[0] != NULL) { for (c = 0; certmap->domains[c] != NULL; c++); el = talloc_zero(tmp_ctx, struct ldb_message_element); if (el == NULL) { @@ -285,28 +286,151 @@ done: return ret; } +enum certmap_info_member { + SSS_CMIM_NAME = 0, + SSS_CMIM_MAPPING_RULE, + SSS_CMIM_MATCHING_RULE, + SSS_CMIM_PRIORITY, + SSS_CMIM_DOMAINS, + + SSS_CMIM_SENTINEL +}; + +errno_t sysdb_ldb_msg_attr_to_certmap_info(TALLOC_CTX *mem_ctx, + struct ldb_message *msg, + const char **attr_map, + struct certmap_info **certmap) +{ + int ret; + size_t d; + size_t num_values; + struct certmap_info *map = NULL; + const char *tmp_str; + uint64_t tmp_uint; + struct ldb_message_element *tmp_el; + + if (msg == NULL || attr_map == NULL || certmap == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid input.\n"); + return EINVAL; + } + + for (d = 0; d < SSS_CMIM_SENTINEL; d++) { + if (attr_map[d] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid attribute map"); + return EINVAL; + } + } + + map = talloc_zero(mem_ctx, struct certmap_info); + if (map == NULL) { + return ENOMEM; + } + + tmp_str = ldb_msg_find_attr_as_string(msg, attr_map[SSS_CMIM_NAME], NULL); + if (tmp_str == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "The object [%s] doesn't have a name.\n", + ldb_dn_get_linearized(msg->dn)); + ret = EINVAL; + goto done; + } + + map->name = talloc_strdup(map, tmp_str); + if (map->name == NULL) { + ret = ENOMEM; + goto done; + } + + tmp_str = ldb_msg_find_attr_as_string(msg, attr_map[SSS_CMIM_MAPPING_RULE], + NULL); + if (tmp_str != NULL) { + map->map_rule = talloc_strdup(map, tmp_str); + if (map->map_rule == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + tmp_str = ldb_msg_find_attr_as_string(msg, attr_map[SSS_CMIM_MATCHING_RULE], + NULL); + if (tmp_str != NULL) { + map->match_rule = talloc_strdup(map, tmp_str); + if (map->match_rule == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + tmp_uint = ldb_msg_find_attr_as_uint64(msg, attr_map[SSS_CMIM_PRIORITY], + (uint64_t) -1); + if (tmp_uint != (uint64_t) -1) { + if (tmp_uint > UINT32_MAX) { + DEBUG(SSSDBG_OP_FAILURE, "Priority value [%lu] too large.\n", + (unsigned long) tmp_uint); + ret = EINVAL; + goto done; + } + + map->priority = (uint32_t) tmp_uint; + } else { + map->priority = SSS_CERTMAP_MIN_PRIO; + } + + tmp_el = ldb_msg_find_element(msg, attr_map[SSS_CMIM_DOMAINS]); + if (tmp_el != NULL) { + num_values = tmp_el->num_values; + } else { + num_values = 0; + } + + map->domains = talloc_zero_array(map, const char *, num_values + 1); + if (map->domains == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); + ret = ENOMEM; + goto done; + } + + for (d = 0; d < num_values; d++) { + map->domains[d] = talloc_strndup(map->domains, + (char *) tmp_el->values[d].data, + tmp_el->values[d].length); + if (map->domains[d] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + *certmap = map; + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(map); + } + + return ret; +} + errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, struct certmap_info ***certmaps, bool *user_name_hint) { size_t c; - size_t d; struct ldb_dn *container_dn = NULL; int ret; struct certmap_info **maps = NULL; TALLOC_CTX *tmp_ctx = NULL; struct ldb_result *res; - const char *tmp_str; - uint64_t tmp_uint; - struct ldb_message_element *tmp_el; const char *attrs[] = {SYSDB_NAME, - SYSDB_CERTMAP_PRIORITY, - SYSDB_CERTMAP_MATCHING_RULE, SYSDB_CERTMAP_MAPPING_RULE, + SYSDB_CERTMAP_MATCHING_RULE, + SYSDB_CERTMAP_PRIORITY, SYSDB_CERTMAP_DOMAINS, NULL}; const char *config_attrs[] = {SYSDB_CERTMAP_USER_NAME_HINT, NULL}; - size_t num_values; bool hint = false; tmp_ctx = talloc_new(NULL); @@ -355,86 +479,13 @@ errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, } for (c = 0; c < res->count; c++) { - maps[c] = talloc_zero(maps, struct certmap_info); - if (maps[c] == NULL) { - ret = ENOMEM; - goto done; - } - tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_NAME, NULL); - if (tmp_str == NULL) { - DEBUG(SSSDBG_MINOR_FAILURE, "The object [%s] doesn't have a name.\n", - ldb_dn_get_linearized(res->msgs[c]->dn)); - ret = EINVAL; - goto done; - } - - maps[c]->name = talloc_strdup(maps, tmp_str); - if (maps[c]->name == NULL) { - ret = ENOMEM; - goto done; - } - - tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], - SYSDB_CERTMAP_MAPPING_RULE, NULL); - if (tmp_str != NULL) { - maps[c]->map_rule = talloc_strdup(maps, tmp_str); - if (maps[c]->map_rule == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); - ret = ENOMEM; - goto done; - } - } - - tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], - SYSDB_CERTMAP_MATCHING_RULE, NULL); - if (tmp_str != NULL) { - maps[c]->match_rule = talloc_strdup(maps, tmp_str); - if (maps[c]->match_rule == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); - ret = ENOMEM; - goto done; - } - } - - tmp_uint = ldb_msg_find_attr_as_uint64(res->msgs[c], - SYSDB_CERTMAP_PRIORITY, - (uint64_t) -1); - if (tmp_uint != (uint64_t) -1) { - if (tmp_uint > UINT32_MAX) { - DEBUG(SSSDBG_OP_FAILURE, "Priority value [%lu] too large.\n", - (unsigned long) tmp_uint); - ret = EINVAL; - goto done; - } - - maps[c]->priority = (uint32_t) tmp_uint; - } - - tmp_el = ldb_msg_find_element(res->msgs[c], SYSDB_CERTMAP_DOMAINS); - if (tmp_el != NULL) { - num_values = tmp_el->num_values; - } else { - num_values = 0; - } - - maps[c]->domains = talloc_zero_array(maps[c], const char *, - num_values + 1); - if (maps[c]->domains == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); - ret = ENOMEM; + ret = sysdb_ldb_msg_attr_to_certmap_info(maps, res->msgs[c], attrs, + &maps[c]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_ldb_msg_attr_to_certmap_info failed.\n"); goto done; } - - for (d = 0; d < num_values; d++) { - maps[c]->domains[d] = talloc_strndup(maps[c]->domains, - (char *) tmp_el->values[d].data, - tmp_el->values[d].length); - if (maps[c]->domains[d] == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); - ret = ENOMEM; - goto done; - } - } } ret = EOK; diff --git a/src/external/cwrap.m4 b/src/external/cwrap.m4 index b8489cc76..6e3487c13 100644 --- a/src/external/cwrap.m4 +++ b/src/external/cwrap.m4 @@ -28,3 +28,8 @@ AC_DEFUN([AM_CHECK_NSS_WRAPPER], [ AM_CHECK_WRAPPER(nss_wrapper, HAVE_NSS_WRAPPER) ]) + +AC_DEFUN([AM_CHECK_PAM_WRAPPER], +[ + AM_CHECK_WRAPPER(pam_wrapper, HAVE_PAM_WRAPPER) +]) diff --git a/src/external/intgcheck.m4 b/src/external/intgcheck.m4 index ef81ec718..d73c5dfb1 100644 --- a/src/external/intgcheck.m4 +++ b/src/external/intgcheck.m4 @@ -75,6 +75,7 @@ AC_DEFUN([SSS_ENABLE_INTGCHECK_REQS], [ if test x"$enable_intgcheck_reqs" = xyes; then SSS_INTGCHECK_REQ([HAVE_UID_WRAPPER], [uid_wrapper]) SSS_INTGCHECK_REQ([HAVE_NSS_WRAPPER], [nss_wrapper]) + SSS_INTGCHECK_REQ([HAVE_PAM_WRAPPER], [pam_wrapper]) SSS_INTGCHECK_REQ([HAVE_SLAPD], [slapd]) SSS_INTGCHECK_REQ([HAVE_LDAPMODIFY], [ldapmodify]) SSS_INTGCHECK_REQ([HAVE_FAKEROOT], [fakeroot]) diff --git a/src/external/test_ca.m4 b/src/external/test_ca.m4 index 2cdb3c750..bb4872698 100644 --- a/src/external/test_ca.m4 +++ b/src/external/test_ca.m4 @@ -58,7 +58,7 @@ AC_DEFUN([AM_CHECK_TEST_CA], AC_MSG_NOTICE([Could not find p11tool]) fi - AM_CONDITIONAL([BUILD_TEST_CA], [test -x "$OPENSSL" -a -x "$SSH_KEYGEN" -a -x "$SOFTHSM2_PATH" -a -x "$SOFTHSM2_UTIL" -a -x "$P11TOOL"]) + AM_CONDITIONAL([BUILD_TEST_CA], [test -x "$OPENSSL" -a -x "$SSH_KEYGEN" -a -r "$SOFTHSM2_PATH" -a -x "$SOFTHSM2_UTIL" -a -x "$P11TOOL"]) fi AM_COND_IF([BUILD_TEST_CA], diff --git a/src/lib/certmap/sss_cert_content_crypto.c b/src/lib/certmap/sss_cert_content_crypto.c index ee9aec208..b01830aec 100644 --- a/src/lib/certmap/sss_cert_content_crypto.c +++ b/src/lib/certmap/sss_cert_content_crypto.c @@ -771,11 +771,25 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx, ret = EIO; goto done; } - if (!(X509_get_extension_flags(cert) & EXFLAG_KUSAGE)) { - ret = EINVAL; - goto done; + if ((X509_get_extension_flags(cert) & EXFLAG_KUSAGE)) { + cont->key_usage = X509_get_key_usage(cert); + } else { + /* According to X.509 https://www.itu.int/rec/T-REC-X.509-201610-I + * section 13.3.2 "Certificate match" "keyUsage matches if all of the + * bits set in the presented value are also set in the key usage + * extension in the stored attribute value, or if there is no key + * usage extension in the stored attribute value;". So we set all bits + * in our key_usage to make sure everything matches is keyUsage is not + * set in the certificate. + * + * Please note that NSS currently + * (https://bugzilla.mozilla.org/show_bug.cgi?id=549952) does not + * support 'decipherOnly' and will only use 0xff in this case. To have + * a consistent behavior with both libraries we will use UINT32_MAX + * for NSS as well. Since comparisons should be always done with a + * bit-wise and-operation the difference should not matter. */ + cont->key_usage = UINT32_MAX; } - cont->key_usage = X509_get_key_usage(cert); ret = get_extended_key_usage_oids(cont, cert, &(cont->extended_key_usage_oids)); diff --git a/src/lib/certmap/sss_cert_content_nss.c b/src/lib/certmap/sss_cert_content_nss.c index ed7ce24c4..cef1efc26 100644 --- a/src/lib/certmap/sss_cert_content_nss.c +++ b/src/lib/certmap/sss_cert_content_nss.c @@ -887,8 +887,25 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx, goto done; } - - cont->key_usage = cert->keyUsage; + /* According to X.509 https://www.itu.int/rec/T-REC-X.509-201610-I + * section 13.3.2 "Certificate match" "keyUsage matches if all of the + * bits set in the presented value are also set in the key usage + * extension in the stored attribute value, or if there is no key + * usage extension in the stored attribute value;". So we set all bits + * in our key_usage to make sure everything matches is keyUsage is not + * set in the certificate. + * + * Please note that NSS currently + * (https://bugzilla.mozilla.org/show_bug.cgi?id=549952) does not + * support 'decipherOnly' and will only use 0xff in this case. To have + * a consistent behavior with both libraries we will use UINT32_MAX + * for NSS as well. Since comparisons should be always done with a + * bit-wise and-operation the difference should not matter. */ + if (cert->keyUsagePresent == PR_FALSE) { + cont->key_usage = UINT32_MAX; + } else { + cont->key_usage = cert->keyUsage; + } ret = get_extended_key_usage_oids(cont, cert, &(cont->extended_key_usage_oids)); diff --git a/src/man/sss-certmap.5.xml b/src/man/sss-certmap.5.xml index db258d14a..10343625e 100644 --- a/src/man/sss-certmap.5.xml +++ b/src/man/sss-certmap.5.xml @@ -92,6 +92,15 @@ Example: <SUBJECT>.*,DC=MY,DC=DOMAIN + + Please note that the characters "^.[$()|*+?{\" have a + special meaning in regular expressions and must be + escaped with the help of the '\' character so that they + are matched as ordinary characters. + + + Example: <SUBJECT>^CN=.* \(Admin\),DC=MY,DC=DOMAIN$ + diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 0e1a97a31..8adbb8de9 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -3452,6 +3452,135 @@ ldap_user_extra_attrs = phone:telephoneNumber + + CERTIFICATE MAPPING SECTION + + To allow authentication with Smartcards and certificates SSSD must + be able to map certificates to users. This can be done by adding the + full certificate to the LDAP object of the user or to a local + override. While using the full certificate is required to use the + Smartcard authentication feature of SSH (see + + sss_ssh_authorizedkeys + 8 + + for details) it might be cumbersome or not even possible to do this + for the general case where local services use PAM for + authentication. + + + To make the mapping more flexible mapping and matching rules were + added to SSSD (see + + sss-certmap + 5 + + for details). + + + A mapping and matching rule can be added to the SSSD configuration + in a section on its own with a name like + [certmap/DOMAIN_NAME/RULE_NAME]. + In this section the following options are allowed: + + + + matchrule (string) + + + Only certificates from the Smartcard which matches this + rule will be processed, all others are ignored. + + + Default: KRB5:<EKU>clientAuth, i.e. only + certificates which have the Extended Key Usage + clientAuth + + + + + maprule (string) + + + Defines how the user is found for a given certificate. + + + Default: + + + LDAP:(userCertificate;binary={cert!bin}) + for LDAP based providers like + ldap, AD or + ipa. + + + The RULE_NAME for the files + provider which tries to find a user with the + same name. + + + + + + + domains (string) + + + Comma separated list of domain names the rule should be + applied. By default a rule is only valid in the domain + configured in sssd.conf. If the provider supports + subdomains this option can be used to add the rule to + subdomains as well. + + + Default: the configured domain in sssd.conf + + + + + priority (integer) + + + Unsigned integer value defining the priority of the + rule. The higher the number the lower the priority. + 0 stands for the highest priority while + 4294967295 is the lowest. + + + Default: the lowest priority + + + + + + To make the configuration simple and reduce the amount of + configuration options the files provider has some + special properties: + + + + if maprule is not set the RULE_NAME name is assumed to + be the name of the matching user + + + + + if a maprule is used both a single user name or a + template like + {subject_rfc822_name.short_name} must + be in braces like e.g. (username) or + ({subject_rfc822_name.short_name}) + + + + + the domains option is ignored + + + + + + EXAMPLES @@ -3494,6 +3623,26 @@ enumerate = False [domain/ipa.com/child.ad.com] use_fully_qualified_names = false + + + + 3. The following example shows the configuration for two certificate + mapping rules. The first is valid for the configured domain + my.domain and additionally for the subdomains + your.domain and uses the full certificate in the + search filter. The second example is valid for the domain + files where it is assumed the files provider is used + for this domain and contains a matching rule for the local user + myname. + +[certmap/my.domain/rule_name] +matchrule = <ISSUER>^CN=My-CA,DC=MY,DC=DOMAIN$ +maprule = (userCertificate;binary={cert!bin}) +domains = my.domain, your.domain +priority = 10 + +[certmap/files/myname] +matchrule = <ISSUER>^CN=My-CA,DC=MY,DC=DOMAIN$<SUBJECT>^CN=User.Name,DC=MY,DC=DOMAIN$ diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index 09397852b..fb24a28e1 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -427,6 +427,22 @@ static errno_t ad_init_misc(struct be_ctx *be_ctx, return ret; } + ret = confdb_certmap_to_sysdb(be_ctx->cdb, be_ctx->domain); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialize certificate mapping rules. " + "Authentication with certificates/Smartcards might not work " + "as expected.\n"); + /* not fatal, ignored */ + } + + ret = sdap_init_certmap(sdap_id_ctx, sdap_id_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialized certificate mapping.\n"); + return ret; + } + return EOK; } diff --git a/src/providers/files/files_auth.c b/src/providers/files/files_auth.c new file mode 100644 index 000000000..b71de6971 --- /dev/null +++ b/src/providers/files/files_auth.c @@ -0,0 +1,69 @@ +/* + SSSD + + files_auth.c - PAM operations on the files provider + + Copyright (C) 2018 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 "providers/data_provider/dp.h" +#include "providers/data_provider.h" +#include "providers/files/files_private.h" +#include "util/cert.h" + +struct files_auth_ctx { + struct pam_data *pd; +}; + +struct tevent_req * +files_auth_handler_send(TALLOC_CTX *mem_ctx, + void *unused, + struct pam_data *pd, + struct dp_req_params *params) +{ + struct files_auth_ctx *state; + struct tevent_req *req; + + req = tevent_req_create(mem_ctx, &state, struct files_auth_ctx); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->pd = pd; + state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; + + tevent_req_done(req); + tevent_req_post(req, params->ev); + return req; +} + +errno_t files_auth_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data) +{ + struct files_auth_ctx *state = NULL; + + state = tevent_req_data(req, struct files_auth_ctx); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *_data = talloc_steal(mem_ctx, state->pd); + + return EOK; +} diff --git a/src/providers/files/files_certmap.c b/src/providers/files/files_certmap.c new file mode 100644 index 000000000..7d90a1fec --- /dev/null +++ b/src/providers/files/files_certmap.c @@ -0,0 +1,186 @@ +/* + SSSD + + files_init.c - Initialization of the files provider + + Copyright (C) 2018 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 "providers/files/files_private.h" +#include "util/util.h" +#include "util/cert.h" +#include "lib/certmap/sss_certmap.h" + +struct priv_sss_debug { + int level; +}; + +static void ext_debug(void *private, const char *file, long line, + const char *function, const char *format, ...) +{ + va_list ap; + struct priv_sss_debug *data = private; + int level = SSSDBG_OP_FAILURE; + + if (data != NULL) { + level = data->level; + } + + if (DEBUG_IS_SET(level)) { + va_start(ap, format); + sss_vdebug_fn(file, line, function, level, APPEND_LINE_FEED, + format, ap); + va_end(ap); + } +} + +errno_t files_init_certmap(TALLOC_CTX *mem_ctx, struct files_id_ctx *id_ctx) +{ + int ret; + bool hint; + struct certmap_info **certmap_list = NULL; + size_t c; + + ret = sysdb_get_certmap(mem_ctx, id_ctx->be->domain->sysdb, + &certmap_list, &hint); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_certmap failed.\n"); + goto done; + } + + if (certmap_list == NULL || *certmap_list == NULL) { + DEBUG(SSSDBG_TRACE_ALL, "No certmap data, nothing to do.\n"); + ret = EOK; + goto done; + } + + ret = sss_certmap_init(mem_ctx, ext_debug, NULL, &id_ctx->sss_certmap_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_init failed.\n"); + goto done; + } + + for (c = 0; certmap_list[c] != NULL; c++) { + DEBUG(SSSDBG_TRACE_ALL, "Trying to add rule [%s][%d][%s][%s].\n", + certmap_list[c]->name, + certmap_list[c]->priority, + certmap_list[c]->match_rule, + certmap_list[c]->map_rule); + + ret = sss_certmap_add_rule(id_ctx->sss_certmap_ctx, + certmap_list[c]->priority, + certmap_list[c]->match_rule, + certmap_list[c]->map_rule, + certmap_list[c]->domains); + if (ret != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sss_certmap_add_rule failed for rule [%s] " + "with error [%d][%s], skipping. " + "Please check for typos and if rule syntax is supported.\n", + certmap_list[c]->name, ret, sss_strerror(ret)); + continue; + } + } + + ret = EOK; + +done: + talloc_free(certmap_list); + + return ret; +} + +errno_t files_map_cert_to_user(struct files_id_ctx *id_ctx, + struct dp_id_data *data) +{ + errno_t ret; + char *filter; + char *user; + struct ldb_message *msg = NULL; + struct sysdb_attrs *attrs = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + ret = sss_cert_derb64_to_ldap_filter(tmp_ctx, data->filter_value, "", + id_ctx->sss_certmap_ctx, + id_ctx->domain, &filter); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_cert_derb64_to_ldap_filter failed.\n"); + goto done; + } + if (filter == NULL || filter[0] != '(' + || filter[strlen(filter) - 1] != ')') { + DEBUG(SSSDBG_OP_FAILURE, + "sss_cert_derb64_to_ldap_filter returned bad filter [%s].\n", + filter); + ret = EINVAL; + goto done; + } + + filter[strlen(filter) - 1] = '\0'; + user = sss_create_internal_fqname(tmp_ctx, &filter[1], + id_ctx->domain->name); + if (user == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_create_internal_fqname failed.\n"); + ret = ENOMEM; + goto done; + } + DEBUG(SSSDBG_TRACE_ALL, "Certificate mapped to user: [%s].\n", user); + + ret = sysdb_search_user_by_name(tmp_ctx, id_ctx->domain, user, NULL, &msg); + if (ret == EOK) { + attrs = sysdb_new_attrs(tmp_ctx); + if (attrs == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_add_base64_blob(attrs, SYSDB_USER_MAPPED_CERT, + data->filter_value); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_base64_blob failed.\n"); + goto done; + } + + ret = sysdb_set_entry_attr(id_ctx->domain->sysdb, msg->dn, attrs, + SYSDB_MOD_ADD); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n"); + goto done; + } + } else if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_ALL, "Mapped user [%s] not found.\n", user); + ret = EOK; + goto done; + } else { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_name failed.\n"); + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} diff --git a/src/providers/files/files_id.c b/src/providers/files/files_id.c index 41314c66b..f6f8c7311 100644 --- a/src/providers/files/files_id.c +++ b/src/providers/files/files_id.c @@ -87,6 +87,26 @@ files_account_info_handler_send(TALLOC_CTX *mem_ctx, ? true \ : false; break; + case BE_REQ_BY_CERT: + if (data->filter_type != BE_FILTER_CERT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected filter type for lookup by cert: %d\n", + data->filter_type); + ret = EINVAL; + goto immediate; + } + if (id_ctx->sss_certmap_ctx == NULL) { + DEBUG(SSSDBG_TRACE_ALL, "Certificate mapping not configured.\n"); + ret = EOK; + goto immediate; + } + + ret = files_map_cert_to_user(id_ctx, data); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "files_map_cert_to_user failed"); + } + goto immediate; + break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected entry type: %d\n", data->entry_type & BE_REQ_TYPE_MASK); diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c index 746c04af1..1ce4bcf27 100644 --- a/src/providers/files/files_init.c +++ b/src/providers/files/files_init.c @@ -189,6 +189,23 @@ int sssm_files_init(TALLOC_CTX *mem_ctx, goto done; } + ret = confdb_certmap_to_sysdb(be_ctx->cdb, be_ctx->domain); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialize certificate mapping rules. " + "Authentication with certificates/Smartcards might not work " + "as expected.\n"); + /* not fatal, ignored */ + } else { + ret = files_init_certmap(ctx, ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "files_init_certmap failed. " + "Authentication with certificates/Smartcards might not work " + "as expected.\n"); + /* not fatal, ignored */ + } + } + *_module_data = ctx; ret = EOK; done: @@ -224,3 +241,15 @@ int sssm_files_id_init(TALLOC_CTX *mem_ctx, return EOK; } + +int sssm_files_auth_init(TALLOC_CTX *mem_ctx, + struct be_ctx *be_ctx, + void *module_data, + struct dp_method *dp_methods) +{ + dp_set_method(dp_methods, DPM_AUTH_HANDLER, + files_auth_handler_send, files_auth_handler_recv, NULL, void, + struct pam_data, struct pam_data *); + + return EOK; +} diff --git a/src/providers/files/files_private.h b/src/providers/files/files_private.h index f44e6d458..fd1781930 100644 --- a/src/providers/files/files_private.h +++ b/src/providers/files/files_private.h @@ -38,6 +38,7 @@ struct files_id_ctx { struct be_ctx *be; struct sss_domain_info *domain; struct files_ctx *fctx; + struct sss_certmap_ctx *sss_certmap_ctx; const char **passwd_files; const char **group_files; @@ -71,4 +72,20 @@ errno_t files_account_info_handler_recv(TALLOC_CTX *mem_ctx, void files_account_info_finished(struct files_id_ctx *id_ctx, int req_type, errno_t ret); + +/* files_auth.c */ +struct tevent_req *files_auth_handler_send(TALLOC_CTX *mem_ctx, + void *unused, + struct pam_data *pd, + struct dp_req_params *params); + +errno_t files_auth_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data); + +/* files_certmap.c */ +errno_t files_init_certmap(TALLOC_CTX *mem_ctx, struct files_id_ctx *id_ctx); + +errno_t files_map_cert_to_user(struct files_id_ctx *id_ctx, + struct dp_id_data *data); #endif /* __FILES_PRIVATE_H_ */ diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index 3714d5d79..7998cc8ff 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -439,6 +439,22 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx, "[%d]: %s\n", ret, sss_strerror(ret)); } + ret = confdb_certmap_to_sysdb(be_ctx->cdb, be_ctx->domain); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialize certificate mapping rules. " + "Authentication with certificates/Smartcards might not work " + "as expected.\n"); + /* not fatal, ignored */ + } + + ret = sdap_init_certmap(id_ctx, id_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to initialized certificate mapping.\n"); + return ret; + } + return EOK; } diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c index 208c415ac..a49b31528 100644 --- a/src/responder/common/responder_dp.c +++ b/src/responder/common/responder_dp.c @@ -598,15 +598,17 @@ static int sss_dp_account_files_params(struct sss_domain_info *dom, enum sss_dp_acct_type *_type_out, const char **_opt_name_out) { - if (sss_domain_get_state(dom) != DOM_INCONSISTENT) { + if (type_in != SSS_DP_CERT) { + if (sss_domain_get_state(dom) != DOM_INCONSISTENT) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "The entries in the files domain are up-to-date\n"); + return EOK; + } + DEBUG(SSSDBG_TRACE_INTERNAL, - "The entries in the files domain are up-to-date\n"); - return EOK; + "Domain files is not consistent, issuing update\n"); } - DEBUG(SSSDBG_TRACE_INTERNAL, - "Domain files is not consistent, issuing update\n"); - switch(type_in) { case SSS_DP_USER: case SSS_DP_GROUP: @@ -620,12 +622,16 @@ static int sss_dp_account_files_params(struct sss_domain_info *dom, *_type_out = type_in; *_opt_name_out = DP_REQ_OPT_FILES_INITGR; return EAGAIN; + case SSS_DP_CERT: + /* Let the backend handle certificate mapping for local users */ + *_type_out = type_in; + *_opt_name_out = opt_name_in; + return EAGAIN; /* These are not handled by the files provider, just fall back */ case SSS_DP_NETGR: case SSS_DP_SERVICES: case SSS_DP_SECID: case SSS_DP_USER_AND_GROUP: - case SSS_DP_CERT: case SSS_DP_WILDCARD_USER: case SSS_DP_WILDCARD_GROUP: return EOK; diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h index 319362a95..ccb2037b1 100644 --- a/src/responder/pam/pamsrv.h +++ b/src/responder/pam/pamsrv.h @@ -123,7 +123,7 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username, bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd); errno_t p11_refresh_certmap_ctx(struct pam_ctx *pctx, - struct certmap_info **certmap_list); + struct sss_domain_info *domains); errno_t pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain, diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index 00302be75..139f4260e 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -1461,7 +1461,9 @@ static void pam_forwarder_cert_cb(struct tevent_req *req) if (pd->cmd == SSS_PAM_AUTHENTICATE) { DEBUG(SSSDBG_CRIT_FAILURE, "No certificate returned, authentication failed.\n"); - ret = ENOENT; + preq->pd->pam_status = PAM_AUTH_ERR; + pam_reply(preq); + return; } else { ret = pam_check_user_search(preq); } @@ -1762,7 +1764,7 @@ static void pam_forwarder_cb(struct tevent_req *req) goto done; } - ret = p11_refresh_certmap_ctx(pctx, pctx->rctx->domains->certmaps); + ret = p11_refresh_certmap_ctx(pctx, pctx->rctx->domains); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "p11_refresh_certmap_ctx failed, " diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c index c7e57be17..c58a8bedd 100644 --- a/src/responder/pam/pamsrv_p11.c +++ b/src/responder/pam/pamsrv_p11.c @@ -141,11 +141,14 @@ static void ext_debug(void *private, const char *file, long line, } errno_t p11_refresh_certmap_ctx(struct pam_ctx *pctx, - struct certmap_info **certmap_list) + struct sss_domain_info *domains) { int ret; struct sss_certmap_ctx *sss_certmap_ctx = NULL; size_t c; + struct sss_domain_info *dom; + bool certmap_found = false; + struct certmap_info **certmap_list; ret = sss_certmap_init(pctx, ext_debug, NULL, &sss_certmap_ctx); if (ret != EOK) { @@ -153,7 +156,15 @@ errno_t p11_refresh_certmap_ctx(struct pam_ctx *pctx, goto done; } - if (certmap_list == NULL || *certmap_list == NULL) { + DLIST_FOR_EACH(dom, domains) { + certmap_list = dom->certmaps; + if (certmap_list != NULL && *certmap_list != NULL) { + certmap_found = true; + break; + } + } + + if (!certmap_found) { /* Try to add default matching rule */ ret = sss_certmap_add_rule(sss_certmap_ctx, SSS_CERTMAP_MIN_PRIO, CERT_AUTH_DEFAULT_MATCHING_RULE, NULL, NULL); @@ -165,24 +176,32 @@ errno_t p11_refresh_certmap_ctx(struct pam_ctx *pctx, goto done; } - for (c = 0; certmap_list[c] != NULL; c++) { - DEBUG(SSSDBG_TRACE_ALL, - "Trying to add rule [%s][%d][%s][%s].\n", - certmap_list[c]->name, certmap_list[c]->priority, - certmap_list[c]->match_rule, certmap_list[c]->map_rule); - - ret = sss_certmap_add_rule(sss_certmap_ctx, certmap_list[c]->priority, - certmap_list[c]->match_rule, - certmap_list[c]->map_rule, - certmap_list[c]->domains); - if (ret != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sss_certmap_add_rule failed for rule [%s] " - "with error [%d][%s], skipping. " - "Please check for typos and if rule syntax is supported.\n", - certmap_list[c]->name, ret, sss_strerror(ret)); + DLIST_FOR_EACH(dom, domains) { + certmap_list = dom->certmaps; + if (certmap_list == NULL || *certmap_list == NULL) { continue; } + + for (c = 0; certmap_list[c] != NULL; c++) { + DEBUG(SSSDBG_TRACE_ALL, + "Trying to add rule [%s][%d][%s][%s].\n", + certmap_list[c]->name, certmap_list[c]->priority, + certmap_list[c]->match_rule, certmap_list[c]->map_rule); + + ret = sss_certmap_add_rule(sss_certmap_ctx, + certmap_list[c]->priority, + certmap_list[c]->match_rule, + certmap_list[c]->map_rule, + certmap_list[c]->domains); + if (ret != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sss_certmap_add_rule failed for rule [%s] " + "with error [%d][%s], skipping. " + "Please check for typos and if rule syntax is supported.\n", + certmap_list[c]->name, ret, sss_strerror(ret)); + continue; + } + } } ret = EOK; @@ -203,19 +222,21 @@ errno_t p11_child_init(struct pam_ctx *pctx) int ret; struct certmap_info **certmaps; bool user_name_hint; - struct sss_domain_info *dom = pctx->rctx->domains; + struct sss_domain_info *dom; - ret = sysdb_get_certmap(dom, dom->sysdb, &certmaps, &user_name_hint); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_certmap failed.\n"); - return ret; - } + DLIST_FOR_EACH(dom, pctx->rctx->domains) { + ret = sysdb_get_certmap(dom, dom->sysdb, &certmaps, &user_name_hint); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_certmap failed.\n"); + return ret; + } - dom->user_name_hint = user_name_hint; - talloc_free(dom->certmaps); - dom->certmaps = certmaps; + dom->user_name_hint = user_name_hint; + talloc_free(dom->certmaps); + dom->certmaps = certmaps; + } - ret = p11_refresh_certmap_ctx(pctx, dom->certmaps); + ret = p11_refresh_certmap_ctx(pctx, pctx->rctx->domains); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "p11_refresh_certmap_ctx failed.\n"); return ret; diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c index 3091e1abe..c882202a0 100644 --- a/src/tests/cmocka/test_certmap.c +++ b/src/tests/cmocka/test_certmap.c @@ -46,8 +46,10 @@ #ifdef HAVE_TEST_CA #include "tests/test_CA/SSSD_test_cert_x509_0003.h" +#include "tests/test_CA/SSSD_test_cert_x509_0004.h" #else #define SSSD_TEST_CERT_0003 "" +#define SSSD_TEST_CERT_0004 "" #endif struct priv_sss_debug { @@ -960,6 +962,48 @@ void test_sss_cert_get_content_test_cert_0003(void **state) talloc_free(content); } +void test_sss_cert_get_content_test_cert_0004(void **state) +{ + int ret; + uint8_t *der; + size_t der_size; + struct sss_cert_content *content; + + der = sss_base64_decode(NULL, SSSD_TEST_CERT_0004, &der_size); + assert_non_null(der); + + ret = sss_cert_get_content(NULL, der, der_size, &content); + assert_int_equal(ret, 0); + assert_non_null(content); + assert_non_null(content->issuer_str); + assert_string_equal(content->issuer_str, + "CN=SSSD test CA,OU=SSSD test,O=SSSD"); + + assert_non_null(content->issuer_rdn_list); + assert_string_equal(content->issuer_rdn_list[0], "O=SSSD"); + assert_string_equal(content->issuer_rdn_list[1], "OU=SSSD test"); + assert_string_equal(content->issuer_rdn_list[2], "CN=SSSD test CA"); + assert_null(content->issuer_rdn_list[3]); + + assert_non_null(content->subject_str); + assert_string_equal(content->subject_str, + "CN=SSSD test cert 0004,OU=SSSD test,O=SSSD"); + + assert_non_null(content->subject_rdn_list); + assert_string_equal(content->issuer_rdn_list[0], "O=SSSD"); + assert_string_equal(content->issuer_rdn_list[1], "OU=SSSD test"); + assert_string_equal(content->subject_rdn_list[2], "CN=SSSD test cert 0004"); + assert_null(content->subject_rdn_list[3]); + + assert_int_equal(content->key_usage, UINT32_MAX); + + assert_non_null(content->extended_key_usage_oids); + assert_null(content->extended_key_usage_oids[0]); + + assert_null(content->san_list); + + talloc_free(content); +} static void test_sss_certmap_match_cert(void **state) { @@ -1572,6 +1616,7 @@ int main(int argc, const char *argv[]) cmocka_unit_test(test_sss_cert_get_content_2), #ifdef HAVE_TEST_CA cmocka_unit_test(test_sss_cert_get_content_test_cert_0003), + cmocka_unit_test(test_sss_cert_get_content_test_cert_0004), #endif cmocka_unit_test(test_sss_certmap_match_cert), cmocka_unit_test(test_sss_certmap_add_mapping_rule), diff --git a/src/tests/cmocka/test_config_check.c b/src/tests/cmocka/test_config_check.c index a2958de63..f1fdbc8eb 100644 --- a/src/tests/cmocka/test_config_check.c +++ b/src/tests/cmocka/test_config_check.c @@ -213,6 +213,18 @@ void config_check_test_bad_subdom_option_name(void **state) config_check_test_common(cfg_str, 1, expected_errors); } +void config_check_test_bad_certmap_option_name(void **state) +{ + char cfg_str[] = "[certmap/files/testuser]\n" + "debug_level = 10\n"; + const char *expected_errors[] = { + "[rule/allowed_certmap_options]: Attribute 'debug_level' is not " + "allowed in section 'certmap/files/testuser'. Check for typos.", + }; + + config_check_test_common(cfg_str, 1, expected_errors); +} + void config_check_test_good_sections(void **state) { char cfg_str[] = "[sssd]\n" @@ -225,7 +237,8 @@ void config_check_test_good_sections(void **state) "[secrets/users/1000]\n" "[ssh]\n" "[ifp]\n" - "[pac]\n"; + "[pac]\n" + "[certmap/files/testuser]\n"; const char *expected_errors[] = { NULL }; config_check_test_common(cfg_str, 0, expected_errors); @@ -272,6 +285,7 @@ int main(int argc, const char *argv[]) cmocka_unit_test(config_check_test_bad_ifp_option_name), cmocka_unit_test(config_check_test_bad_appdomain_option_name), cmocka_unit_test(config_check_test_bad_subdom_option_name), + cmocka_unit_test(config_check_test_bad_certmap_option_name), cmocka_unit_test(config_check_test_good_sections), cmocka_unit_test(config_check_test_inherit_from_in_normal_dom), cmocka_unit_test(config_check_test_inherit_from_in_app_dom), diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py index 7e5828dde..e97bd409b 100644 --- a/src/tests/intg/test_pam_responder.py +++ b/src/tests/intg/test_pam_responder.py @@ -27,12 +27,9 @@ import signal import errno import subprocess import time -import pytest - -import config import shutil -from util import unindent +import config import intg.ds_openldap import pytest @@ -109,24 +106,35 @@ def format_basic_conf(ldap_conn): """).format(**locals()) -def format_pam_cert_auth_conf(): +USER1 = dict(name='user1', passwd='x', uid=10001, gid=20001, + gecos='User for tests', + dir='/home/user1', + shell='/bin/bash') + + +def format_pam_cert_auth_conf(config): """Format a basic SSSD configuration""" return unindent("""\ [sssd] + debug_level = 10 domains = auth_only - services = pam + services = pam, nss [nss] + debug_level = 10 [pam] pam_cert_auth = True + pam_p11_allowed_services = +pam_sss_service + pam_cert_db_path = {config.PAM_CERT_DB_PATH} debug_level = 10 [domain/auth_only] - id_provider = ldap - auth_provider = ldap - chpass_provider = ldap - access_provider = ldap + debug_level = 10 + id_provider = files + + [certmap/auth_only/user1] + matchrule = .*CN=SSSD test cert 0001.* """).format(**locals()) @@ -193,12 +201,42 @@ def create_sssd_fixture(request): request.addfinalizer(cleanup_sssd_process) +def create_nssdb(): + os.mkdir(config.SYSCONFDIR + "/pki") + os.mkdir(config.SYSCONFDIR + "/pki/nssdb") + if subprocess.call(["certutil", "-N", "-d", + "sql:" + config.SYSCONFDIR + "/pki/nssdb/", + "--empty-password"]) != 0: + raise Exception("certutil failed") + + pkcs11_txt = open(config.SYSCONFDIR + "/pki/nssdb/pkcs11.txt", "w") + pkcs11_txt.write("library=libsoftokn3.so\nname=soft\n" + + "parameters=configdir='sql:" + config.ABS_BUILDDIR + + "/../test_CA/p11_nssdb' " + + "dbSlotDescription='SSSD Test Slot' " + + "dbTokenDescription='SSSD Test Token' " + + "secmod='secmod.db' flags=readOnly)\n\n") + pkcs11_txt.close() + + +def cleanup_nssdb(): + shutil.rmtree(config.SYSCONFDIR + "/pki") + + +def create_nssdb_fixture(request): + create_nssdb() + request.addfinalizer(cleanup_nssdb) + + @pytest.fixture -def simple_pam_cert_auth(request): +def simple_pam_cert_auth(request, passwd_ops_setup): """Setup SSSD with pam_cert_auth=True""" - conf = format_pam_cert_auth_conf() + config.PAM_CERT_DB_PATH = os.environ['PAM_CERT_DB_PATH'] + conf = format_pam_cert_auth_conf(config) create_conf_fixture(request, conf) create_sssd_fixture(request) + create_nssdb_fixture(request) + passwd_ops_setup.useradd(**USER1) return None @@ -281,3 +319,50 @@ def env_for_sssctl(request): env_for_sssctl['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH'] return env_for_sssctl + + +def test_sc_auth_wrong_pin(simple_pam_cert_auth, env_for_sssctl): + + sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", + "--action=auth", "--service=pam_sss_service"], + universal_newlines=True, + env=env_for_sssctl, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + try: + out, err = sssctl.communicate(input="111") + except: + sssctl.kill() + out, err = sssctl.communicate() + + sssctl.stdin.close() + sssctl.stdout.close() + + if sssctl.wait() != 0: + raise Exception("sssctl failed") + + assert err.find("pam_authenticate for user [user1]: " + + "Authentication failure") != -1 + + +def test_sc_auth(simple_pam_cert_auth, env_for_sssctl): + + sssctl = subprocess.Popen(["sssctl", "user-checks", "user1", + "--action=auth", "--service=pam_sss_service"], + universal_newlines=True, + env=env_for_sssctl, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + try: + out, err = sssctl.communicate(input="123456") + except: + sssctl.kill() + out, err = sssctl.communicate() + + sssctl.stdin.close() + sssctl.stdout.close() + + if sssctl.wait() != 0: + raise Exception("sssctl failed") + + assert err.find("pam_authenticate for user [user1]: Success") != -1 diff --git a/src/tests/test_CA/Makefile.am b/src/tests/test_CA/Makefile.am index 0c7099390..19772d150 100644 --- a/src/tests/test_CA/Makefile.am +++ b/src/tests/test_CA/Makefile.am @@ -4,9 +4,11 @@ dist_noinst_DATA = \ SSSD_test_cert_0001.config \ SSSD_test_cert_0002.config \ SSSD_test_cert_0003.config \ + SSSD_test_cert_0004.config \ SSSD_test_cert_key_0001.pem \ SSSD_test_cert_key_0002.pem \ SSSD_test_cert_key_0003.pem \ + SSSD_test_cert_key_0004.pem \ $(NULL) openssl_ca_config = $(srcdir)/SSSD_test_CA.config @@ -33,14 +35,18 @@ endif ca_all: clean serial SSSD_test_CA.pem $(certs) $(certs_h) $(pubkeys) $(pubkeys_h) $(pkcs12) $(extra) $(pwdfile): - @echo "12345678" > $@ + @echo "123456" > $@ SSSD_test_CA.pem: $(openssl_ca_key) $(openssl_ca_config) serial $(OPENSSL) req -batch -config ${openssl_ca_config} -x509 -new -nodes -key $< -sha256 -days 1024 -set_serial 0 -extensions v3_ca -out $@ SSSD_test_cert_req_%.pem: $(srcdir)/SSSD_test_cert_key_%.pem $(srcdir)/SSSD_test_cert_%.config - $(OPENSSL) req -new -nodes -key $< -reqexts req_exts -config $(srcdir)/SSSD_test_cert_$*.config -out $@ + if [ $(shell grep -c req_exts $(srcdir)/SSSD_test_cert_$*.config) -eq 0 ]; then \ + $(OPENSSL) req -new -nodes -key $< -config $(srcdir)/SSSD_test_cert_$*.config -out $@ ; \ + else \ + $(OPENSSL) req -new -nodes -key $< -reqexts req_exts -config $(srcdir)/SSSD_test_cert_$*.config -out $@ ; \ + fi SSSD_test_cert_x509_%.pem: SSSD_test_cert_req_%.pem $(openssl_ca_config) SSSD_test_CA.pem $(OPENSSL) ca -config ${openssl_ca_config} -batch -notext -keyfile $(openssl_ca_key) -in $< -days 200 -extensions usr_cert -out $@ @@ -65,18 +71,18 @@ SSSD_test_cert_pubsshkey_%.h: SSSD_test_cert_pubsshkey_%.pub # - src/tests/cmocka/test_pam_srv.c p11_nssdb: SSSD_test_cert_pkcs12_0001.pem SSSD_test_CA.pem $(pwdfile) mkdir $@ - $(CERTUTIL) -d sql:./$@ -N --empty-password - $(CERTUTIL) -d sql:./$@ -A -n 'SSSD test CA' -t CT,CT,CT -a -i SSSD_test_CA.pem - $(PK12UTIL) -d sql:./$@ -i SSSD_test_cert_pkcs12_0001.pem -w $(pwdfile) + $(CERTUTIL) -d sql:./$@ -N -f $(pwdfile) + $(CERTUTIL) -d sql:./$@ -A -n 'SSSD test CA' -t CT,CT,CT -a -i SSSD_test_CA.pem -f $(pwdfile) + $(PK12UTIL) -d sql:./$@ -i SSSD_test_cert_pkcs12_0001.pem -w $(pwdfile) -k $(pwdfile) # This nss db is used in # - src/tests/cmocka/test_pam_srv.c p11_nssdb_2certs: SSSD_test_cert_pkcs12_0001.pem SSSD_test_cert_pkcs12_0002.pem SSSD_test_CA.pem $(pwdfile) mkdir $@ - $(CERTUTIL) -d sql:./$@ -N --empty-password - $(CERTUTIL) -d sql:./$@ -A -n 'SSSD test CA' -t CT,CT,CT -a -i SSSD_test_CA.pem - $(PK12UTIL) -d sql:./$@ p11_nssdb -i SSSD_test_cert_pkcs12_0001.pem -w $(pwdfile) - $(PK12UTIL) -d sql:./$@ p11_nssdb -i SSSD_test_cert_pkcs12_0002.pem -w $(pwdfile) + $(CERTUTIL) -d sql:./$@ -N -f $(pwdfile) + $(CERTUTIL) -d sql:./$@ -A -n 'SSSD test CA' -t CT,CT,CT -a -i SSSD_test_CA.pem -f $(pwdfile) + $(PK12UTIL) -d sql:./$@ -i SSSD_test_cert_pkcs12_0001.pem -w $(pwdfile) -k $(pwdfile) + $(PK12UTIL) -d sql:./$@ -i SSSD_test_cert_pkcs12_0002.pem -w $(pwdfile) -k $(pwdfile) # The softhsm2 PKCS#11 setups are used in # - src/tests/cmocka/test_pam_srv.c diff --git a/src/tests/test_CA/SSSD_test_cert_0004.config b/src/tests/test_CA/SSSD_test_cert_0004.config new file mode 100644 index 000000000..cb61b43ce --- /dev/null +++ b/src/tests/test_CA/SSSD_test_cert_0004.config @@ -0,0 +1,11 @@ +# This certificate is used in +# - test_sss_cert_get_content_test_cert_0004 +# as an example for a simple certificate without KU, EKU and SAN extensions +[ req ] +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] +O = SSSD +OU = SSSD test +CN = SSSD test cert 0004 diff --git a/src/tests/test_CA/SSSD_test_cert_key_0004.pem b/src/tests/test_CA/SSSD_test_cert_key_0004.pem new file mode 100644 index 000000000..e7e1b1de7 --- /dev/null +++ b/src/tests/test_CA/SSSD_test_cert_key_0004.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCdue/OaH/8xyzm +PUXFJeVJe0GOLZv3Pv/wPuIlNjAU1JNSDQUUKBlv7SOJr7KZ+4se6RyTU22G0KMN +0qswY5hlpOtCbRlH2fp5zaYakDVbAv00UBvllPuLetQA9hjCxvz3DZLfLC/N954N +ZKJIrO2fqTDvJwKqhw7gvp4p1vZcpAcsDf/AYzPgw1oX3yZyzQhfQwQ5Gu3U0Fwc +nQL/l++mDFD2faDBfn9CFu7hPHKMQvjITsK/RwuFqZa1BzU80x0iyRMhYyDuUDWD +2tDgzgt4qlMIHJb0ACHuSZFNIiqCF2xkM63PP3is2w7DUpRSu26FR4JacoKq7v5g +yhtw9y9HAgMBAAECggEAVpNKKy03G4QkhBib5HRBoAz01dr5IkTFbZTGwxA0Yiqw +1rfo0sCT/djXyerUCSuGmKfyFHgVxYteBOdfKgdxDlHxBJwn5UWj9BnKlAgWEWfZ +nk5eka0uSchY+FIdE0Twc5dSyAdUEiVZ7xYO8f9hy2KuRodOMlZB92EKJgMlZYGS +/hYOfZYmz3c4LFWO+UEiXyKKjENtnp5CpOw+Vcrwlu77PbFiT4Y12dOOwDRP4a/a +ddXQBUaApOMDBA6gpB4jaysq5EBnrLTL5fzHNpATVKFnAL7icPuIfefjU2kxQMoo +siUL7RzZnLlx0mN37DIzTv4uGltvGzzqhkIA5X/TsQKBgQDNBt3+dih7YbDt/4cC +HtuApUAbwYDYhETzU8Zt+WRiFZdOgBcm/bacxOqBWGJ1WCYnegPYmk4WVThH1zrF +Pr2EN2sOn2KJzQlLIOR7hvtTXgLx1hqc9XVBq/8JKhvCPfk/RoCjt+GmkoLHdrWI +w1kd2milRcFs09UCV8LGa/vYSQKBgQDE8JUXD8x77IP/CBXLBmFq6tSwYkRWh4jC +l8HB75VWXrknzgjv4Iqx4FEm2T0Mp0QFZLF6WCoclUcsGiCTz7jm20eoRL+5dX1d +yASi00GSpS1p2Q9eTTU4FHVg1nD1B5F1kQB8uqBj0oSjeQLLPngaIftxTGNrkw3J +4mk5kVdrDwKBgF0iA3F1pwn05HQYIPHbpoYXirmQ+sBfxRprMbX/FZRgjmzATsQN +eAhagtPinEcFlb9U865O2a3XZEtt/2peB6Spr93ilNZX5yLTfDaIqF3EVL4aLdii +v3LneGBnWliv4irWEdVM0Bnkb7e/utK3OiIPdn2s5CJVT2tTBk0v/CTRAoGAIe04 +IeLs3SRfkN25s2IEAkE2JrSnBSkQHEW8cUZuuZRT3VGXJIvQGNiF4mVmKPnfs/Ym +xObPSmFFA4n0tsIAHnUEIS7GwJJG6JL+iXZPQ44FBskH5rzyQBj2J5qJlwyYuGIk +bVhRLSElDGxaWN0IH6hfAqOgNPX+WBsS+YHaR20CgYAVUwTRA9kQgPZJfg+mepFG +zw9Tx7/TSwILZDlL0AU/i12xn0RA7sweLW8cPEDx1OnTbv+/pqSZ46eeZDzTrlu7 +ASy844law96NdhpKuTyz/jEl6aj0RLp1wzQZLSQkV0nv3f2Qlknhz83uShhxmxJv +FqS4fShRFJNoQDwEUvE7ZA== +-----END PRIVATE KEY----- -- 2.21.3