On 03/27/2015 02:01 PM, Orion Poplawski wrote:
I've got IPA running on an EL7.1 box for the domain
NWRA.COM. I
established a
trust with our active directory domain (
AD.NWRA.COM). The trust seem to be
working mostly correctly, I can auto-login with AD kerberos tickets for example.
However, password authentication for the AD users does not appear to be working:
$ su - orion(a)AD.NWRA.COM
Password:
su: Authentication failure
sssd log shows:
(Fri Mar 27 13:51:43 2015) [sssd[be[nwra.com]]] [krb5_auth_done]
(0x0020): UPN
used in the request [Orion Poplawski(a)AD.NWRA.COM] and returned UPN
[orion(a)AD.NWRA.COM] differ by more than just the case.
The UPN message seems like an issue. Ideas?
ipa-server-4.1.0-18.sl7_1.3.x86_64
sssd-1.12.2-58.el7.x86_64
Possibly relevant commit:
$ git show 7c4845bd0efb1dcb44b5be52923c539316725693
commit 7c4845bd0efb1dcb44b5be52923c539316725693
Author: Sumit Bose <sbose(a)redhat.com>
Date: Wed Oct 24 10:01:09 2012 +0200
krb5_auth: update with correct UPN if needed
The Active Directory KDC handles request case in-sensitive and it might
not always to possible to guess the UPN with the correct case. We check
if the returned principal has a different case then the one used in the
request and updates the principal if needed. This will help using calls
from the Kerberos client libraries later on which would otherwise fail
because the principal is handled case sensitive by those libraries.
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index c1f9f14..f2e00fa 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 9837616..6cfd48c 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 2848545..25d8c6c 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);
--
Orion Poplawski
Technical Manager 303-415-9701 x222
NWRA, Boulder/CoRA Office FAX: 303-415-9702
3380 Mitchell Lane orion(a)nwra.com
Boulder, CO 80301
http://www.nwra.com