diff options
author | Sumit Bose <sbose@redhat.com> | 2012-10-23 21:30:17 +0200 |
---|---|---|
committer | Sumit Bose <sbose@redhat.com> | 2012-10-26 10:32:05 +0200 |
commit | d3dca30d3a6feba062d0299718d1a9fcdc8b9d17 (patch) | |
tree | 008de45d9668d85600ac2a57ed8bd460ffb95594 | |
parent | cac29dc2ece94180de33b52c113865bbab49b252 (diff) | |
download | sssd-d3dca30d3a6feba062d0299718d1a9fcdc8b9d17.tar.gz sssd-d3dca30d3a6feba062d0299718d1a9fcdc8b9d17.tar.xz sssd-d3dca30d3a6feba062d0299718d1a9fcdc8b9d17.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.h | 1 | ||||
-rw-r--r-- | src/providers/krb5/krb5_auth.h | 1 | ||||
-rw-r--r-- | src/providers/krb5/krb5_child.c | 29 | ||||
-rw-r--r-- | src/providers/krb5/krb5_child_handler.c | 16 |
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; } |