From d5a9f18e748bc4e30dc638f411c45d6066c6d624 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 18 Jul 2012 14:38:47 -0700 Subject: [PATCH 01/11] 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 (cherry picked from commit 1bc2f28b9420829645ed571daf2a17e6688b2103) --- nsswitch/libwbclient/wbc_pam.c | 16 +++- nsswitch/libwbclient/wbclient.h | 42 +++++----- nsswitch/winbind_struct_protocol.h | 1 + source3/winbindd/winbindd_pam.c | 128 +++++++++++++++++++++++++++-- source3/winbindd/winbindd_pam_auth_crap.c | 23 ++++++ source3/winbindd/winbindd_proto.h | 8 ++ 6 files changed, 191 insertions(+), 27 deletions(-) diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c index f7fb9f2..f183cc6 100644 --- a/nsswitch/libwbclient/wbc_pam.c +++ b/nsswitch/libwbclient/wbc_pam.c @@ -364,7 +364,7 @@ wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, BAIL_ON_WBC_ERROR(wbc_status); } - if (!params->account_name) { + if (params->level != WBC_AUTH_USER_LEVEL_PAC && !params->account_name) { wbc_status = WBC_ERR_INVALID_PARAM; BAIL_ON_WBC_ERROR(wbc_status); } @@ -491,6 +491,20 @@ wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params, request.data.auth_crap.nt_resp_len); } break; + + case WBC_AUTH_USER_LEVEL_PAC: + cmd = WINBINDD_PAM_AUTH_CRAP; + request.flags = WBFLAG_PAM_AUTH_PAC | WBFLAG_PAM_INFO3_TEXT; + request.extra_data.data = malloc(params->password.pac.length); + if (request.extra_data.data == NULL) { + wbc_status = WBC_ERR_NO_MEMORY; + BAIL_ON_WBC_ERROR(wbc_status); + } + memcpy(request.extra_data.data, params->password.pac.data, + params->password.pac.length); + request.extra_len = params->password.pac.length; + break; + default: break; } diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h index cb70cbd..473c901 100644 --- a/nsswitch/libwbclient/wbclient.h +++ b/nsswitch/libwbclient/wbclient.h @@ -197,6 +197,25 @@ struct wbcDomainInfo { #define WBC_DOMINFO_TRUSTTYPE_EXTERNAL 0x00000003 /** + * @brief Generic Blob + **/ + +struct wbcBlob { + uint8_t *data; + size_t length; +}; + +/** + * @brief Named Blob + **/ + +struct wbcNamedBlob { + const char *name; + uint32_t flags; + struct wbcBlob blob; +}; + +/** * @brief Auth User Parameters **/ @@ -212,7 +231,8 @@ struct wbcAuthUserParams { enum wbcAuthUserLevel { WBC_AUTH_USER_LEVEL_PLAIN = 1, WBC_AUTH_USER_LEVEL_HASH = 2, - WBC_AUTH_USER_LEVEL_RESPONSE = 3 + WBC_AUTH_USER_LEVEL_RESPONSE = 3, + WBC_AUTH_USER_LEVEL_PAC = 4 } level; union { const char *plaintext; @@ -227,29 +247,11 @@ struct wbcAuthUserParams { uint32_t lm_length; uint8_t *lm_data; } response; + struct wbcBlob pac; } password; }; /** - * @brief Generic Blob - **/ - -struct wbcBlob { - uint8_t *data; - size_t length; -}; - -/** - * @brief Named Blob - **/ - -struct wbcNamedBlob { - const char *name; - uint32_t flags; - struct wbcBlob blob; -}; - -/** * @brief Logon User Parameters **/ diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h index e5ed8e1..c1704c8 100644 --- a/nsswitch/winbind_struct_protocol.h +++ b/nsswitch/winbind_struct_protocol.h @@ -218,6 +218,7 @@ typedef struct winbindd_gr { #define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x00002000 #define WBFLAG_PAM_CACHED_LOGIN 0x00004000 #define WBFLAG_PAM_GET_PWD_POLICY 0x00008000 +#define WBFLAG_PAM_AUTH_PAC 0x00010000 /* generic request flags */ #define WBFLAG_QUERY_ONLY 0x00000020 /* not used */ diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 6ad0baf..5b6b77b 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 */ diff --git a/source3/winbindd/winbindd_pam_auth_crap.c b/source3/winbindd/winbindd_pam_auth_crap.c index 2fb5111..ffbc322 100644 --- a/source3/winbindd/winbindd_pam_auth_crap.c +++ b/source3/winbindd/winbindd_pam_auth_crap.c @@ -22,6 +22,8 @@ struct winbindd_pam_auth_crap_state { struct winbindd_response *response; + struct netr_SamInfo3 *info3; + uint32_t flags; }; static void winbindd_pam_auth_crap_done(struct tevent_req *subreq); @@ -42,6 +44,21 @@ struct tevent_req *winbindd_pam_auth_crap_send( return NULL; } + if (request->flags & WBFLAG_PAM_AUTH_PAC) { + NTSTATUS status; + + state->flags = request->flags; + status = winbindd_pam_auth_pac_send(cli, &state->info3); + if (NT_STATUS_IS_OK(status)) { + /* Defer filling out response to recv */ + tevent_req_done(req); + } else { + tevent_req_nterror(req, status); + } + + return tevent_req_post(req, ev); + } + /* Ensure null termination */ request->data.auth_crap.user[ sizeof(request->data.auth_crap.user)-1] = '\0'; @@ -114,6 +131,12 @@ NTSTATUS winbindd_pam_auth_crap_recv(struct tevent_req *req, set_auth_errors(response, status); return status; } + + if (state->flags & WBFLAG_PAM_AUTH_PAC) { + return append_auth_data(response, response, state->flags, + state->info3, NULL, NULL); + } + *response = *state->response; response->result = WINBINDD_PENDING; state->response = talloc_move(response, &state->response); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index ec5ec37..5cc90f2 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -353,6 +353,12 @@ void ndr_print_winbindd_domain(struct ndr_print *ndr, /* The following definitions come from winbindd/winbindd_pam.c */ bool check_request_flags(uint32_t flags); +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); uid_t get_uid_from_request(struct winbindd_request *request); struct winbindd_domain *find_auth_domain(uint8_t flags, const char *domain_name); @@ -365,6 +371,8 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain, struct winbindd_cli_state *state) ; enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domain *domainSt, struct winbindd_cli_state *state); +NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, + struct netr_SamInfo3 **info3); /* The following definitions come from winbindd/winbindd_util.c */ -- 1.7.9.5 From f80c9354499ca6e864b129b60004f38ae698a688 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Mon, 30 Jul 2012 11:03:54 -0700 Subject: [PATCH 02/11] auth/kerberos: Adjust log level for failed PAC signature verification With winbindd trying to verify the signature of an application provided PAC, this message can be easily triggered. Adjust the debug level to avoid filling up the logs. Signed-off-by: Andrew Bartlett (cherry picked from commit 05befd2f734d3962619ebc0cc137bbe5cedfd81d) --- auth/kerberos/kerberos_pac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/kerberos/kerberos_pac.c b/auth/kerberos/kerberos_pac.c index 80f31d8..81f7f21 100644 --- a/auth/kerberos/kerberos_pac.c +++ b/auth/kerberos/kerberos_pac.c @@ -322,7 +322,7 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, context, service_keyblock); if (ret) { - DEBUG(1, ("PAC Decode: Failed to verify the service " + DEBUG(5, ("PAC Decode: Failed to verify the service " "signature: %s\n", error_message(ret))); return NT_STATUS_ACCESS_DENIED; } -- 1.7.9.5 From 243dac7fc343c156248304f38a94e9bcac528bb7 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Thu, 20 Sep 2012 18:30:07 -0700 Subject: [PATCH 03/11] s4-torture: Complete test for winbindd PAC parsing Decode the PAC through the wbcAuthenticateUserEx call, also decode it locally and compare the result. Signed-off-by: Andrew Bartlett (cherry picked from commit d9747b15c4a737a1422d0156d92efed762bb672d) --- source4/torture/winbind/winbind.c | 92 ++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/source4/torture/winbind/winbind.c b/source4/torture/winbind/winbind.c index cb895f5..5956834 100644 --- a/source4/torture/winbind/winbind.c +++ b/source4/torture/winbind/winbind.c @@ -3,6 +3,7 @@ SMB torture tester Copyright (C) Stefan Metzmacher 2007 Copyright (C) Andrew Bartlett 2012 + Copyright (C) Christof Schmit 2012 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +30,8 @@ #include "auth/credentials/credentials.h" #include "param/param.h" #include "lib/cmdline/popt_common.h" +#include "auth/kerberos/pac_utils.h" +#include "wbclient.h" struct pac_data { DATA_BLOB pac_blob; @@ -88,9 +91,89 @@ static NTSTATUS test_generate_session_info_pac(struct auth4_context *auth_ctx, return nt_status; } -/* Check to see if we can pass the PAC across to the NETLOGON server for validation */ +static bool torture_decode_compare_pac(struct torture_context *tctx, + DATA_BLOB pac) +{ + struct wbcAuthUserParams params; + struct wbcAuthUserInfo *info; + struct wbcAuthErrorInfo *error; + struct PAC_LOGON_INFO *logon_info; + struct netr_SamInfo3 *info3; + struct netr_SamBaseInfo *base; + wbcErr wbc_err; + NTSTATUS status; + int result, sid_idx, i; + char sid_str[50]; + + /* Let winbind decode the PAC */ + memset(¶ms, 0, sizeof(params)); + params.level = WBC_AUTH_USER_LEVEL_PAC; + params.password.pac.data = pac.data; + params.password.pac.length = pac.length; + + wbc_err = wbcAuthenticateUserEx(¶ms, &info, &error); + torture_assert(tctx, WBC_ERROR_IS_OK(wbc_err), wbcErrorString(wbc_err)); + + /* Decode the PAC internally */ + status = kerberos_pac_logon_info(tctx, pac, NULL, NULL, NULL, NULL, 0, + &logon_info); + torture_assert(tctx, NT_STATUS_IS_OK(status), "pac_logon_info"); + info3 = &logon_info->info3; + base = &info3->base; + + /* Compare the decoded data from winbind and from internal call */ + torture_assert(tctx, info->user_flags == base->user_flags, "user_flags"); + torture_assert_str_equal(tctx, info->account_name, base->account_name.string, "account_name"); + torture_assert_str_equal(tctx, info->full_name, base->full_name.string, "full_name"); + torture_assert_str_equal(tctx, info->domain_name, base->logon_domain.string, "domain_name"); + torture_assert(tctx, info->acct_flags == base->acct_flags, "acct_flags"); + torture_assert(tctx, info->logon_count == base->logon_count, "logon_count"); + torture_assert(tctx, info->bad_password_count == base->bad_password_count, "bad_password_count"); + torture_assert(tctx, info->logon_time == nt_time_to_unix(base->logon_time), "logon_time"); + torture_assert(tctx, info->logoff_time == nt_time_to_unix(base->logoff_time), "logoff_time"); + torture_assert(tctx, info->kickoff_time == nt_time_to_unix(base->kickoff_time), "kickoff_time"); + torture_assert(tctx, info->pass_last_set_time == nt_time_to_unix(base->last_password_change), "last_password_change"); + torture_assert(tctx, info->pass_can_change_time == nt_time_to_unix(base->allow_password_change), "allow_password_change"); + torture_assert(tctx, info->pass_must_change_time == nt_time_to_unix(base->force_password_change), "force_password_change"); + torture_assert(tctx, info->num_sids == 2 + base->groups.count + info3->sidcount, "num_sids"); + + sid_idx = 0; + wbcSidToStringBuf(&info->sids[sid_idx].sid, sid_str, sizeof(sid_str)); + torture_assert(tctx, + dom_sid_equal(dom_sid_parse_talloc(tctx, sid_str), + dom_sid_add_rid(tctx, base->domain_sid, base->rid)), + sid_str); + + sid_idx++; + wbcSidToStringBuf(&info->sids[sid_idx].sid, sid_str, sizeof(sid_str)); + torture_assert(tctx, + dom_sid_equal(dom_sid_parse_talloc(tctx, sid_str), + dom_sid_add_rid(tctx, base->domain_sid, base->primary_gid)), + sid_str); + + for(i = 0; i < base->groups.count; i++ ) { + sid_idx++; + wbcSidToStringBuf(&info->sids[sid_idx].sid, + sid_str, sizeof(sid_str)); + torture_assert(tctx, + dom_sid_equal(dom_sid_parse_talloc(tctx, sid_str), + dom_sid_add_rid(tctx, base->domain_sid, + base->groups.rids[i].rid)), + sid_str); + } + + for(i = 0; i < info3->sidcount; i++) { + sid_idx++; + wbcSidToStringBuf(&info->sids[sid_idx].sid, + sid_str, sizeof(sid_str)); + torture_assert(tctx, + dom_sid_equal(dom_sid_parse_talloc(tctx, sid_str), + info3->sids[i].sid), + sid_str); + } -/* Also happens to be a really good one-step verfication of our Kerberos stack */ + return true; +} static bool torture_winbind_pac(struct torture_context *tctx) { @@ -164,14 +247,11 @@ static bool torture_winbind_pac(struct torture_context *tctx) torture_assert(tctx, pac_data != NULL, "gensec_update failed to fill in pac_data in auth_context"); torture_assert(tctx, pac_data->pac_blob.data != NULL, "pac_blob not present"); - - /* TODO: Check the PAC blob with winbind */ + torture_decode_compare_pac(tctx, pac_data->pac_blob); return true; } - - NTSTATUS torture_winbind_init(void) { struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "winbind"); -- 1.7.9.5 From 5ddc977087004f85563afb4495beb5e971d2a7d4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 20 Sep 2012 19:46:31 -0700 Subject: [PATCH 04/11] libwbclient: bump ABI to 0.11 as wbcAuthenticateUserEx now provides PAC parsing Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri Sep 21 06:37:15 CEST 2012 on sn-devel-104 (cherry picked from commit 914b02be5a3e7805110f517e39ed9f6fe760c2bc) --- nsswitch/libwbclient/ABI/wbclient-0.11.sigs | 76 +++++++++++++++++++++++++++ nsswitch/libwbclient/wbclient.h | 3 +- nsswitch/libwbclient/wscript | 2 +- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 nsswitch/libwbclient/ABI/wbclient-0.11.sigs diff --git a/nsswitch/libwbclient/ABI/wbclient-0.11.sigs b/nsswitch/libwbclient/ABI/wbclient-0.11.sigs new file mode 100644 index 0000000..eda96f4 --- /dev/null +++ b/nsswitch/libwbclient/ABI/wbclient-0.11.sigs @@ -0,0 +1,76 @@ +wbcAddNamedBlob: wbcErr (size_t *, struct wbcNamedBlob **, const char *, uint32_t, uint8_t *, size_t) +wbcAllocateGid: wbcErr (gid_t *) +wbcAllocateMemory: void *(size_t, size_t, void (*)(void *)) +wbcAllocateStringArray: const char **(int) +wbcAllocateUid: wbcErr (uid_t *) +wbcAuthenticateUser: wbcErr (const char *, const char *) +wbcAuthenticateUserEx: wbcErr (const struct wbcAuthUserParams *, struct wbcAuthUserInfo **, struct wbcAuthErrorInfo **) +wbcChangeTrustCredentials: wbcErr (const char *, struct wbcAuthErrorInfo **) +wbcChangeUserPassword: wbcErr (const char *, const char *, const char *) +wbcChangeUserPasswordEx: wbcErr (const struct wbcChangePasswordParams *, struct wbcAuthErrorInfo **, enum wbcPasswordChangeRejectReason *, struct wbcUserPasswordPolicyInfo **) +wbcCheckTrustCredentials: wbcErr (const char *, struct wbcAuthErrorInfo **) +wbcCredentialCache: wbcErr (struct wbcCredentialCacheParams *, struct wbcCredentialCacheInfo **, struct wbcAuthErrorInfo **) +wbcCredentialSave: wbcErr (const char *, const char *) +wbcDcInfo: wbcErr (const char *, size_t *, const char ***, const char ***) +wbcDomainInfo: wbcErr (const char *, struct wbcDomainInfo **) +wbcEndgrent: wbcErr (void) +wbcEndpwent: wbcErr (void) +wbcErrorString: const char *(wbcErr) +wbcFreeMemory: void (void *) +wbcGetDisplayName: wbcErr (const struct wbcDomainSid *, char **, char **, enum wbcSidType *) +wbcGetGroups: wbcErr (const char *, uint32_t *, gid_t **) +wbcGetSidAliases: wbcErr (const struct wbcDomainSid *, struct wbcDomainSid *, uint32_t, uint32_t **, uint32_t *) +wbcGetgrent: wbcErr (struct group **) +wbcGetgrgid: wbcErr (gid_t, struct group **) +wbcGetgrlist: wbcErr (struct group **) +wbcGetgrnam: wbcErr (const char *, struct group **) +wbcGetpwent: wbcErr (struct passwd **) +wbcGetpwnam: wbcErr (const char *, struct passwd **) +wbcGetpwsid: wbcErr (struct wbcDomainSid *, struct passwd **) +wbcGetpwuid: wbcErr (uid_t, struct passwd **) +wbcGidToSid: wbcErr (gid_t, struct wbcDomainSid *) +wbcGuidToString: wbcErr (const struct wbcGuid *, char **) +wbcInterfaceDetails: wbcErr (struct wbcInterfaceDetails **) +wbcLibraryDetails: wbcErr (struct wbcLibraryDetails **) +wbcListGroups: wbcErr (const char *, uint32_t *, const char ***) +wbcListTrusts: wbcErr (struct wbcDomainInfo **, size_t *) +wbcListUsers: wbcErr (const char *, uint32_t *, const char ***) +wbcLogoffUser: wbcErr (const char *, uid_t, const char *) +wbcLogoffUserEx: wbcErr (const struct wbcLogoffUserParams *, struct wbcAuthErrorInfo **) +wbcLogonUser: wbcErr (const struct wbcLogonUserParams *, struct wbcLogonUserInfo **, struct wbcAuthErrorInfo **, struct wbcUserPasswordPolicyInfo **) +wbcLookupDomainController: wbcErr (const char *, uint32_t, struct wbcDomainControllerInfo **) +wbcLookupDomainControllerEx: wbcErr (const char *, struct wbcGuid *, const char *, uint32_t, struct wbcDomainControllerInfoEx **) +wbcLookupName: wbcErr (const char *, const char *, struct wbcDomainSid *, enum wbcSidType *) +wbcLookupRids: wbcErr (struct wbcDomainSid *, int, uint32_t *, const char **, const char ***, enum wbcSidType **) +wbcLookupSid: wbcErr (const struct wbcDomainSid *, char **, char **, enum wbcSidType *) +wbcLookupSids: wbcErr (const struct wbcDomainSid *, int, struct wbcDomainInfo **, int *, struct wbcTranslatedName **) +wbcLookupUserSids: wbcErr (const struct wbcDomainSid *, bool, uint32_t *, struct wbcDomainSid **) +wbcPing: wbcErr (void) +wbcPingDc: wbcErr (const char *, struct wbcAuthErrorInfo **) +wbcPingDc2: wbcErr (const char *, struct wbcAuthErrorInfo **, char **) +wbcQueryGidToSid: wbcErr (gid_t, struct wbcDomainSid *) +wbcQuerySidToGid: wbcErr (const struct wbcDomainSid *, gid_t *) +wbcQuerySidToUid: wbcErr (const struct wbcDomainSid *, uid_t *) +wbcQueryUidToSid: wbcErr (uid_t, struct wbcDomainSid *) +wbcRemoveGidMapping: wbcErr (gid_t, const struct wbcDomainSid *) +wbcRemoveUidMapping: wbcErr (uid_t, const struct wbcDomainSid *) +wbcRequestResponse: wbcErr (int, struct winbindd_request *, struct winbindd_response *) +wbcRequestResponsePriv: wbcErr (int, struct winbindd_request *, struct winbindd_response *) +wbcResolveWinsByIP: wbcErr (const char *, char **) +wbcResolveWinsByName: wbcErr (const char *, char **) +wbcSetGidHwm: wbcErr (gid_t) +wbcSetGidMapping: wbcErr (gid_t, const struct wbcDomainSid *) +wbcSetUidHwm: wbcErr (uid_t) +wbcSetUidMapping: wbcErr (uid_t, const struct wbcDomainSid *) +wbcSetgrent: wbcErr (void) +wbcSetpwent: wbcErr (void) +wbcSidToGid: wbcErr (const struct wbcDomainSid *, gid_t *) +wbcSidToString: wbcErr (const struct wbcDomainSid *, char **) +wbcSidToStringBuf: int (const struct wbcDomainSid *, char *, int) +wbcSidToUid: wbcErr (const struct wbcDomainSid *, uid_t *) +wbcSidTypeString: const char *(enum wbcSidType) +wbcSidsToUnixIds: wbcErr (const struct wbcDomainSid *, uint32_t, struct wbcUnixId *) +wbcStrDup: char *(const char *) +wbcStringToGuid: wbcErr (const char *, struct wbcGuid *) +wbcStringToSid: wbcErr (const char *, struct wbcDomainSid *) +wbcUidToSid: wbcErr (uid_t, struct wbcDomainSid *) diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h index 473c901..a72d09e 100644 --- a/nsswitch/libwbclient/wbclient.h +++ b/nsswitch/libwbclient/wbclient.h @@ -70,9 +70,10 @@ const char *wbcErrorString(wbcErr error); * 0.8: Added wbcSidsToUnixIds() and wbcLookupSids() * 0.9: Added support for WBC_ID_TYPE_BOTH * 0.10: Added wbcPingDc2() + * 0.11: Extended wbcAuthenticateUserEx to provide PAC parsing **/ #define WBCLIENT_MAJOR_VERSION 0 -#define WBCLIENT_MINOR_VERSION 10 +#define WBCLIENT_MINOR_VERSION 11 #define WBCLIENT_VENDOR_VERSION "Samba libwbclient" struct wbcLibraryDetails { uint16_t major_version; diff --git a/nsswitch/libwbclient/wscript b/nsswitch/libwbclient/wscript index f73af94..9c4da16 100644 --- a/nsswitch/libwbclient/wscript +++ b/nsswitch/libwbclient/wscript @@ -3,7 +3,7 @@ import Options, Logs # Remember to also update wbclient.h -VERSION="0.10" +VERSION="0.11" # It may be useful at some point to allow Samba to build against a # system libwbclient, such as the one provided by Likewise. To to -- 1.7.9.5 From 72554cbde8c1e20252959c17042d2ea0d06f973f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Sep 2012 18:09:20 +1000 Subject: [PATCH 05/11] nsswitch: Add waf tests for solaris special cases These are in configure.in for autoconf. Found in the config.h comparison on the smbtorture4 build. Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Sep 26 11:50:10 CEST 2012 on sn-devel-104 (cherry picked from commit 968da5f890a978f482f56f9eaff0c56a0d52980c) --- nsswitch/wscript_configure | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nsswitch/wscript_configure b/nsswitch/wscript_configure index 7d6ea82..3048f48 100644 --- a/nsswitch/wscript_configure +++ b/nsswitch/wscript_configure @@ -4,3 +4,19 @@ conf.CHECK_HEADERS('nss.h nss_common.h ns_api.h') conf.CHECK_HEADERS('security/pam_appl.h security/pam_modules.h pam/pam_modules.h', together=True) conf.CHECK_FUNCS_IN('pam_start', 'pam', checklibc=True, headers='security/pam_appl.h') + +# Solaris 10 does have new member in nss_XbyY_key +conf.CHECK_STRUCTURE_MEMBER('union nss_XbyY_key', 'ipnode.af_family', + define='HAVE_NSS_XBYY_KEY_IPNODE', + headers='nss_dbdefs.h') + +# Solaris has some extra fields in struct passwd that need to be +# initialised otherwise nscd crashes. + +conf.CHECK_STRUCTURE_MEMBER('struct passwd', 'pw_comment', + define='HAVE_PASSWD_PW_COMMENT', + headers='pwd.h') + +conf.CHECK_STRUCTURE_MEMBER('struct passwd', 'pw_age', + define='HAVE_PASSWD_PW_AGE', + headers='pwd.h') -- 1.7.9.5 From ada23e71c9b6ef12941cd2df489db46d2f439f9c Mon Sep 17 00:00:00 2001 From: Ira Cooper Date: Sun, 30 Sep 2012 19:02:13 +0000 Subject: [PATCH 06/11] s3: Fix libnss_winbind.so's build on Illumos/Solaris Due to not building and linking in the winbind_nss_solaris bits in addition to the linux bits, nss was broken on Solaris. Autobuild-User(master): Ira Cooper Autobuild-Date(master): Sun Sep 30 22:56:30 CEST 2012 on sn-devel-104 (cherry picked from commit 6dbe0aad260d1f6e46e58871a7ce613ca27d0bf6) --- nsswitch/winbind_nss_solaris.c | 6 ++++++ nsswitch/wscript_build | 21 ++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/nsswitch/winbind_nss_solaris.c b/nsswitch/winbind_nss_solaris.c index 5fb3764..92da859 100644 --- a/nsswitch/winbind_nss_solaris.c +++ b/nsswitch/winbind_nss_solaris.c @@ -26,6 +26,7 @@ #undef DEVELOPER + #include "winbind_client.h" #include #include @@ -34,6 +35,7 @@ #include #include "includes.h" #include + #if !defined(HPUX) #include #endif /*hpux*/ @@ -48,6 +50,10 @@ #define NSS_DEBUG(str) ; #endif +#if !defined(SMB_MALLOC_P) +#define SMB_MALLOC_P(type) (type *)malloc(sizeof(type)) +#endif + #define NSS_ARGS(args) ((nss_XbyY_args_t *)args) #ifdef HPUX diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 0802687..3931445 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -1,4 +1,5 @@ #!/usr/bin/env python +import Utils bld.SAMBA_LIBRARY('winbind-client', source='wb_common.c', @@ -13,13 +14,19 @@ bld.SAMBA_BINARY('nsstest', deps='replace dl' ) - -bld.SAMBA_LIBRARY('nss_winbind', - source='winbind_nss_linux.c', - deps='winbind-client', - realname='libnss_winbind.so.2', - vnum='2') - +if Utils.unversioned_sys_platform() == 'linux': + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_linux.c', + deps='winbind-client', + realname='libnss_winbind.so.2', + vnum='2') + +if Utils.unversioned_sys_platform() == 'sunos': + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_solaris.c winbind_nss_linux.c', + deps='winbind-client', + realname='libnss_winbind.so.2', + vnum='2') if bld.CONFIG_SET('WITH_PAM_MODULES') and bld.CONFIG_SET('HAVE_PAM_START'): bld.SAMBA_LIBRARY('pamwinbind', -- 1.7.9.5 From 750e6bf7d545a897cbd490819a1167749a93d1a2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 3 Oct 2012 16:36:34 +1000 Subject: [PATCH 07/11] selftest: Always build a linux-style nss_winbind for nss_wrapper (cherry picked from commit 0e037bfc60162aa094df3e3cda59f7b9c2327ca9) --- nsswitch/wscript_build | 9 +++++++++ selftest/target/Samba.pm | 9 +++++++++ selftest/target/Samba3.pm | 5 +---- selftest/target/Samba4.pm | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 3931445..97f0af5 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -14,6 +14,15 @@ bld.SAMBA_BINARY('nsstest', deps='replace dl' ) +# The nss_wrapper code relies strictly on the linux implementation and +# name, so compile but do not install a copy under this name. +bld.SAMBA_LIBRARY('nss_wrapper_winbind', + source='winbind_nss_linux.c', + deps='winbind-client', + realname='libnss_wrapper_winbind.so.2', + install=False, + vnum='2') + if Utils.unversioned_sys_platform() == 'linux': bld.SAMBA_LIBRARY('nss_winbind', source='winbind_nss_linux.c', diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index ec6fc48..d811053 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -64,6 +64,15 @@ sub bindir_path($$) { return $path; } +sub nss_wrapper_winbind_so_path($) { + my ($object) = @_; + my $ret = $ENV{NSS_WRAPPER_WINBIND_SO_PATH}; + if (not defined($ret)) { + $ret = bindir_path($object, "default/nsswitch/libnss-winbind.so"); + } + return $ret; +} + sub mk_krb5_conf($$) { my ($ctx, $other_realms_stanza) = @_; diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 288439c..5c86612 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1098,10 +1098,7 @@ domusers:X:$gid_domusers: $ret{SOCKET_WRAPPER_DEFAULT_IFACE} = $swiface; $ret{NSS_WRAPPER_PASSWD} = $nss_wrapper_passwd; $ret{NSS_WRAPPER_GROUP} = $nss_wrapper_group; - $ret{NSS_WRAPPER_WINBIND_SO_PATH} = $ENV{NSS_WRAPPER_WINBIND_SO_PATH}; - if (not defined($ret{NSS_WRAPPER_WINBIND_SO_PATH})) { - $ret{NSS_WRAPPER_WINBIND_SO_PATH} = Samba::bindir_path($self, "default/nsswitch/libnss-winbind.so"); - } + $ret{NSS_WRAPPER_WINBIND_SO_PATH} = Samba::nss_wrapper_winbind_so_path($self); $ret{LOCAL_PATH} = "$shrdir"; return \%ret; diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 2f36930..fbc8117 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -682,7 +682,7 @@ nogroup:x:65534:nobody SAMBA_TEST_FIFO => "$ctx->{prefix}/samba_test.fifo", SAMBA_TEST_LOG => "$ctx->{prefix}/samba_test.log", SAMBA_TEST_LOG_POS => 0, - NSS_WRAPPER_WINBIND_SO_PATH => Samba::bindir_path($self, "default/nsswitch/libnss-winbind.so"), + NSS_WRAPPER_WINBIND_SO_PATH => Samba::nss_wrapper_winbind_so_path($self), LOCAL_PATH => $ctx->{share} }; -- 1.7.9.5 From 7137e8b2430ca43424954887b5b8ed168d0661a2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 2 Oct 2012 08:12:16 +1000 Subject: [PATCH 08/11] nsswitch: Build nss_winbind on all supported platforms This matches what the autoconf build can do. Andrew Bartlett (cherry picked from commit 1f267ca10e174ec3661631df2169e381136c2540) --- nsswitch/wscript_build | 59 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 97f0af5..8499c62 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -1,5 +1,7 @@ #!/usr/bin/env python import Utils +import sys +host_os = sys.platform bld.SAMBA_LIBRARY('winbind-client', source='wb_common.c', @@ -23,19 +25,56 @@ bld.SAMBA_LIBRARY('nss_wrapper_winbind', install=False, vnum='2') -if Utils.unversioned_sys_platform() == 'linux': +# FIXME: original was *linux* | gnu* | k*bsd*-gnu | kopensolaris*-gnu) +# the search for .rfind('gnu') covers gnu* and *-gnu is that too broad? + +if (Utils.unversioned_sys_platform() == 'linux' or (host_os.rfind('gnu') > -1)): + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_linux.c', + deps='winbind-client', + realname='libnss_winbind.so.2', + vnum='2') +elif (host_os.rfind('freebsd') > -1): + # FreeBSD winbind client is implemented as a wrapper around + # the Linux version. bld.SAMBA_LIBRARY('nss_winbind', - source='winbind_nss_linux.c', - deps='winbind-client', - realname='libnss_winbind.so.2', - vnum='2') + source='winbind_nss_linux.c winbind_nss_freebsd.c', + deps='winbind-client', + realname='libnss_winbind.so.1', + vnum='1') + +elif (host_os.rfind('netbsd') > -1): + # NetBSD winbind client is implemented as a wrapper + # around the Linux version. It needs getpwent_r() to + # indicate libc's use of the correct nsdispatch API. -if Utils.unversioned_sys_platform() == 'sunos': + if bld.CONFIG_SET("HAVE_GETPWENT_R"): + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_linux.c winbind_nss_netbsd.c', + deps='winbind-client', + realname='libnss_winbind.so') +elif (host_os.rfind('irix') > -1): + bld.SAMBA_LIBRARY('ns_winbind', + source='winbind_nss_irix.c', + deps='winbind-client', + realname='libns_winbind.so') + +elif Utils.unversioned_sys_platform() == 'sunos': + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_solaris.c winbind_nss_linux.c', + deps='winbind-client', + realname='nss_winbind.so.1', + vnum='1') +elif (host_os.rfind('hpux') > -1): + bld.SAMBA_LIBRARY('nss_winbind', + source='winbind_nss_linux.c', + deps='winbind-client', + realname='libnss_winbind.so') +elif (host_os.rfind('aix') > -1): bld.SAMBA_LIBRARY('nss_winbind', - source='winbind_nss_solaris.c winbind_nss_linux.c', - deps='winbind-client', - realname='libnss_winbind.so.2', - vnum='2') + source='winbind_nss_aix.c', + deps='winbind-client', + realname='libnss_winbind.so') if bld.CONFIG_SET('WITH_PAM_MODULES') and bld.CONFIG_SET('HAVE_PAM_START'): bld.SAMBA_LIBRARY('pamwinbind', -- 1.7.9.5 From 7852dae74d219b4509b0cfc6717d1865c2363723 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 17 Oct 2012 18:03:55 +0200 Subject: [PATCH 09/11] wafsamba: If we define a realname and a soname create a symlink. This is needed that libnss_winbind.so.2 and libnss_wins.so.2 will get a corresponding symlinks. (cherry picked from commit 8490c1a503cba909b429cc3cb9c972d51dfa5ea8) --- buildtools/wafsamba/samba_install.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildtools/wafsamba/samba_install.py b/buildtools/wafsamba/samba_install.py index 5e53989..aa7f143 100644 --- a/buildtools/wafsamba/samba_install.py +++ b/buildtools/wafsamba/samba_install.py @@ -103,6 +103,8 @@ def install_library(self): if getattr(self, 'samba_realname', None): install_name = self.samba_realname install_link = None + if getattr(self, 'soname', ''): + install_link = self.soname if getattr(self, 'samba_type', None) == 'PYTHON': inst_name = bld.make_libname(t.target, nolibprefix=True, python=True) else: -- 1.7.9.5 From bcfc7985facae948f5fe12bebfdc69f49655ec84 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 17 Oct 2012 18:16:15 +0200 Subject: [PATCH 10/11] waf: Create a libnss_winbind.so symlink. This fixes bug #9299. (cherry picked from commit 1f017efeedffed84b872bd17ebefee7dfff0d11a) --- nsswitch/wscript_build | 1 + 1 file changed, 1 insertion(+) diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 8499c62..a94c02c 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -33,6 +33,7 @@ if (Utils.unversioned_sys_platform() == 'linux' or (host_os.rfind('gnu') > -1)): source='winbind_nss_linux.c', deps='winbind-client', realname='libnss_winbind.so.2', + soname='libnss_winbind.so', vnum='2') elif (host_os.rfind('freebsd') > -1): # FreeBSD winbind client is implemented as a wrapper around -- 1.7.9.5 From e1279f28a26bc481bf0e8d1bbb5449b55cfd7959 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 17 Oct 2012 18:17:27 +0200 Subject: [PATCH 11/11] waf: Create a libnss_wins.so symlink. The last 3 patches fixe bug #9299 - nsswitch modules under Linux need a symbolic to their so version library. https://bugzilla.samba.org/show_bug.cgi?id=9299 Reviewed-by: David Disseldorp Autobuild-User(master): Karolin Seeger Autobuild-Date(master): Mon Oct 22 10:48:16 CEST 2012 on sn-devel-104 (cherry picked from commit bd099c49f816f8f7faad7da34370bcec2d59a0aa) --- source3/wscript_build | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/wscript_build b/source3/wscript_build index 0db13b0..9375423 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -659,6 +659,7 @@ bld.SAMBA3_LIBRARY('nss_wins', source=WINBIND_WINS_NSS_SRC, deps='''param libsmb LIBTSOCKET''', realname='libnss_wins.so.2', + soname='libnss_wins.so', vnum='2') bld.SAMBA3_LIBRARY('gse', -- 1.7.9.5