From b7e11b9b4ef32bd4cc141ce62fe20565c9265020 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 14:16:56 +0200 Subject: [PATCH 01/10] s3-rpc_client: return info3 in rpccli_netlogon_password_logon(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Andreas Schneider --- source3/rpc_client/cli_netlogon.c | 100 +++++++++++++++++++++----------------- source3/rpc_client/cli_netlogon.h | 3 +- source3/rpcclient/cmd_netlogon.c | 3 +- 3 files changed, 60 insertions(+), 46 deletions(-) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 3d6a3e1..615ad97 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -154,6 +154,53 @@ NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, return NT_STATUS_OK; } +static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, + uint16_t validation_level, + union netr_Validation *validation, + struct netr_SamInfo3 **info3_p) +{ + struct netr_SamInfo3 *info3; + NTSTATUS status; + + if (validation == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (validation_level) { + case 3: + if (validation->sam3 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + info3 = talloc_move(mem_ctx, &validation->sam3); + break; + case 6: + if (validation->sam6 == NULL) { + return NT_STATUS_INVALID_PARAMETER; + } + + info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); + if (info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info3); + return status; + } + + info3->sidcount = validation->sam6->sidcount; + info3->sids = talloc_move(info3, &validation->sam6->sids); + break; + default: + return NT_STATUS_BAD_VALIDATION_CLASS; + } + + *info3_p = info3; + + return NT_STATUS_OK; +} + /* Logon domain user */ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, @@ -164,7 +211,8 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, const char *password, const char *workstation, uint16_t validation_level, - int logon_type) + int logon_type, + struct netr_SamInfo3 **info3) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; NTSTATUS status; @@ -302,54 +350,18 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, return NT_STATUS_ACCESS_DENIED; } - return result; -} - -static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx, - uint16_t validation_level, - union netr_Validation *validation, - struct netr_SamInfo3 **info3_p) -{ - struct netr_SamInfo3 *info3; - NTSTATUS status; - - if (validation == NULL) { - return NT_STATUS_INVALID_PARAMETER; + if (!NT_STATUS_IS_OK(result)) { + return result; } - switch (validation_level) { - case 3: - if (validation->sam3 == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - info3 = talloc_move(mem_ctx, &validation->sam3); - break; - case 6: - if (validation->sam6 == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - info3 = talloc_zero(mem_ctx, struct netr_SamInfo3); - if (info3 == NULL) { - return NT_STATUS_NO_MEMORY; - } - status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(info3); - return status; - } + netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, &validation); - info3->sidcount = validation->sam6->sidcount; - info3->sids = talloc_move(info3, &validation->sam6->sids); - break; - default: - return NT_STATUS_BAD_VALIDATION_CLASS; + result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); + if (!NT_STATUS_IS_OK(result)) { + return result; } - *info3_p = info3; - - return NT_STATUS_OK; + return result; } /** diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index ad59d5b..9c6cbc8 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -41,7 +41,8 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, const char *password, const char *workstation, uint16_t validation_level, - int logon_type); + int logon_type, + struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 logon_parameters, diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 01d6da4..f1477b2 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -750,6 +750,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, uint16_t validation_level = 3; uint32 logon_param = 0; const char *workstation = NULL; + struct netr_SamInfo3 *info3 = NULL; /* Check arguments */ @@ -776,7 +777,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, /* Perform the sam logon */ - result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, validation_level, logon_type); + result = rpccli_netlogon_sam_logon(cli, mem_ctx, logon_param, lp_workgroup(), username, password, workstation, validation_level, logon_type, &info3); if (!NT_STATUS_IS_OK(result)) goto done; -- 2.1.0 From f035e523da5add702bceba2173b1370656e8d1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 14:25:19 +0200 Subject: [PATCH 02/10] s3-winbindd: call interactive samlogon via rpccli_netlogon_password_logon. Guenther Signed-off-by: Guenther Deschner Pair-Programmed-With: Andreas Schneider Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_pam.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c356686..15323ac 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1214,11 +1214,13 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, uint32_t logon_parameters, const char *server, const char *username, + const char *password, const char *domainname, const char *workstation, const uint8_t chal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, + bool interactive, struct netr_SamInfo3 **info3) { int attempts = 0; @@ -1331,7 +1333,19 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, domain->can_do_validation6 = false; } - if (domain->can_do_samlogon_ex && domain->can_do_validation6) { + if (interactive && username != NULL && password != NULL) { + result = rpccli_netlogon_sam_logon( + netlogon_pipe, + mem_ctx, + logon_parameters, + domainname, + username, + password, + workstation, + 3, /* FIXME */ + NetlogonInteractiveInformation, + info3); + } else if (domain->can_do_samlogon_ex && domain->can_do_validation6) { result = rpccli_netlogon_sam_network_logon_ex( netlogon_pipe, mem_ctx, @@ -1515,11 +1529,13 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(TALLOC_CTX *mem_ctx, 0, domain->dcname, name_user, + pass, name_domain, lp_netbios_name(), chal, lm_resp, nt_resp, + true, &my_info3); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -1938,12 +1954,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request->data.auth_crap.logon_parameters, domain->dcname, name_user, + NULL, /* password */ name_domain, /* Bug #3248 - found by Stefan Burkei. */ workstation, /* We carefully set this above so use it... */ state->request->data.auth_crap.chal, lm_resp, nt_resp, + false, /* interactive */ &info3); if (!NT_STATUS_IS_OK(result)) { goto done; -- 2.1.0 From cc43ad67c12402f7724dbcbab7a07ee5eaae42d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 7 Jul 2014 17:14:37 +0200 Subject: [PATCH 03/10] s3-winbindd: add wcache_query_user_fullname(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper function is used to query the full name of a cached user object (for further gecos processing). Thanks to Matt Rogers . BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Guenther Pair-Programmed-With: Andreas Schneider Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_cache.c | 34 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 59ce515..d1e10e6c 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2309,6 +2309,40 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, return status; } + +/** +* @brief Query a fullname from the username cache (for further gecos processing) +* +* @param domain A pointer to the winbindd_domain struct. +* @param mem_ctx The talloc context. +* @param user_sid The user sid. +* @param full_name A pointer to the full_name string. +* +* @return NTSTATUS code +*/ +NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + const char **full_name) +{ + NTSTATUS status; + struct wbint_userinfo info; + + status = wcache_query_user(domain, mem_ctx, user_sid, &info); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (info.full_name != NULL) { + *full_name = talloc_strdup(mem_ctx, info.full_name); + if (*full_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + } + + return NT_STATUS_OK; +} + /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 3df7d7c..53b8aed 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -106,6 +106,10 @@ NTSTATUS wcache_query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid, struct wbint_userinfo *info); +NTSTATUS wcache_query_user_fullname(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + const struct dom_sid *user_sid, + const char **full_name); NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 num_sids, const struct dom_sid *sids, -- 2.1.0 From be2b4c4701ae29d17adae8a986825d665f72c34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Mon, 7 Jul 2014 17:16:32 +0200 Subject: [PATCH 04/10] s3-winbindd: use wcache_query_user_fullname after inspecting samlogon cache. The reason for this followup query is that very often the samlogon cache only contains a info3 netlogon user structure that has been retrieved during a netlogon samlogon authentication using "network" logon level. With that logon level only a few info3 fields are filled in; the user's fullname is never filled in that case. This is problematic when the cache is used to fill in the user's gecos field (for NSS queries). When we have retrieved the user's fullname during other queries, reuse it from the other caches. Thanks to Matt Rogers . BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Guenther Pair-Programmed-With: Andreas Schneider Signed-off-by: Guenther Deschner Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_ads.c | 8 ++++++++ source3/winbindd/winbindd_msrpc.c | 8 ++++++++ source3/winbindd/winbindd_pam.c | 41 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 4c26389..a20fba5 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -619,6 +619,14 @@ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_FREE(user); + if (info->full_name == NULL) { + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + mem_ctx, + sid, + &info->full_name); + } + return NT_STATUS_OK; } diff --git a/source3/winbindd/winbindd_msrpc.c b/source3/winbindd/winbindd_msrpc.c index 426d64c..c097bf3 100644 --- a/source3/winbindd/winbindd_msrpc.c +++ b/source3/winbindd/winbindd_msrpc.c @@ -439,6 +439,14 @@ static NTSTATUS msrpc_query_user(struct winbindd_domain *domain, user_info->full_name = talloc_strdup(user_info, user->base.full_name.string); + if (user_info->full_name == NULL) { + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + mem_ctx, + user_sid, + &user_info->full_name); + } + status = NT_STATUS_OK; goto done; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 15323ac..543e45c 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1801,6 +1801,26 @@ process_result: sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); + if (info3->base.full_name.string == NULL) { + struct netr_SamInfo3 *cached_info3; + + cached_info3 = netsamlogon_cache_get(state->mem_ctx, + &user_sid); + if (cached_info3 != NULL && + cached_info3->base.full_name.string != NULL) { + info3->base.full_name.string = + talloc_strdup(info3, + cached_info3->base.full_name.string); + } else { + + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + info3, + &user_sid, + &info3->base.full_name.string); + } + } + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &user_sid); netsamlogon_cache_store(name_user, info3); @@ -1974,6 +1994,27 @@ process_result: sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid); + + if (info3->base.full_name.string == NULL) { + struct netr_SamInfo3 *cached_info3; + + cached_info3 = netsamlogon_cache_get(state->mem_ctx, + &user_sid); + if (cached_info3 != NULL && + cached_info3->base.full_name.string != NULL) { + info3->base.full_name.string = + talloc_strdup(info3, + cached_info3->base.full_name.string); + } else { + + /* this might fail so we dont check the return code */ + wcache_query_user_fullname(domain, + info3, + &user_sid, + &info3->base.full_name.string); + } + } + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &user_sid); netsamlogon_cache_store(name_user, info3); -- 2.1.0 From b89caa4a2cbd5731c6ba8236c45e04267e0aa009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 9 Jul 2014 13:36:06 +0200 Subject: [PATCH 05/10] samlogon_cache: use a talloc_stackframe inside netsamlogon_cache_store. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/libsmb/samlogon_cache.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index b04cf0a..9b09ab9 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -125,7 +125,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) bool result = false; struct dom_sid user_sid; time_t t = time(NULL); - TALLOC_CTX *mem_ctx; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); DATA_BLOB blob; enum ndr_err_code ndr_err; struct netsamlogoncache_entry r; @@ -147,13 +147,6 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr)); - /* Prepare data */ - - if (!(mem_ctx = talloc( NULL, int))) { - DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n")); - return false; - } - /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ @@ -168,11 +161,11 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r, + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r, (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(tmp_ctx); return false; } @@ -183,7 +176,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) result = true; } - TALLOC_FREE(mem_ctx); + TALLOC_FREE(tmp_ctx); return result; } -- 2.1.0 From 76ca383a5b9b0c6c0dbc7ba092fc0178a64c5203 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 3 Jul 2014 16:17:46 +0200 Subject: [PATCH 06/10] samlogon_cache: avoid overwriting info3->base.full_name.string. This field servers as a source for the gecos field. We should not overwrite it when a info3 struct from a samlogon network level gets saved in which case this field is always NULL. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Signed-off-by: Andreas Schneider Reviewed-by: Guenther Deschner Conflicts: source3/libsmb/samlogon_cache.c --- source3/libsmb/samlogon_cache.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 9b09ab9..ad638c1 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -147,6 +147,20 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr)); + if (info3->base.full_name.string == NULL) { + struct netr_SamInfo3 *cached_info3; + const char *full_name = NULL; + + cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid); + if (cached_info3 != NULL) { + full_name = cached_info3->base.full_name.string; + } + + if (full_name != NULL) { + info3->base.full_name.string = talloc_strdup(info3, full_name); + } + } + /* only Samba fills in the username, not sure why NT doesn't */ /* so we fill it in since winbindd_getpwnam() makes use of it */ -- 2.1.0 From 11fa869e5cb756c7b8bbbb0b8d6b2bfc9ed83040 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 3 Jul 2014 16:19:42 +0200 Subject: [PATCH 07/10] s3-winbind: Don't set the gecos field to NULL. The value is loaded from the cache anyway. So it will be set to NULL if it is not available. BUG: https://bugzilla.samba.org/show_bug.cgi?id=10440 Signed-off-by: Andreas Schneider Reviewed-by: Guenther Deschner --- source3/winbindd/nss_info_template.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source3/winbindd/nss_info_template.c b/source3/winbindd/nss_info_template.c index 5fdfd9b..de93803 100644 --- a/source3/winbindd/nss_info_template.c +++ b/source3/winbindd/nss_info_template.c @@ -48,7 +48,6 @@ static NTSTATUS nss_template_get_info( struct nss_domain_entry *e, username */ *homedir = talloc_strdup( ctx, lp_template_homedir() ); *shell = talloc_strdup( ctx, lp_template_shell() ); - *gecos = NULL; if ( !*homedir || !*shell ) { return NT_STATUS_NO_MEMORY; -- 2.1.0 From 63ac2feac45a23dc5ce263854e926ec121609c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 16:21:08 +0200 Subject: [PATCH 08/10] s3-rpc_client: add rpccli_netlogon_sam_logon_ex(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function deals with interactive samlogon and does a dcerpc_netr_SamLogonEx call (w/o credential chaining). Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/rpc_client/cli_netlogon.c | 152 ++++++++++++++++++++++++++++++++++++++ source3/rpc_client/cli_netlogon.h | 10 +++ 2 files changed, 162 insertions(+) diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 615ad97..ab6c910 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -364,6 +364,158 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, return result; } +/* Logon domain user */ + +NTSTATUS rpccli_netlogon_sam_logon_ex(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, + uint16_t validation_level, + int logon_type, + struct netr_SamInfo3 **info3) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + NTSTATUS status; + struct netr_Authenticator ret_creds; + union netr_LogonLevel *logon; + union netr_Validation validation; + uint8_t authoritative; + fstring clnt_name_slash; + struct dcerpc_binding_handle *b = cli->binding_handle; + uint32_t flags = 0; + + ZERO_STRUCT(ret_creds); + + logon = talloc_zero(mem_ctx, union netr_LogonLevel); + if (!logon) { + return NT_STATUS_NO_MEMORY; + } + + if (workstation) { + fstr_sprintf( clnt_name_slash, "\\\\%s", workstation ); + } else { + fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() ); + } + + /* Initialise input parameters */ + + switch (logon_type) { + case NetlogonInteractiveInformation: { + + struct netr_PasswordInfo *password_info; + + struct samr_Password lmpassword; + struct samr_Password ntpassword; + + password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo); + if (!password_info) { + return NT_STATUS_NO_MEMORY; + } + + nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash); + + if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) { + netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16); + netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16); + } else { + netlogon_creds_des_encrypt(cli->dc, &lmpassword); + netlogon_creds_des_encrypt(cli->dc, &ntpassword); + } + + password_info->identity_info.domain_name.string = domain; + password_info->identity_info.parameter_control = logon_parameters; + password_info->identity_info.logon_id_low = 0xdead; + password_info->identity_info.logon_id_high = 0xbeef; + password_info->identity_info.account_name.string = username; + password_info->identity_info.workstation.string = clnt_name_slash; + + password_info->lmpassword = lmpassword; + password_info->ntpassword = ntpassword; + + logon->password = password_info; + + break; + } + case NetlogonNetworkInformation: { + struct netr_NetworkInfo *network_info; + uint8 chal[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + struct netr_ChallengeResponse lm; + struct netr_ChallengeResponse nt; + + ZERO_STRUCT(lm); + ZERO_STRUCT(nt); + + network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo); + if (!network_info) { + return NT_STATUS_NO_MEMORY; + } + + generate_random_buffer(chal, 8); + + SMBencrypt(password, chal, local_lm_response); + SMBNTencrypt(password, chal, local_nt_response); + + lm.length = 24; + lm.data = local_lm_response; + + nt.length = 24; + nt.data = local_nt_response; + + network_info->identity_info.domain_name.string = domain; + network_info->identity_info.parameter_control = logon_parameters; + network_info->identity_info.logon_id_low = 0xdead; + network_info->identity_info.logon_id_high = 0xbeef; + network_info->identity_info.account_name.string = username; + network_info->identity_info.workstation.string = clnt_name_slash; + + memcpy(network_info->challenge, chal, 8); + network_info->nt = nt; + network_info->lm = lm; + + logon->network = network_info; + + break; + } + default: + DEBUG(0, ("switch value %d not supported\n", + logon_type)); + return NT_STATUS_INVALID_INFO_CLASS; + } + + status = dcerpc_netr_LogonSamLogonEx(b, mem_ctx, + cli->srv_name_slash, + lp_netbios_name(), + logon_type, + logon, + validation_level, + &validation, + &authoritative, + &flags, + &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level, &validation); + + result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + return result; +} + + /** * Logon domain user with an 'network' SAM logon * diff --git a/source3/rpc_client/cli_netlogon.h b/source3/rpc_client/cli_netlogon.h index 9c6cbc8..3763843 100644 --- a/source3/rpc_client/cli_netlogon.h +++ b/source3/rpc_client/cli_netlogon.h @@ -43,6 +43,16 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, uint16_t validation_level, int logon_type, struct netr_SamInfo3 **info3); +NTSTATUS rpccli_netlogon_sam_logon_ex(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + uint32 logon_parameters, + const char *domain, + const char *username, + const char *password, + const char *workstation, + uint16_t validation_level, + int logon_type, + struct netr_SamInfo3 **info3); NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 logon_parameters, -- 2.1.0 From 372ba28ae85b7a26dc1eddd35014129ad5ba3a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Tue, 15 Jul 2014 16:22:15 +0200 Subject: [PATCH 09/10] s3-winbindd: prefer to do a rpccli_netlogon_sam_logon_ex if we can. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider --- source3/winbindd/winbindd_pam.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index 543e45c..b22d52f 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1334,17 +1334,31 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, } if (interactive && username != NULL && password != NULL) { - result = rpccli_netlogon_sam_logon( - netlogon_pipe, - mem_ctx, - logon_parameters, - domainname, - username, - password, - workstation, - 3, /* FIXME */ - NetlogonInteractiveInformation, - info3); + if (domain->can_do_samlogon_ex && domain->can_do_validation6) { + result = rpccli_netlogon_sam_logon_ex( + netlogon_pipe, + mem_ctx, + logon_parameters, + domainname, + username, + password, + workstation, + 6, + NetlogonInteractiveInformation, + info3); + } else { + result = rpccli_netlogon_sam_logon( + netlogon_pipe, + mem_ctx, + logon_parameters, + domainname, + username, + password, + workstation, + domain->can_do_validation6 ? 6 : 3, + NetlogonInteractiveInformation, + info3); + } } else if (domain->can_do_samlogon_ex && domain->can_do_validation6) { result = rpccli_netlogon_sam_network_logon_ex( netlogon_pipe, -- 2.1.0 From e5847202def73179c4fe97a2feb1fc7837a3b2bd Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Aug 2014 15:51:21 +0200 Subject: [PATCH 10/10] s3-winbind: Reset netlogon pipe for interactive samlogon_ex. Signed-off-by: Andreas Schneider Signed-off-by: Guenther Deschner --- source3/winbindd/winbindd_pam.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index b22d52f..ac67fd0 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1359,6 +1359,18 @@ static NTSTATUS winbind_samlogon_retry_loop(struct winbindd_domain *domain, NetlogonInteractiveInformation, info3); } + + if (NT_STATUS_EQUAL(result, NT_STATUS_WRONG_PASSWORD)) { + /* + * HACK: This is a 3.6 hack that we get a new + * session_key to do a successfuly interactive + * logon + */ + TALLOC_FREE(domain->conn.netlogon_pipe); + attempts += 1; + retry = true; + continue; + } } else if (domain->can_do_samlogon_ex && domain->can_do_validation6) { result = rpccli_netlogon_sam_network_logon_ex( netlogon_pipe, -- 2.1.0