diff options
Diffstat (limited to 'src/providers/krb5')
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 30 | ||||
-rw-r--r-- | src/providers/krb5/krb5_utils.c | 99 | ||||
-rw-r--r-- | src/providers/krb5/krb5_utils.h | 4 |
3 files changed, 133 insertions, 0 deletions
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index c1f9f14b..f2e00fac 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -782,6 +782,36 @@ static void krb5_child_done(struct tevent_req *subreq) } } + /* Check if the cases of our upn are correct and update it if needed. + * Fail if the upn differs by more than just the case. */ + if (res->correct_upn != NULL && + strcmp(kr->upn, res->correct_upn) != 0) { + if (strcasecmp(kr->upn, res->correct_upn) == 0) { + talloc_free(kr->upn); + kr->upn = talloc_strdup(kr, res->correct_upn); + if (kr->upn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + ret = ENOMEM; + goto done; + } + + ret = check_if_cached_upn_needs_update(state->sysdb, pd->user, + res->correct_upn); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("check_if_cached_upn_needs_update failed.\n")); + goto done; + } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, ("UPN used in the request [%s] and " \ + "returned UPN [%s] differ by more " \ + "than just the case.\n", + kr->upn, res->correct_upn)); + ret = EINVAL; + goto done; + } + } + /* If the child request failed, but did not return an offline error code, * return with the status */ if (res->msg_status != PAM_SUCCESS && diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c index 98376169..6cfd48cf 100644 --- a/src/providers/krb5/krb5_utils.c +++ b/src/providers/krb5/krb5_utils.c @@ -57,6 +57,105 @@ errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg, return EOK; } +errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb, + const char *user, + const char *upn) +{ + TALLOC_CTX *tmp_ctx; + int ret; + int sret; + const char *attrs[] = {SYSDB_UPN, NULL}; + struct sysdb_attrs *new_attrs; + struct ldb_result *res; + bool in_transaction = false; + const char *cached_upn; + + if (sysdb == NULL || user == NULL || upn == NULL) { + return EINVAL; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n")); + return ENOMEM; + } + + ret = sysdb_get_user_attr(tmp_ctx, sysdb, user, attrs, &res); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_user_attr failed.\n")); + goto done; + } + + if (res->count != 1) { + DEBUG(SSSDBG_OP_FAILURE, ("[%d] user objects for name [%s] found, " \ + "expected 1.\n", res->count, user)); + ret = EINVAL; + goto done; + } + + cached_upn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_UPN, NULL); + + if (cached_upn != NULL && strcmp(cached_upn, upn) == 0) { + DEBUG(SSSDBG_TRACE_ALL, ("Cached UPN and new one match, " + "nothing to do.\n")); + ret = EOK; + goto done; + } + + DEBUG(SSSDBG_TRACE_LIBS, ("Replacing UPN [%s] with [%s] for user [%s].\n", + cached_upn, upn, user)); + + new_attrs = sysdb_new_attrs(tmp_ctx); + if (new_attrs == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_new_attrs failed.\n")); + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_add_string(new_attrs, SYSDB_UPN, upn); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n")); + goto done; + } + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Error %d starting transaction (%s)\n", ret, strerror(ret))); + goto done; + } + in_transaction = true; + + ret = sysdb_set_entry_attr(sysdb, res->msgs[0]->dn, new_attrs, + SYSDB_MOD_REP); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("sysdb_set_entry_attr failed [%d][%s].\n", + ret, strerror(ret))); + goto done; + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Failed to commit transaction!\n")); + goto done; + } + in_transaction = false; + + ret = EOK; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n")); + } + } + + talloc_free(tmp_ctx); + + return ret; +} + char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr, const char *template, bool file_mode, bool case_sensitive, bool *private_path) diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h index 28485458..25d8c6cf 100644 --- a/src/providers/krb5/krb5_utils.h +++ b/src/providers/krb5/krb5_utils.h @@ -37,6 +37,10 @@ errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg, const char *domain_name, const char *user, const char *user_dom, char **_upn); +errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb, + const char *user, + const char *upn); + /* Operations on a credential cache */ typedef errno_t (*cc_be_create_fn)(const char *location, pcre *illegal_re, uid_t uid, gid_t gid, bool private_path); |