diff options
author | Pavel Reichl <preichl@redhat.com> | 2015-04-30 06:43:05 -0400 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2015-05-28 11:04:28 +0200 |
commit | aa8a8318aaa3270e9d9957d0c22dec6342360a37 (patch) | |
tree | 9f6ccd9d2cc601adde7f21fa161715f9d76aee2d /src/providers | |
parent | 62b20154899f847e760d6dfbae6a32fb45b448de (diff) | |
download | sssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.tar.gz sssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.tar.xz sssd-aa8a8318aaa3270e9d9957d0c22dec6342360a37.zip |
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
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/providers')
-rw-r--r-- | src/providers/ad/ad_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ipa/ipa_opts.h | 1 | ||||
-rw-r--r-- | src/providers/krb5/krb5_access.c | 8 | ||||
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 76 | ||||
-rw-r--r-- | src/providers/krb5/krb5_auth.h | 5 | ||||
-rw-r--r-- | src/providers/krb5/krb5_common.h | 8 | ||||
-rw-r--r-- | src/providers/krb5/krb5_init_shared.c | 11 | ||||
-rw-r--r-- | src/providers/krb5/krb5_opts.h | 1 | ||||
-rw-r--r-- | src/providers/krb5/krb5_utils.c | 114 | ||||
-rw-r--r-- | src/providers/krb5/krb5_utils.h | 5 |
10 files changed, 215 insertions, 15 deletions
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h index 15b140434..6e859447f 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 8a0764265..34e9e167e 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -310,6 +310,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 7fda2a379..3afb90150 100644 --- a/src/providers/krb5/krb5_access.c +++ b/src/providers/krb5/krb5_access.c @@ -64,7 +64,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, state->krb5_ctx = krb5_ctx; state->access_allowed = false; - ret = krb5_setup(state, pd, krb5_ctx, &state->kr); + ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive, + &state->kr); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n"); goto done; @@ -105,9 +106,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, goto done; break; case 1: - ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, - be_ctx->domain, pd->user, pd->domain, - &state->kr->upn); + ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain, + state->kr->user, 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 148b08fdf..8c851442b 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -36,6 +36,7 @@ #include "util/find_uid.h" #include "util/auth_utils.h" #include "db/sysdb.h" +#include "util/sss_utf8.h" #include "util/child_common.h" #include "providers/krb5/krb5_auth.h" #include "providers/krb5/krb5_utils.h" @@ -175,15 +176,51 @@ static int krb5_cleanup(void *ptr) return EOK; } +static errno_t +get_krb_primary(struct map_id_name_to_krb_primary *name_to_primary, + char *id_prov_name, bool cs, const char **_krb_primary) +{ + errno_t ret; + int i = 0; + + while(name_to_primary != NULL && + name_to_primary[i].id_name != NULL && + name_to_primary[i].krb_primary != NULL) { + + if (sss_string_equal(cs, name_to_primary[i].id_name, id_prov_name)) { + *_krb_primary = name_to_primary[i].krb_primary; + ret = EOK; + goto done; + } + i++; + } + + /* Handle also the case of name_to_primary being NULL */ + 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 krb5_ctx *krb5_ctx, bool cs, + struct krb5child_req **_krb5_req) { - struct krb5child_req *kr = NULL; + struct krb5child_req *kr; + const char *mapped_name; + TALLOC_CTX *tmp_ctx; + errno_t ret; - kr = talloc_zero(mem_ctx, struct krb5child_req); + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + kr = talloc_zero(tmp_ctx, struct krb5child_req); if (kr == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n"); - return ENOMEM; + ret = ENOMEM; + goto done; } kr->is_offline = false; talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup); @@ -191,9 +228,28 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, kr->pd = pd; kr->krb5_ctx = krb5_ctx; - *krb5_req = kr; + ret = get_krb_primary(krb5_ctx->name_to_primary, + pd->user, cs, &mapped_name); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "Setting mapped name to: %s\n", mapped_name); + kr->user = mapped_name; + } else if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_ALL, "No mapping for: %s\n", pd->user); + kr->user = pd->user; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "get_krb_primary failed - %s:[%d]\n", + sss_strerror(ret), ret); + goto done; + } - return EOK; + ret = EOK; + +done: + if (ret == EOK) { + *_krb5_req = talloc_steal(mem_ctx, kr); + } + talloc_free(tmp_ctx); + return ret; } @@ -502,7 +558,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, attrs[6] = SYSDB_AUTH_TYPE; attrs[7] = NULL; - ret = krb5_setup(state, pd, krb5_ctx, &state->kr); + ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive, + &state->kr); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n"); goto done; @@ -535,9 +592,8 @@ struct tevent_req *krb5_auth_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, - &kr->upn); + ret = find_or_guess_upn(state, res->msgs[0], krb5_ctx, be_ctx->domain, + kr->user, pd->domain, &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.h b/src/providers/krb5/krb5_auth.h index c93252916..a00f1d9d9 100644 --- a/src/providers/krb5/krb5_auth.h +++ b/src/providers/krb5/krb5_auth.h @@ -55,10 +55,13 @@ struct krb5child_req { bool valid_tgt; bool upn_from_different_realm; bool send_pac; + + const char *user; }; errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, - struct krb5_ctx *krb5_ctx, struct krb5child_req **krb5_req); + struct krb5_ctx *krb5_ctx, bool case_sensitive, + struct krb5child_req **krb5_req); void krb5_pam_handler(struct be_req *be_req); void krb5_pam_handler_auth_done(struct tevent_req *req); diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h index 81e64688a..8f6fb229a 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_primary { + const char *id_name; + const char* krb_primary; +}; + struct krb5_ctx { /* opts taken from kinit */ /* in seconds */ @@ -128,6 +134,8 @@ struct krb5_ctx { hash_table_t *wait_queue_hash; enum krb5_config_type config_type; + + struct map_id_name_to_krb_primary *name_to_primary; }; struct remove_info_files_ctx { diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c index 3b4bf096e..767291c0b 100644 --- a/src/providers/krb5/krb5_init_shared.c +++ b/src/providers/krb5/krb5_init_shared.c @@ -24,6 +24,7 @@ #include "providers/krb5/krb5_common.h" #include "providers/krb5/krb5_auth.h" +#include "providers/krb5/krb5_utils.h" #include "providers/krb5/krb5_init_shared.h" errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, @@ -90,6 +91,16 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx, goto done; } + ret = parse_krb5_map_user(krb5_auth_ctx, + dp_opt_get_cstring(krb5_auth_ctx->opts, + KRB5_MAP_USER), + &krb5_auth_ctx->name_to_primary); + 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 db62cc3b2..50d701b8b 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/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c index de2d94503..0b73880ec 100644 --- a/src/providers/krb5/krb5_utils.c +++ b/src/providers/krb5/krb5_utils.c @@ -465,3 +465,117 @@ errno_t get_domain_or_subdomain(struct be_ctx *be_ctx, return EOK; } + +static errno_t split_tuple(TALLOC_CTX *mem_ctx, const char *tuple, + const char **_first, const char **_second) +{ + errno_t ret; + char **list; + int n; + + ret = split_on_separator(mem_ctx, tuple, ':', true, true, &list, &n); + + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "split_on_separator failed - %s:[%d]\n", + sss_strerror(ret), ret); + goto done; + } else if (n != 2) { + DEBUG(SSSDBG_MINOR_FAILURE, + "split_on_separator failed - Expected format is: " + "'username:primary' but got: '%s'.\n", tuple); + ret = EINVAL; + goto done; + } + + *_first = list[0]; + *_second = list[1]; + +done: + return ret; +} + +static errno_t +fill_name_to_primary_map(TALLOC_CTX *mem_ctx, char **map, + struct map_id_name_to_krb_primary *name_to_primary, + size_t size) +{ + int i; + errno_t ret; + + for (i = 0; i < size; i++) { + ret = split_tuple(mem_ctx, map[i], + &name_to_primary[i].id_name, + &name_to_primary[i].krb_primary); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "split_tuple failed - %s:[%d]\n", sss_strerror(ret), ret); + goto done; + } + } + + ret = EOK; + +done: + return ret; +} + +errno_t +parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user, + struct map_id_name_to_krb_primary **_name_to_primary) +{ + int size; + char **map; + errno_t ret; + TALLOC_CTX *tmp_ctx; + struct map_id_name_to_krb_primary *name_to_primary; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + if (krb5_map_user == NULL || strlen(krb5_map_user) == 0) { + DEBUG(SSSDBG_FUNC_DATA, "Warning: krb5_map_user is empty!\n"); + size = 0; + } else { + 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_primary = talloc_zero_array(tmp_ctx, + struct map_id_name_to_krb_primary, + size + 1); + if (name_to_primary == NULL) { + ret = ENOMEM; + goto done; + } + /* sentinel */ + name_to_primary[size].id_name = NULL; + name_to_primary[size].krb_primary = NULL; + + if (size > 0) { + ret = fill_name_to_primary_map(name_to_primary, map, name_to_primary, + size); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "fill_name_to_primary_map failed: %s:[%d]\n", + sss_strerror(ret), ret); + goto done; + } + } + + ret = EOK; + +done: + if (ret == EOK) { + *_name_to_primary = talloc_steal(mem_ctx, name_to_primary); + } + talloc_free(tmp_ctx); + return ret; +} diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h index 0155905b5..75b93c30e 100644 --- a/src/providers/krb5/krb5_utils.h +++ b/src/providers/krb5/krb5_utils.h @@ -49,4 +49,9 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr, errno_t get_domain_or_subdomain(struct be_ctx *be_ctx, char *domain_name, struct sss_domain_info **dom); + +errno_t +parse_krb5_map_user(TALLOC_CTX *mem_ctx, const char *krb5_map_user, + struct map_id_name_to_krb_primary **_name_to_primary); + #endif /* __KRB5_UTILS_H__ */ |