s3-winbindd: Implement SamLogon IRPC call
authorAndrew Bartlett <abartlet@samba.org>
Thu, 8 May 2014 04:49:13 +0000 (16:49 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 11 Jun 2014 10:43:58 +0000 (12:43 +0200)
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 <abartlet@samba.org>
Reviewed-by: Kamen Mazdrashki <kamenim@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Jun 11 12:43:58 CEST 2014 on sn-devel-104

source3/winbindd/winbindd_dual_srv.c
source3/winbindd/winbindd_irpc.c
source3/winbindd/winbindd_pam.c
source3/winbindd/winbindd_proto.h

index 985f0a92097ca382225d13e1beb26bd2ecbccca4..5e33787bd34b102cfe650e5ba33421a0fde14f11 100644 (file)
@@ -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;
 }
index 3c33076d615c20b15df0451a1a2332c9e240e1e6..cf58a088eb4761f10522edb936da241cb09aec86 100644 (file)
@@ -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;
 }
index c432afac1a21464a7822041fddb3a86ae67b6795..1fb4360e3511200f6f930b384dd3e822a8299178 100644 (file)
@@ -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;
 }
 
index 540a99ab43a76fdb66f0d7b0126e8372228cadd3..dfd61621c6abae204f10693a58a017159748db2b 100644 (file)
@@ -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);