diff options
author | Christof Schmitt <christof.schmitt@us.ibm.com> | 2012-07-18 14:38:47 -0700 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-09-20 19:49:32 -0700 |
commit | 1bc2f28b9420829645ed571daf2a17e6688b2103 (patch) | |
tree | 24001ed654ed1634f3f9f48f075010a02a4052d7 /source3/winbindd/winbindd_pam.c | |
parent | 8a6a13ab51f404525ff18f65d5a22132c465898e (diff) | |
download | samba-1bc2f28b9420829645ed571daf2a17e6688b2103.tar.gz samba-1bc2f28b9420829645ed571daf2a17e6688b2103.tar.bz2 samba-1bc2f28b9420829645ed571daf2a17e6688b2103.zip |
winbind: Extend wbcAuthenticateUserEx to provide PAC
With this new interface, external applications that have authenticated
to an ADS can pass the PAC from the Kerberos ticket to
wbcAuthenticateUserEx. winbindd decodes and extracts the info3
information for the external application. If winbindd can verify the PAC
signature, the info3 from the PACis also added to the netsamlogon_cache.
The info3 data can be used by the external application to get the uid
and primary gid. The data in netsamlogon_cache allows to retrieve the
complete group list through the NSS function getgrouplist.
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source3/winbindd/winbindd_pam.c')
-rw-r--r-- | source3/winbindd/winbindd_pam.c | 128 |
1 files changed, 122 insertions, 6 deletions
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 6ad0baf196..5b6b77b48c 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -38,6 +38,9 @@ #include "passdb/machine_sid.h" #include "auth.h" #include "../lib/tsocket/tsocket.h" +#include "auth/kerberos/pac_utils.h" +#include "auth/gensec/gensec.h" +#include "librpc/crypto/gse_krb5.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -724,12 +727,12 @@ bool check_request_flags(uint32_t flags) /**************************************************************** ****************************************************************/ -static NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx, - struct winbindd_response *resp, - uint32_t request_flags, - struct netr_SamInfo3 *info3, - const char *name_domain, - const char *name_user) +NTSTATUS append_auth_data(TALLOC_CTX *mem_ctx, + struct winbindd_response *resp, + uint32_t request_flags, + struct netr_SamInfo3 *info3, + const char *name_domain, + const char *name_user) { NTSTATUS result; @@ -2270,3 +2273,116 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } + +#ifdef HAVE_KRB5 +static NTSTATUS extract_pac_vrfy_sigs(TALLOC_CTX *mem_ctx, DATA_BLOB pac_blob, + struct PAC_LOGON_INFO **logon_info) +{ + krb5_context krbctx = NULL; + krb5_error_code k5ret; + krb5_keytab keytab; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(entry); + ZERO_STRUCT(cursor); + + k5ret = krb5_init_context(&krbctx); + if (k5ret) { + DEBUG(1, ("Failed to initialize kerberos context: %s\n", + error_message(k5ret))); + status = krb5_to_nt_status(k5ret); + goto out; + } + + k5ret = gse_krb5_get_server_keytab(krbctx, &keytab); + if (k5ret) { + DEBUG(1, ("Failed to get keytab: %s\n", + error_message(k5ret))); + status = krb5_to_nt_status(k5ret); + goto out_free; + } + + k5ret = krb5_kt_start_seq_get(krbctx, keytab, &cursor); + if (k5ret) { + DEBUG(1, ("Failed to start seq: %s\n", + error_message(k5ret))); + status = krb5_to_nt_status(k5ret); + goto out_keytab; + } + + k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor); + while (k5ret == 0) { + status = kerberos_pac_logon_info(mem_ctx, pac_blob, + krbctx, NULL, + KRB5_KT_KEY(&entry), NULL, 0, + logon_info); + if (NT_STATUS_IS_OK(status)) { + break; + } + k5ret = smb_krb5_kt_free_entry(krbctx, &entry); + k5ret = krb5_kt_next_entry(krbctx, keytab, &entry, &cursor); + } + + k5ret = krb5_kt_end_seq_get(krbctx, keytab, &cursor); + if (k5ret) { + DEBUG(1, ("Failed to end seq: %s\n", + error_message(k5ret))); + } +out_keytab: + k5ret = krb5_kt_close(krbctx, keytab); + if (k5ret) { + DEBUG(1, ("Failed to close keytab: %s\n", + error_message(k5ret))); + } +out_free: + krb5_free_context(krbctx); +out: + return status; +} + +NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3) +{ + struct winbindd_request *req = state->request; + DATA_BLOB pac_blob; + struct PAC_LOGON_INFO *logon_info = NULL; + NTSTATUS result; + + pac_blob = data_blob_const(req->extra_data.data, req->extra_len); + result = extract_pac_vrfy_sigs(state->mem_ctx, pac_blob, &logon_info); + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) { + DEBUG(1, ("Error during PAC signature verification: %s\n", + nt_errstr(result))); + return result; + } + + if (logon_info) { + /* Signature verification succeeded, trust the PAC */ + netsamlogon_cache_store(NULL, &logon_info->info3); + + } else { + /* Try without signature verification */ + result = kerberos_pac_logon_info(state->mem_ctx, pac_blob, NULL, + NULL, NULL, NULL, 0, + &logon_info); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10, ("Could not extract PAC: %s\n", + nt_errstr(result))); + return result; + } + } + + *info3 = &logon_info->info3; + + return NT_STATUS_OK; +} +#else /* HAVE_KRB5 */ +NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3) +{ + return NT_STATUS_NO_SUCH_USER; +} +#endif /* HAVE_KRB5 */ |