summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2012-10-23 21:30:17 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-11-05 00:14:05 +0100
commitef3053bd244cb3b104b608b338c764c6a2e34f29 (patch)
tree6e3405f1da00c2f632a7433c0c606ad3c28ad0c0
parentb3ea76f3c6d32b4fbf29caa2f4f6ec4138da5be1 (diff)
downloadsssd-ef3053bd244cb3b104b608b338c764c6a2e34f29.tar.gz
sssd-ef3053bd244cb3b104b608b338c764c6a2e34f29.tar.xz
sssd-ef3053bd244cb3b104b608b338c764c6a2e34f29.zip
krb5_child: send back the client principal
In general Kerberos is case sensitive but the KDC of Active Directory typically handles request case in-sensitive. In the case where we guess a user principal by combining the user name and the realm and are not sure about the cases of the letters used in the user name we might get a valid ticket from the AD KDC but are not able to access it with the Kerberos client library because we assume a wrong case. The client principal in the returned credentials will always have the right cases. To be able to update the cache user principal name the krb5_child will return the principal for further processing.
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/providers/krb5/krb5_auth.h1
-rw-r--r--src/providers/krb5/krb5_child.c29
-rw-r--r--src/providers/krb5/krb5_child_handler.c16
4 files changed, 42 insertions, 5 deletions
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index b783081bc..d49fcd524 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -195,6 +195,7 @@ struct pam_data {
#define SSS_PROXY_INFO 0x10000000
#define SSS_KRB5_INFO_TGT_LIFETIME (SSS_SERVER_INFO|SSS_KRB5_INFO|0x01)
+#define SSS_KRB5_INFO_UPN (SSS_SERVER_INFO|SSS_KRB5_INFO|0x02)
errno_t copy_pam_data(TALLOC_CTX *mem_ctx, struct pam_data *old_pd,
struct pam_data **new_pd);
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index a23b8b47d..bf49f7cfd 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -80,6 +80,7 @@ struct krb5_child_response {
int32_t msg_status;
struct tgt_times tgtt;
char *ccname;
+ char *correct_upn;
};
errno_t
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 4bfbf4bf3..3e64a8652 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -785,10 +785,13 @@ static errno_t sendresponse(int fd, krb5_error_code kerr, int pam_status,
return EOK;
}
-static errno_t add_ticket_times_to_response(struct krb5_req *kr)
+static errno_t add_ticket_times_and_upn_to_response(struct krb5_req *kr)
{
int ret;
int64_t t[4];
+ krb5_error_code kerr;
+ char *upn = NULL;
+ unsigned int upn_len = 0;
t[0] = (int64_t) kr->creds->times.authtime;
t[1] = (int64_t) kr->creds->times.starttime;
@@ -799,8 +802,24 @@ static errno_t add_ticket_times_to_response(struct krb5_req *kr)
4*sizeof(int64_t), (uint8_t *) t);
if (ret != EOK) {
DEBUG(1, ("pack_response_packet failed.\n"));
+ goto done;
+ }
+
+ kerr = krb5_unparse_name_ext(kr->ctx, kr->creds->client, &upn, &upn_len);
+ if (kerr != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("krb5_unparse_name failed.\n"));
+ goto done;
+ }
+
+ ret = pam_add_response(kr->pd, SSS_KRB5_INFO_UPN, upn_len,
+ (uint8_t *) upn);
+ krb5_free_unparsed_name(kr->ctx, upn);
+ if (ret != EOK) {
+ DEBUG(1, ("pack_response_packet failed.\n"));
+ goto done;
}
+done:
return ret;
}
@@ -1054,9 +1073,9 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
goto done;
}
- ret = add_ticket_times_to_response(kr);
+ ret = add_ticket_times_and_upn_to_response(kr);
if (ret != EOK) {
- DEBUG(1, ("add_ticket_times_to_response failed.\n"));
+ DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
}
kerr = 0;
@@ -1447,9 +1466,9 @@ static errno_t renew_tgt_child(int fd, struct krb5_req *kr)
goto done;
}
- ret = add_ticket_times_to_response(kr);
+ ret = add_ticket_times_and_upn_to_response(kr);
if (ret != EOK) {
- DEBUG(1, ("add_ticket_times_to_response failed.\n"));
+ DEBUG(1, ("add_ticket_times_and_upn_to_response failed.\n"));
}
status = PAM_SUCCESS;
diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
index f0fe81b6f..e792db3f7 100644
--- a/src/providers/krb5/krb5_child_handler.c
+++ b/src/providers/krb5/krb5_child_handler.c
@@ -441,6 +441,8 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
uint32_t *expiration;
uint32_t *msg_subtype;
struct krb5_child_response *res;
+ const char *upn = NULL;
+ size_t upn_len;
if ((size_t) len < sizeof(int32_t)) {
DEBUG(SSSDBG_CRIT_FAILURE, ("message too short.\n"));
@@ -505,6 +507,11 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
tgtt.authtime, tgtt.starttime, tgtt.endtime, tgtt.renew_till));
}
+ if (msg_type == SSS_KRB5_INFO_UPN) {
+ upn = (char *) buf + p;
+ upn_len = msg_len;
+ }
+
if (msg_type == SSS_PAM_USER_INFO) {
msg_subtype = (uint32_t *)&buf[p];
if (*msg_subtype == SSS_PAM_USER_INFO_EXPIRE_WARN)
@@ -549,6 +556,15 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len,
}
}
+ if (upn != NULL) {
+ res->correct_upn = talloc_strndup(res, upn, upn_len);
+ if (res->correct_upn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strndup failed.\n"));
+ talloc_free(res);
+ return ENOMEM;
+ }
+ }
+
*_res = res;
return EOK;
}