diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/external/pac_responder.m4 | 2 | ||||
-rw-r--r-- | src/providers/krb5/krb5_child.c | 122 | ||||
-rw-r--r-- | src/util/sss_krb5.c | 111 | ||||
-rw-r--r-- | src/util/sss_krb5.h | 7 |
4 files changed, 138 insertions, 104 deletions
diff --git a/src/external/pac_responder.m4 b/src/external/pac_responder.m4 index 91c8263a..0aadd40b 100644 --- a/src/external/pac_responder.m4 +++ b/src/external/pac_responder.m4 @@ -30,3 +30,5 @@ then fi AM_CONDITIONAL([BUILD_PAC_RESPONDER], [test x$build_pac_responder = xyes -a x$ndr_krb5pac_ok = xyes -a x$krb5_version_ok = xyes ]) +AM_COND_IF([BUILD_PAC_RESPONDER], + [AC_DEFINE_UNQUOTED(HAVE_PAC_RESPONDER, 1, [Build with the PAC responder])]) diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index e7776248..8a68f275 100644 --- a/src/providers/krb5/krb5_child.c +++ b/src/providers/krb5/krb5_child.c @@ -101,94 +101,12 @@ struct krb5_req { static krb5_context krb5_error_ctx; #define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error) -static krb5_error_code extract_and_send_pac(struct krb5_req *kr, - krb5_ccache ccache, - krb5_principal server_principal, - krb5_principal client_principal, - krb5_keytab keytab) + +static errno_t sss_send_pac(krb5_authdata **pac_authdata) { - krb5_error_code kerr; - krb5_creds mcred; - krb5_creds cred; - krb5_authdata **pac_authdata = NULL; - krb5_pac pac = NULL; struct sss_cli_req_data sss_data; int ret; int errnop; - krb5_ticket *ticket = NULL; - krb5_keytab_entry entry; - - memset(&entry, 0, sizeof(entry)); - memset(&mcred, 0, sizeof(mcred)); - memset(&cred, 0, sizeof(mcred)); - - mcred.server = server_principal; - mcred.client = client_principal; - - kerr = krb5_cc_retrieve_cred(kr->ctx, ccache, 0, &mcred, &cred); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_retrieve_cred failed.\n")); - goto done; - } - - kerr = krb5_decode_ticket(&cred.ticket, &ticket); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_decode_ticket failed.\n")); - goto done; - } - - kerr = krb5_server_decrypt_ticket_keytab(kr->ctx, keytab, ticket); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_server_decrypt_ticket_keytab failed.\n")); - goto done; - } - - kerr = sss_krb5_find_authdata(kr->ctx, - ticket->enc_part2->authorization_data, NULL, - KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_find_authdata failed.\n")); - goto done; - } - - if (pac_authdata == NULL || pac_authdata[0] == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("No PAC authdata available.\n")); - kerr = ENOENT; - goto done; - } - - if (pac_authdata[1] != NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("More than one PAC autdata found.\n")); - kerr = EINVAL; - goto done; - } - - kerr = krb5_pac_parse(kr->ctx, pac_authdata[0]->contents, - pac_authdata[0]->length, &pac); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_parse failed.\n")); - goto done; - } - - kerr = krb5_kt_get_entry(kr->ctx, keytab, ticket->server, - ticket->enc_part.kvno, ticket->enc_part.enctype, - &entry); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_kt_get_entry failed.\n")); - goto done; - } - - kerr = krb5_pac_verify(kr->ctx, pac, 0, NULL, &entry.key, NULL); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_verify failed.\n")); - goto done; - } - - ret = unsetenv("_SSS_LOOPS"); - if (ret != EOK) { - DEBUG(1, ("Failed to unset _SSS_LOOPS, " - "sss_pac_make_request will most certainly fail.\n")); - } sss_data.len = pac_authdata[0]->length; sss_data.data = pac_authdata[0]->contents; @@ -198,25 +116,10 @@ static krb5_error_code extract_and_send_pac(struct krb5_req *kr, if (ret != NSS_STATUS_SUCCESS || errnop != 0) { DEBUG(SSSDBG_OP_FAILURE, ("sss_pac_make_request failed [%d][%d].\n", ret, errnop)); - kerr = EIO; - goto done; - } - - kerr = 0; - -done: - if (entry.magic != 0) { - krb5_free_keytab_entry_contents(kr->ctx, &entry); - } - krb5_pac_free(kr->ctx, pac); - krb5_free_authdata(kr->ctx, pac_authdata); - if (ticket != NULL) { - krb5_free_ticket(kr->ctx, ticket); + return EIO; } - krb5_free_cred_contents(kr->ctx, &cred); - - return kerr; + return EOK; } static void sss_krb5_expire_callback_func(krb5_context context, void *data, @@ -835,6 +738,7 @@ static krb5_error_code validate_tgt(struct krb5_req *kr) krb5_principal validation_princ = NULL; bool realm_entry_found = false; krb5_ccache validation_ccache = NULL; + krb5_authdata **pac_authdata = NULL; memset(&keytab, 0, sizeof(keytab)); kerr = krb5_kt_resolve(kr->ctx, kr->keytab, &keytab); @@ -931,10 +835,20 @@ static krb5_error_code validate_tgt(struct krb5_req *kr) /* Try to find and send the PAC to the PAC responder for principals which * do not belong to our realm. Failures are not critical. */ if (kr->upn_from_different_realm) { - kerr = extract_and_send_pac(kr, validation_ccache, validation_princ, - kr->creds->client, keytab); + kerr = sss_extract_pac(kr->ctx, validation_ccache, validation_princ, + kr->creds->client, keytab, &pac_authdata); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("sss_extract_and_send_pac failed, group " \ + "membership for user with principal [%s] " \ + "might not be correct.\n", kr->name)); + kerr = 0; + goto done; + } + + kerr = sss_send_pac(pac_authdata); + krb5_free_authdata(kr->ctx, pac_authdata); if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, ("extract_and_send_pac failed, group " \ + DEBUG(SSSDBG_OP_FAILURE, ("sss_send_pac failed, group " \ "membership for user with principal [%s] " \ "might not be correct.\n", kr->name)); kerr = 0; diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c index cbee96e8..38374578 100644 --- a/src/util/sss_krb5.c +++ b/src/util/sss_krb5.c @@ -1004,3 +1004,114 @@ krb5_error_code sss_krb5_find_authdata(krb5_context context, return ENOTSUP; #endif } + +krb5_error_code sss_extract_pac(krb5_context ctx, + krb5_ccache ccache, + krb5_principal server_principal, + krb5_principal client_principal, + krb5_keytab keytab, + krb5_authdata ***_pac_authdata) +{ +#ifdef HAVE_PAC_RESPONDER + krb5_error_code kerr; + krb5_creds mcred; + krb5_creds cred; + krb5_authdata **pac_authdata = NULL; + krb5_pac pac = NULL; + int ret; + krb5_ticket *ticket = NULL; + krb5_keytab_entry entry; + + memset(&entry, 0, sizeof(entry)); + memset(&mcred, 0, sizeof(mcred)); + memset(&cred, 0, sizeof(mcred)); + + mcred.server = server_principal; + mcred.client = client_principal; + + kerr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_cc_retrieve_cred failed.\n")); + goto done; + } + + kerr = krb5_decode_ticket(&cred.ticket, &ticket); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_decode_ticket failed.\n")); + goto done; + } + + kerr = krb5_server_decrypt_ticket_keytab(ctx, keytab, ticket); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_server_decrypt_ticket_keytab failed.\n")); + goto done; + } + + kerr = sss_krb5_find_authdata(ctx, + ticket->enc_part2->authorization_data, NULL, + KRB5_AUTHDATA_WIN2K_PAC, &pac_authdata); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_find_authdata failed.\n")); + goto done; + } + + if (pac_authdata == NULL || pac_authdata[0] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("No PAC authdata available.\n")); + kerr = ENOENT; + goto done; + } + + if (pac_authdata[1] != NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("More than one PAC autdata found.\n")); + kerr = EINVAL; + goto done; + } + + kerr = krb5_pac_parse(ctx, pac_authdata[0]->contents, + pac_authdata[0]->length, &pac); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_parse failed.\n")); + goto done; + } + + kerr = krb5_kt_get_entry(ctx, keytab, ticket->server, + ticket->enc_part.kvno, ticket->enc_part.enctype, + &entry); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_kt_get_entry failed.\n")); + goto done; + } + + kerr = krb5_pac_verify(ctx, pac, 0, NULL, &entry.key, NULL); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("krb5_pac_verify failed.\n")); + goto done; + } + + ret = unsetenv("_SSS_LOOPS"); + if (ret != EOK) { + DEBUG(1, ("Failed to unset _SSS_LOOPS, " + "sss_pac_make_request will most certainly fail.\n")); + } + + *_pac_authdata = pac_authdata; + kerr = 0; + +done: + if (kerr != 0) { + krb5_free_authdata(ctx, pac_authdata); + } + if (entry.magic != 0) { + krb5_free_keytab_entry_contents(ctx, &entry); + } + krb5_pac_free(ctx, pac); + if (ticket != NULL) { + krb5_free_ticket(ctx, ticket); + } + + krb5_free_cred_contents(ctx, &cred); + return kerr; +#else + return ENOTSUP; +#endif +} diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h index 6a61f0ea..deb0cbff 100644 --- a/src/util/sss_krb5.h +++ b/src/util/sss_krb5.h @@ -175,4 +175,11 @@ krb5_error_code sss_krb5_find_authdata(krb5_context context, krb5_authdata *const *ap_req_authdata, krb5_authdatatype ad_type, krb5_authdata ***results); + +krb5_error_code sss_extract_pac(krb5_context ctx, + krb5_ccache ccache, + krb5_principal server_principal, + krb5_principal client_principal, + krb5_keytab keytab, + krb5_authdata ***_pac_authdata); #endif /* __SSS_KRB5_H__ */ |