From ba4467ca65d5f85a2732da27d88760b684c6e30d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 8 May 2014 16:49:13 +1200 Subject: s3-winbindd: Implement SamLogon IRPC call We do this by lifting parts of the winbindd_dual_pam_auth_crap() code into a new helper function winbind_dual_SamLogon(). This allows us to implement the semantics we need for IRPC, without the artifacts of the winbindd pipe protocol. Change-Id: Idb169217e6d68d387c99765d0af7ed394cb5b93a Signed-off-by: Andrew Bartlett Reviewed-by: Kamen Mazdrashki Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Wed Jun 11 12:43:58 CEST 2014 on sn-devel-104 --- source3/winbindd/winbindd_dual_srv.c | 32 ++++++++- source3/winbindd/winbindd_irpc.c | 29 ++++++++ source3/winbindd/winbindd_pam.c | 129 ++++++++++++++++++++++------------- source3/winbindd/winbindd_proto.h | 11 +++ 4 files changed, 150 insertions(+), 51 deletions(-) diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 985f0a92097..5e33787bd34 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -758,8 +758,34 @@ NTSTATUS _winbind_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p, } NTSTATUS _winbind_SamLogon(struct pipes_struct *p, - struct winbind_SamLogon *r) + struct winbind_SamLogon *r) { - p->fault_state = DCERPC_FAULT_OP_RNG_ERROR; - return NT_STATUS_NOT_IMPLEMENTED; + struct winbindd_domain *domain; + NTSTATUS status; + DATA_BLOB lm_response, nt_response; + domain = wb_child_domain(); + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + + /* TODO: Handle interactive logons here */ + if (r->in.validation_level != 3 || + r->in.logon.network == NULL || + (r->in.logon_level != NetlogonNetworkInformation + && r->in.logon_level != NetlogonNetworkTransitiveInformation)) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + + + lm_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->lm.data, r->in.logon.network->lm.length); + nt_response = data_blob_talloc(p->mem_ctx, r->in.logon.network->nt.data, r->in.logon.network->nt.length); + + status = winbind_dual_SamLogon(domain, p->mem_ctx, + r->in.logon.network->identity_info.parameter_control, + r->in.logon.network->identity_info.account_name.string, + r->in.logon.network->identity_info.domain_name.string, + r->in.logon.network->identity_info.workstation.string, + r->in.logon.network->challenge, + lm_response, nt_response, &r->out.validation.sam3); + return status; } diff --git a/source3/winbindd/winbindd_irpc.c b/source3/winbindd/winbindd_irpc.c index 3c33076d615..cf58a088eb4 100644 --- a/source3/winbindd/winbindd_irpc.c +++ b/source3/winbindd/winbindd_irpc.c @@ -128,10 +128,39 @@ static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *m domain, IRPC_CALL_TIMEOUT); } +static NTSTATUS wb_irpc_SamLogon(struct irpc_message *msg, + struct winbind_SamLogon *req) +{ + struct winbindd_domain *domain; + const char *target_domain_name; + if (req->in.logon.network == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + target_domain_name = req->in.logon.network->identity_info.domain_name.string; + + domain = find_auth_domain(0, target_domain_name); + if (domain == NULL) { + return NT_STATUS_NO_SUCH_USER; + } + + DEBUG(5, ("wb_irpc_SamLogon called\n")); + + return wb_irpc_forward_rpc_call(msg, msg, + winbind_event_context(), + req, NDR_WINBIND_SAMLOGON, + "winbind_SamLogon", + domain, IRPC_CALL_TIMEOUT); +} + NTSTATUS wb_irpc_register(void) { NTSTATUS status; status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS, wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_SAMLOGON, + wb_irpc_SamLogon, NULL); return status; } diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c432afac1a2..1fb4360e351 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -1866,6 +1866,76 @@ done: return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } +NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *name_user, + const char *name_domain, + const char *workstation, + const uint8_t chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3) +{ + NTSTATUS result; + + if (strequal(name_domain, get_global_sam_name())) { + DATA_BLOB chal_blob = data_blob_const( + chal, 8); + + result = winbindd_dual_auth_passdb( + mem_ctx, + logon_parameters, + name_domain, name_user, + &chal_blob, &lm_response, &nt_response, info3); + goto process_result; + } + + result = winbind_samlogon_retry_loop(domain, + mem_ctx, + logon_parameters, + domain->dcname, + name_user, + name_domain, + /* Bug #3248 - found by Stefan Burkei. */ + workstation, /* We carefully set this above so use it... */ + chal, + lm_response, + nt_response, + info3); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + +process_result: + + if (NT_STATUS_IS_OK(result)) { + struct dom_sid user_sid; + + sid_compose(&user_sid, (*info3)->base.domain_sid, + (*info3)->base.rid); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), + &user_sid); + netsamlogon_cache_store(name_user, *info3); + } + +done: + + /* give us a more useful (more correct?) error code */ + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + result = NT_STATUS_NO_LOGON_SERVERS; + } + + DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, + ("NTLM CRAP authentication for user [%s]\\[%s] returned %s\n", + name_domain, + name_user, + nt_errstr(result))); + + return result; +} + enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, struct winbindd_cli_state *state) { @@ -1916,46 +1986,22 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, state->request->data.auth_crap.nt_resp_len); } - if (strequal(name_domain, get_global_sam_name())) { - DATA_BLOB chal_blob = data_blob_const( - state->request->data.auth_crap.chal, - sizeof(state->request->data.auth_crap.chal)); - - result = winbindd_dual_auth_passdb( - state->mem_ctx, - state->request->data.auth_crap.logon_parameters, - name_domain, name_user, - &chal_blob, &lm_resp, &nt_resp, &info3); - goto process_result; - } - - result = winbind_samlogon_retry_loop(domain, - state->mem_ctx, - state->request->data.auth_crap.logon_parameters, - domain->dcname, - name_user, - 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, - &info3); + result = winbind_dual_SamLogon(domain, + state->mem_ctx, + state->request->data.auth_crap.logon_parameters, + name_user, + 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, + &info3); if (!NT_STATUS_IS_OK(result)) { goto done; } -process_result: - if (NT_STATUS_IS_OK(result)) { - struct dom_sid user_sid; - - sid_compose(&user_sid, info3->base.domain_sid, - info3->base.rid); - wcache_invalidate_samlogon(find_domain_from_name(name_domain), - &user_sid); - netsamlogon_cache_store(name_user, info3); - /* Check if the user is in the right group */ result = check_info3_in_group( @@ -1979,25 +2025,12 @@ process_result: done: - /* give us a more useful (more correct?) error code */ - if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || - (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { - result = NT_STATUS_NO_LOGON_SERVERS; - } - if (state->request->flags & WBFLAG_PAM_NT_STATUS_SQUASH) { result = nt_status_squash(result); } set_auth_errors(state->response, result); - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", - name_domain, - name_user, - state->response->data.auth.nt_status_string, - state->response->data.auth.pam_error)); - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 540a99ab43a..dfd61621c6a 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -394,6 +394,17 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, struct netr_SamInfo3 **info3); +NTSTATUS winbind_dual_SamLogon(struct winbindd_domain *domain, + TALLOC_CTX *mem_ctx, + uint32_t logon_parameters, + const char *name_user, + const char *name_domain, + const char *workstation, + const uint8_t chal[8], + DATA_BLOB lm_response, + DATA_BLOB nt_response, + struct netr_SamInfo3 **info3); + /* The following definitions come from winbindd/winbindd_util.c */ struct winbindd_domain *domain_list(void); -- cgit