Hello, please see attached patches, thanks!
>From e824d4aa1051bf405243deb06cef1e05ed3ffd25 Mon Sep 17 00:00:00 2001 From: Pavel Reichl <prei...@redhat.com> Date: Fri, 27 Feb 2015 11:37:50 -0500 Subject: [PATCH 1/3] krb5: new option krb5_map_user
New option `krb5_map_user` providing mapping of ID provider names to Kerberos principals. Resolves: https://fedorahosted.org/sssd/ticket/2509 --- src/config/SSSDConfig/__init__.py.in | 1 + src/config/SSSDConfigTest.py | 9 ++- src/config/etc/sssd.api.d/sssd-ad.conf | 1 + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + src/config/etc/sssd.api.d/sssd-krb5.conf | 1 + src/man/sssd-krb5.5.xml | 26 ++++++++ src/providers/ad/ad_opts.h | 1 + src/providers/ipa/ipa_opts.h | 1 + src/providers/krb5/krb5_access.c | 4 +- src/providers/krb5/krb5_auth.c | 40 +++++++++++- src/providers/krb5/krb5_auth.h | 2 + src/providers/krb5/krb5_common.h | 9 +++ src/providers/krb5/krb5_init_shared.c | 101 +++++++++++++++++++++++++++++++ src/providers/krb5/krb5_opts.h | 1 + src/util/util.c | 56 +++++++++++++++++ src/util/util.h | 6 ++ 16 files changed, 254 insertions(+), 6 deletions(-) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index dbbffebf38977e526cf2944510a2f60da7edf33a..1d4b9c2cc6e20ea82222931551e0cb7ca859600e 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -216,6 +216,7 @@ option_strings = { 'krb5_fast_principal' : _("Selects the principal to use for FAST"), 'krb5_canonicalize' : _("Enables principal canonicalization"), 'krb5_use_enterprise_principal' : _("Enables enterprise principals"), + 'krb5_map_user' : _('A mapping from user names to kerberos principal names'), # [provider/krb5/chpass] 'krb5_kpasswd' : _('Server where the change password service is running if not on the KDC'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 3a5312ea945b5247c69e97b73565b7061e037b69..87ee2b5f7d7bc81bd620a10f7dd86701b3efd870 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -621,7 +621,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_fast_principal', 'krb5_canonicalize', 'krb5_use_enterprise_principal', - 'krb5_use_kdcinfo']) + 'krb5_use_kdcinfo', + 'krb5_map_user']) options = domain.list_options() @@ -781,7 +782,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_fast_principal', 'krb5_canonicalize', 'krb5_use_enterprise_principal', - 'krb5_use_kdcinfo'] + 'krb5_use_kdcinfo', + 'krb5_map_user'] self.assertTrue(type(options) == dict, "Options should be a dictionary") @@ -981,7 +983,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'krb5_fast_principal', 'krb5_canonicalize', 'krb5_use_enterprise_principal', - 'krb5_use_kdcinfo']) + 'krb5_use_kdcinfo', + 'krb5_map_user']) options = domain.list_options() diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf index 5a5ea0c36b07d7497c1caa4208c7270d6de6dcc9..c46f3a7cb50db519d113e15f425c7f746d34ad81 100644 --- a/src/config/etc/sssd.api.d/sssd-ad.conf +++ b/src/config/etc/sssd.api.d/sssd-ad.conf @@ -139,6 +139,7 @@ krb5_renew_interval = str, None, false krb5_use_fast = str, None, false krb5_fast_principal = str, None, false krb5_use_enterprise_principal = bool, None, false +krb5_map_user = str, None, false [provider/ad/access] diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf index 2a3b7ef1519e3476cb4b432336da0c359b1844ba..d9ab673f25831da3a513da68a7113a525691a2db 100644 --- a/src/config/etc/sssd.api.d/sssd-ipa.conf +++ b/src/config/etc/sssd.api.d/sssd-ipa.conf @@ -155,6 +155,7 @@ krb5_renew_interval = str, None, false krb5_use_fast = str, None, false krb5_fast_principal = str, None, false krb5_use_enterprise_principal = bool, None, false +krb5_map_user = str, None, false [provider/ipa/access] ipa_hbac_refresh = int, None, false diff --git a/src/config/etc/sssd.api.d/sssd-krb5.conf b/src/config/etc/sssd.api.d/sssd-krb5.conf index e65ed01b688078aff090ff53b91779595fd6f465..b7423b74f7b6845d235cc523a8e249d6a74d69ab 100644 --- a/src/config/etc/sssd.api.d/sssd-krb5.conf +++ b/src/config/etc/sssd.api.d/sssd-krb5.conf @@ -21,6 +21,7 @@ krb5_use_fast = str, None, false krb5_fast_principal = str, None, false krb5_canonicalize = bool, None, false krb5_use_enterprise_principal = bool, None, false +krb5_map_user = str, None, false [provider/krb5/access] diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml index 5bcab21111670a22e6d0c3cdc9eccf765e950b07..cf40ab4c70beded443933b820a9b65f7f57d1e2c 100644 --- a/src/man/sssd-krb5.5.xml +++ b/src/man/sssd-krb5.5.xml @@ -507,6 +507,32 @@ </listitem> </varlistentry> + <varlistentry> + <term>krb5_map_user (string)</term> + <listitem> + <para> + The list of mappings is given as a comma-separated + list of pairs `username:principal` where `username` + is a UNIX user name and `principal` is a kerberos + principal name. This mapping is used when user is + authenticating using `auth_provider = krb5`. + </para> + + <para> + example: + krb5_map_user = joe:juser,vince:rraines + </para> + <para> + `joe` and `vince` are UNIX user names and `juser` + and `rraines` are kerberos principal names. + </para> + + <para> + Default: not set + </para> + </listitem> + </varlistentry> + </variablelist> </para> </refsect1> diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h index f4c1c523bdc57a824105dfd781eb90a88e068908..4c287021c2d901999602621a4fe3b7af9c6b8c35 100644 --- a/src/providers/ad/ad_opts.h +++ b/src/providers/ad/ad_opts.h @@ -168,6 +168,7 @@ struct dp_option ad_def_krb5_opts[] = { { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 66af648583e552d7edd932f6bb5a2c3bef107e51..5ce47c31ed0bb947dd1f3f361c5052a1d76fb692 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -311,6 +311,7 @@ struct dp_option ipa_def_krb5_opts[] = { { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c index 7fda2a37922a537f7fe53d629c4e0cb4df1bd4da..72b93180f9cdeb53ad78c821ed73281d38cda920 100644 --- a/src/providers/krb5/krb5_access.c +++ b/src/providers/krb5/krb5_access.c @@ -106,8 +106,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, break; case 1: ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, - be_ctx->domain, pd->user, pd->domain, - &state->kr->upn); + be_ctx->domain, state->kr->mapped_name, + pd->domain, &state->kr->upn); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n"); goto done; diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index 25caf7b788a3f373f47e9d8aad38a2ea6fc12621..f665fab786b27bf1e85d238cdb2567915d0ae0b8 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -175,10 +175,33 @@ static int krb5_cleanup(void *ptr) return EOK; } +errno_t get_krb_princ(struct map_id_name_to_krb_princ *name_to_princ, int size, + char *id_prov_name, const char **_krb_princ) +{ + errno_t ret; + int i; + + for (i=0; i < size; i++) { + if (strcmp(name_to_princ[i].id_name, id_prov_name) == 0) { + *_krb_princ = name_to_princ[i].krb_princ; + ret = EOK; + goto done; + } + } + + /* Handle also the case of size being zero */ + ret = ENOENT; + +done: + return ret; +} + errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req) { struct krb5child_req *kr = NULL; + const char *mapped_name; + errno_t ret; kr = talloc_zero(mem_ctx, struct krb5child_req); if (kr == NULL) { @@ -192,6 +215,20 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, kr->pd = pd; kr->krb5_ctx = krb5_ctx; + ret = get_krb_princ(krb5_ctx->name_to_princ, krb5_ctx->name_to_princ_size, + pd->user, &mapped_name); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "Setting mapped name to: %s\n", mapped_name); + kr->mapped_name = mapped_name; + } else if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC, "No mapping for: %s\n", pd->user); + kr->mapped_name = pd->user; + } else { + DEBUG(SSSDBG_MINOR_FAILURE, "get_krb_princ failed - %s:[%d]\n", + sss_strerror(ret), ret); + kr->mapped_name = pd->user; + } + *krb5_req = kr; return EOK; @@ -350,6 +387,7 @@ struct krb5_auth_state { static void krb5_auth_resolve_done(struct tevent_req *subreq); static void krb5_auth_done(struct tevent_req *subreq); + struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct be_ctx *be_ctx, @@ -510,7 +548,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, case 1: ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, - be_ctx->domain, pd->user, pd->domain, + be_ctx->domain, kr->mapped_name, pd->domain, &kr->upn); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "find_or_guess_upn failed.\n"); diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index 00cb658c418ade2e6a1d9b5362a40f97e0dc6c6b..354c74f5d806c9bd9355a9abdc2976f1fcf8b1aa 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -56,6 +56,8 @@ struct krb5child_req { bool run_as_user; bool upn_from_different_realm; bool send_pac; + + const char *mapped_name; }; errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h index 81e64688a6d93a4b3ecf41d75d1bf6166b4619ce..99ee3b4930fb275efebc09e510cd0459d11bf19e 100644 --- a/src/providers/krb5/krb5_common.h +++ b/src/providers/krb5/krb5_common.h @@ -67,6 +67,7 @@ enum krb5_opts { KRB5_CANONICALIZE, KRB5_USE_ENTERPRISE_PRINCIPAL, KRB5_USE_KDCINFO, + KRB5_MAP_USER, KRB5_OPTS }; @@ -89,6 +90,11 @@ enum krb5_config_type { K5C_IPA_SERVER }; +struct map_id_name_to_krb_princ { + char *id_name; + char* krb_princ; +}; + struct krb5_ctx { /* opts taken from kinit */ /* in seconds */ @@ -128,6 +134,9 @@ struct krb5_ctx { hash_table_t *wait_queue_hash; enum krb5_config_type config_type; + + struct map_id_name_to_krb_princ *name_to_princ; + int name_to_princ_size; }; struct remove_info_files_ctx { diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c index 3b4bf096ef49d0f2d369fda20462b7fd56d61127..e0c010fefe79ffa594a63a88c43279aecd4559c2 100644 --- a/src/providers/krb5/krb5_init_shared.c +++ b/src/providers/krb5/krb5_init_shared.c @@ -26,6 +26,98 @@ #include "providers/krb5/krb5_auth.h" #include "providers/krb5/krb5_init_shared.h" +static errno_t +fill_name_to_princ_map(TALLOC_CTX *mem_ctx, char **map, + struct map_id_name_to_krb_princ *name_to_princ, + int size) +{ + int i; + errno_t ret; + + for (i=0; i < size; i++) { + ret = split_str(mem_ctx, ':', map[i], + &name_to_princ[i].id_name, + &name_to_princ[i].krb_princ); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "split_str failed - %s:[%d]\n", sss_strerror(ret), ret); + goto done; + } else if (name_to_princ[i].id_name == NULL || + name_to_princ[i].krb_princ == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "split_str failed - %s:%s\n", + name_to_princ[i].id_name, name_to_princ[i].krb_princ ); + ret = EINVAL; + goto done; + } + } + + ret = EOK; + +done: + return ret; +} + +errno_t parse_krb5_map_user(TALLOC_CTX *mem_ctx, struct dp_option *opts, + struct map_id_name_to_krb_princ **_name_to_princ, + int *_size) +{ + int size; + char **map; + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *krb5_map_user; + struct map_id_name_to_krb_princ *name_to_princ; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + krb5_map_user = dp_opt_get_cstring(opts, KRB5_MAP_USER); + if (krb5_map_user == NULL) { + DEBUG(SSSDBG_FUNC_DATA, "Option krb5_map_user is empty!\n"); + size = 0; + ret = EOK; + goto done; + } + + ret = split_on_separator(tmp_ctx, krb5_map_user, ',', true, true, + &map, &size); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to parse krb5_map_user!\n"); + goto done; + } + + name_to_princ = talloc_array(tmp_ctx, + struct map_id_name_to_krb_princ, size); + if (name_to_princ == NULL) { + ret = ENOMEM; + goto done; + } + + ret = fill_name_to_princ_map(name_to_princ, map, name_to_princ, size); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "fill_name_to_princ_map failed: %s:[%d]\n", + sss_strerror(ret), ret); + goto done; + } + + ret = EOK; + +done: + if (ret == EOK) { + if (size == 0) { + *_name_to_princ = NULL; + } else { + *_name_to_princ = talloc_steal(mem_ctx, name_to_princ); + } + *_size = size; + } + talloc_free(tmp_ctx); + return ret; +} + errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, struct be_ctx *bectx) { @@ -90,6 +182,15 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, goto done; } + ret = parse_krb5_map_user(krb5_auth_ctx, krb5_auth_ctx->opts, + &krb5_auth_ctx->name_to_princ, + &krb5_auth_ctx->name_to_princ_size); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "parse_krb5_map_user failed: %s:[%d]\n", + sss_strerror(ret), ret); + goto done; + } + ret = EOK; done: diff --git a/src/providers/krb5/krb5_opts.h b/src/providers/krb5/krb5_opts.h index db62cc3b23d8a5eadd3df97a102fb84128b740da..50d701b8ba431719dbf67799230ec345cdee30a9 100644 --- a/src/providers/krb5/krb5_opts.h +++ b/src/providers/krb5/krb5_opts.h @@ -45,6 +45,7 @@ struct dp_option default_krb5_opts[] = { { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, + { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING }, DP_OPTION_TERMINATOR }; diff --git a/src/util/util.c b/src/util/util.c index 613c559bb2002686c7833642d0946e46e5a9b5d6..a3da6c51d2b92a529b03632a26b6e07569b5da77 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -30,6 +30,62 @@ #include "util/util.h" #include "util/sss_utf8.h" +errno_t split_str(TALLOC_CTX *mem_ctx, + const char delimiter, + char *str, + char **_first, + char **_second) +{ + char *sep; + errno_t ret; + char *first; + char *second; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + sep = strchr(str, delimiter); + if (sep == NULL) { + ret = ENOENT; + goto done; + } else { + if (sep == str) { + first = NULL; + } else { + first = talloc_strndup(tmp_ctx, str, sep - str); + if (first == NULL) { + ret = ENOMEM; + goto done; + } + } + + if (*(sep + 1) == '\0') { + second = NULL; + } else { + second = talloc_strdup(tmp_ctx, sep+1); + if (second == NULL) { + ret = ENOMEM; + goto done; + } + } + } + + ret = EOK; + +done: + if (ret == EOK) { + *_first = talloc_steal(mem_ctx, first); + *_second = talloc_steal(mem_ctx, second); + } + + talloc_free(tmp_ctx); + return ret; +} + int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, const char sep, bool trim, bool skip_empty, char ***_list, int *size) diff --git a/src/util/util.h b/src/util/util.h index 3c5ce295ec4ad2ad3c3a7ae0e7482c232db79746..479e24cabe947419cf9d63e803b1b662359ad38b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -408,6 +408,12 @@ const char * const * get_known_services(void); errno_t sss_user_by_name_or_uid(const char *input, uid_t *_uid, gid_t *_gid); +errno_t split_str(TALLOC_CTX *mem_ctx, + const char delimiter, + char *str, + char **_first, + char **_second); + int split_on_separator(TALLOC_CTX *mem_ctx, const char *str, const char sep, bool trim, bool skip_empty, char ***_list, int *size); -- 2.1.0
>From 50839ec51277cb9aa45c21b71bfb9dc5e8b0b553 Mon Sep 17 00:00:00 2001 From: Pavel Reichl <prei...@redhat.com> Date: Wed, 29 Apr 2015 06:03:04 -0400 Subject: [PATCH 2/3] krb5: remove field run_as_user run_as_user is set set but never read. --- src/providers/krb5/krb5_auth.c | 14 -------------- src/providers/krb5/krb5_auth.h | 1 - 2 files changed, 15 deletions(-) diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index f665fab786b27bf1e85d238cdb2567915d0ae0b8..9bd9348b29501148f29e0762b662868e4dcd4f17 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -209,7 +209,6 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, return ENOMEM; } kr->is_offline = false; - kr->run_as_user = true; talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup); kr->pd = pd; @@ -710,19 +709,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) kr->is_offline = be_is_offline(state->be_ctx); } - /* We need to keep the root privileges to read the keytab file if - * validation or FAST is enabled, otherwise we can drop them and run - * krb5_child with user privileges. - * If we are offline we want to create an empty ccache file. In this - * case we can drop the privileges, too. */ - if ((dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) || - kr->krb5_ctx->use_fast) && - (!kr->is_offline)) { - kr->run_as_user = false; - } else { - kr->run_as_user = true; - } - subreq = handle_child_send(state, state->ev, kr); if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "handle_child_send failed.\n"); diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h index 354c74f5d806c9bd9355a9abdc2976f1fcf8b1aa..7e88c2004b82e50606b622add59b80233bff0310 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -53,7 +53,6 @@ struct krb5child_req { struct fo_server *kpasswd_srv; bool active_ccache; bool valid_tgt; - bool run_as_user; bool upn_from_different_realm; bool send_pac; -- 2.1.0
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel