On Thu, Jun 27, 2013 at 01:27:28PM +0200, Jakub Hrozek wrote: > Hi, > > during testing I found out that we mishandle UPNs for subdomain users > when using Kerberos authentication. > > If there is no userPrincipal attribute we guess based on username@REALM. > But for subdomain users the username is already qualified, so so you end > up with username@DOMAIN@REALM. Currently first login works fine because > krb5 auth code treats the result as an enterprise principal. But if you > are checking existing ccache then the krb5 code errors out because one of > the krb5_cc_* functions treats username@DOMAIN@REALM as invalid principal. > > The attached patch checks if the username is already qualified and > replaces the domain name with realm name when guessing the UPN. I really > don't like the result because parsing out is inherently fragile. I think > we should store the plain username in an additional sysdb attribute, > too.
... > } > > errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx, > - const char *domain_name, const char *username, > + struct sss_domain_info *dom, const char > *username, > const char *user_dom, char **_upn) > { > const char *realm = NULL; > char *uc_dom = NULL; > char *upn; > + char *name; > + char *domname; > + TALLOC_CTX *tmp_ctx = NULL; I'm not sure a tmp_ctx is really needed here. > + errno_t ret; > > - if (user_dom != NULL && domain_name != NULL && > - strcasecmp(domain_name,user_dom) != 0) { > + tmp_ctx = talloc_new(NULL); > + if (tmp_ctx == NULL) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new failed.\n")); > + return ENOMEM; > + } > + > + if (user_dom != NULL && dom->name != NULL && > + strcasecmp(dom->name, user_dom) != 0) { > uc_dom = get_uppercase_realm(mem_ctx, user_dom); > if (uc_dom == NULL) { > DEBUG(SSSDBG_OP_FAILURE, ("get_uppercase_realm failed.\n")); > - return ENOMEM; > + ret = ENOMEM; > + goto done; > } > } else { > realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM); > if (realm == NULL) { > DEBUG(SSSDBG_OP_FAILURE, ("Missing Kerberos realm.\n")); > - return ENOENT; > + ret = ENOMEM; > + goto done; > } > } > > + /* Subdomains already have a fully qualified name, which contains > + * the domain name. We need to replace it with the realm name > + */ > + ret = sss_parse_name(tmp_ctx, dom->names, username, &domname, &name); > + if (ret != EOK) { > + DEBUG(SSSDBG_CRIT_FAILURE, ("Could not parse %s into name and " \ > + "domain components\n")); > + goto done; > + } > + > /* NOTE: this is a hack, works only in some environments */ > - upn = talloc_asprintf(mem_ctx, "%s@%s", username, > + upn = talloc_asprintf(mem_ctx, "%s@%s", name, > realm != NULL ? realm : uc_dom); > + talloc_free(name); if you call talloc_free(name) here you should also call talloc_free(domname) after calling sss_parse_name(). And the you do not need the tmp_ctx. > talloc_free(uc_dom); > if (upn == NULL) { > DEBUG(1, ("talloc_asprintf failed.\n")); > - return ENOMEM; > + ret = ENOMEM; > + goto done; > } > > DEBUG(9, ("Using simple UPN [%s].\n", upn)); > > - *_upn = upn; > - return EOK; > + *_upn = talloc_steal(mem_ctx, upn); You used mem_ctx to allocate upn, so not stealing is needed here. bye, Sumit > + ret = EOK; > +done: > + talloc_free(tmp_ctx); > + return ret; > } > > errno_t compare_principal_realm(const char *upn, const char *realm, > diff --git a/src/providers/krb5/krb5_common.h > b/src/providers/krb5/krb5_common.h > index > 501cdef10b0afc746ada7763a4253d4a0e3988b7..9eb602cfba7a032374ff57db53fd3c3638209153 > 100644 > --- a/src/providers/krb5/krb5_common.h > +++ b/src/providers/krb5/krb5_common.h > @@ -182,7 +182,7 @@ errno_t write_krb5info_file(const char *realm, const char > *kdc, > errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm); > > errno_t krb5_get_simple_upn(TALLOC_CTX *mem_ctx, struct krb5_ctx *krb5_ctx, > - const char *domain_name, const char *username, > + struct sss_domain_info *dom, const char > *username, > const char *user_dom, char **_upn); > > errno_t compare_principal_realm(const char *upn, const char *realm, > diff --git a/src/providers/krb5/krb5_renew_tgt.c > b/src/providers/krb5/krb5_renew_tgt.c > index > 0b1f26fd3a646e29a2f39ae6699714ca5318b66f..d6cdff8f8c0efc98445363c0a12a7ec19d12477f > 100644 > --- a/src/providers/krb5/krb5_renew_tgt.c > +++ b/src/providers/krb5/krb5_renew_tgt.c > @@ -442,7 +442,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx > *renew_tgt_ctx) > } > > ret = find_or_guess_upn(tmp_ctx, msgs[c], renew_tgt_ctx->krb5_ctx, > - renew_tgt_ctx->be_ctx->domain->name, > + renew_tgt_ctx->be_ctx->domain, > user_name, user_dom, &upn); > if (ret != EOK) { > DEBUG(SSSDBG_OP_FAILURE, ("find_or_guess_upn failed.\n")); > diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c > index > 3f16faa7fb238bbb9801029beed66293cd873c15..1f7ed07452d8814e813692f84423c74c1c8ecb65 > 100644 > --- a/src/providers/krb5/krb5_utils.c > +++ b/src/providers/krb5/krb5_utils.c > @@ -32,7 +32,7 @@ > > errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg, > struct krb5_ctx *krb5_ctx, > - const char *domain_name, const char *user, > + struct sss_domain_info *dom, const char *user, > const char *user_dom, char **_upn) > { > const char *upn; > @@ -40,7 +40,7 @@ errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct > ldb_message *msg, > > upn = ldb_msg_find_attr_as_string(msg, SYSDB_UPN, NULL); > if (upn == NULL) { > - ret = krb5_get_simple_upn(mem_ctx, krb5_ctx, domain_name, user, > + ret = krb5_get_simple_upn(mem_ctx, krb5_ctx, dom, user, > user_dom, _upn); > if (ret != EOK) { > DEBUG(SSSDBG_OP_FAILURE, ("krb5_get_simple_upn failed.\n")); > diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h > index > aad2770d4d3beb28c3ccb06278ee4cfc88562c85..2e1bec717ac7c3ac1c9bb87392d011eb854f21be > 100644 > --- a/src/providers/krb5/krb5_utils.h > +++ b/src/providers/krb5/krb5_utils.h > @@ -34,7 +34,7 @@ > > errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg, > struct krb5_ctx *krb5_ctx, > - const char *domain_name, const char *user, > + struct sss_domain_info *dom, const char *user, > const char *user_dom, char **_upn); > > errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb, > -- > 1.8.3.1 > > _______________________________________________ > sssd-devel mailing list > sssd-devel@lists.fedorahosted.org > https://lists.fedorahosted.org/mailman/listinfo/sssd-devel _______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel