r1061: The start of the SamLogon call for the NETLOGON pipe.
authorAndrew Bartlett <abartlet@samba.org>
Mon, 7 Jun 2004 08:54:49 +0000 (08:54 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:56:35 +0000 (12:56 -0500)
Changes:

- Check for a valid 'pipe_state' in netr_ServerAuthenticate3 before
  we dereference it

- removes the expansionroom[7] in the netr_SamInfo* structs to 7
individual elements.
- renames netr_SamInfo -> netr_SamInfo2
          netr_SamInfo2 -> netr_SamInfo3
  - Having the thing we always called an 'info3' being 'netr_SamInfo2'
    was just too confusing.

- Expand and fill in extra details about users from the SAM, into
  the server_info, for processing into the SamLogon reply.

- Add a dum_sid_dup() function to duplicate a struct dom_sid

The SamLogon code currently does not return supplementary groups, and is
only tested with Samba4 smbtorture.

Andrew Bartlett
(This used to be commit 6c92563b7961f15fc74b02601e105d5e1d04f04d)

source4/libcli/util/dom_sid.c
source4/librpc/idl/netlogon.idl
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/torture/rpc/netlogon.c

index cdf89ccf9611ca350e4972244fa41107f5e63a6b..9b8b45e302f2bd6e75917845092b587cfe7ab417 100644 (file)
@@ -89,3 +89,36 @@ struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
        return ret;
 }
 
+/*
+  convert a string to a dom_sid, returning a talloc'd dom_sid
+*/
+struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, struct dom_sid *dom_sid)
+{
+       struct dom_sid *ret;
+       int i;
+       ret = talloc_p(mem_ctx, struct dom_sid);
+       if (!ret) {
+               return NULL;
+       }
+
+       ret->sub_auths = talloc_array_p(mem_ctx, uint32_t, dom_sid->num_auths);
+       if (!ret->sub_auths) {
+               return NULL;
+       }
+
+       ret->sid_rev_num = dom_sid->sid_rev_num;
+       ret->id_auth[0] = dom_sid->id_auth[0];
+       ret->id_auth[1] = dom_sid->id_auth[1];
+       ret->id_auth[2] = dom_sid->id_auth[2];
+       ret->id_auth[3] = dom_sid->id_auth[3];
+       ret->id_auth[4] = dom_sid->id_auth[4];
+       ret->id_auth[5] = dom_sid->id_auth[5];
+       ret->num_auths = dom_sid->num_auths;
+
+       for (i=0;i<dom_sid->num_auths;i++) {
+               ret->sub_auths[i] = dom_sid->sub_auths[i];
+       }
+
+       return ret;
+}
+
index a3e1e804dc009a542ab447b39e917ff5132ee78e..48154dc001f0d0f906f774d2da8356c3ed17a538 100644 (file)
@@ -171,8 +171,14 @@ interface netlogon
                dom_sid2 *domain_sid;
                netr_LMSessionKey LMSessKey;
                uint32 AccountControl;
-               uint32 expansionroom[7];
-       } netr_SamInfo;
+               uint32 unknown1;
+               uint32 unknown2;
+               uint32 unknown3;
+               uint32 unknown4;
+               uint32 unknown5;
+               uint32 unknown6;
+               uint32 unknown7;
+       } netr_SamInfo2;
 
        typedef struct {
                dom_sid2 *sid;
@@ -205,10 +211,16 @@ interface netlogon
                dom_sid2 *domain_sid;
                netr_LMSessionKey LMSessKey;
                uint32 AccountControl;
-               uint32 expansionroom[7];
+               uint32 unknown1;
+               uint32 unknown2;
+               uint32 unknown3;
+               uint32 unknown4;
+               uint32 unknown5;
+               uint32 unknown6;
+               uint32 unknown7;
                uint32 sidcount;
                [size_is(sidcount)] netr_SidAttr *sids;
-       } netr_SamInfo2;
+       } netr_SamInfo3;
 
        typedef struct {
                uint32 pac_size;
@@ -227,8 +239,8 @@ interface netlogon
        } netr_PacInfo;
 
        typedef union {
-               [case(2)] netr_SamInfo  *sam;
-               [case(3)] netr_SamInfo2 *sam2;
+               [case(2)] netr_SamInfo2  *sam2;
+               [case(3)] netr_SamInfo3 *sam3;
                [case(4)] netr_PacInfo  *pac;
                [case(5)] netr_PacInfo  *pac2;
        } netr_Validation;
@@ -237,7 +249,7 @@ interface netlogon
                [in] unistr *server_name,
                [in] unistr *workstation,
                [in] netr_Authenticator *credential,
-               [in][out] netr_Authenticator *authenticator,
+               [in][out] netr_Authenticator *return_authenticator,
                [in]  uint16 logon_level,
                [in]  [switch_is(logon_level)] netr_LogonLevel logon,
                [in]  uint16 validation_level,
index bfc5e3b759c75af48d150cfbbe06ee4e0482e806..933f28d84a8f31b83235eeb65554e21c39a226e5 100644 (file)
@@ -228,7 +228,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL
        return nt_status;
 }
                                                 
-
 static NTSTATUS netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                                        struct netr_ServerAuthenticate *r)
 {
@@ -302,12 +301,12 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO
        const char **domain_attrs = attrs;
        ZERO_STRUCT(mod);
 
-       if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
+       if (!pipe_state) {
+               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       if (!pipe_state) {
-               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+       if (!netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
@@ -426,8 +425,6 @@ static WERROR netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
 */
 
-#if 0
-
 static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct netr_LogonSamLogon *r)
 {
@@ -438,8 +435,24 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
        struct auth_serversupplied_info *server_info;
        NTSTATUS nt_status;
        const uint8_t *chal;
+       static const char zeros[16];
+       struct netr_SamInfo2 *sam2;
+       struct netr_SamInfo3 *sam;
        
-       
+       if (!pipe_state) {
+               DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       r->out.return_authenticator = talloc_p(mem_ctx, struct netr_Authenticator);
+       if (!r->out.return_authenticator) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (!netr_creds_server_step_check(pipe_state, r->in.credential, r->out.return_authenticator)) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        switch (r->in.logon_level) {
        case 1:
        case 3:
@@ -476,8 +489,8 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
                                                            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->nt.data, r->in.logon.network->nt.length,
-                                                           r->in.logon.network->lm.data, r->in.logon.network->lm.length);
+                                                           r->in.logon.network->lm.data, r->in.logon.network->lm.length,
+                                                           r->in.logon.network->nt.data, r->in.logon.network->nt.length);
                break;
        default:
                free_auth_context(&auth_context);
@@ -498,48 +511,127 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
        }
        free_auth_context(&auth_context);
 
+       sam = talloc_p(mem_ctx, struct netr_SamInfo3);
+       
+       sam->last_logon = server_info->last_logon;
+       sam->last_logoff = server_info->last_logoff;
+       sam->acct_expiry = server_info->acct_expiry;
+       sam->last_password_change = server_info->last_password_change;
+       sam->allow_password_change = server_info->allow_password_change;
+       sam->force_password_change = server_info->force_password_change;
+       
+       sam->account_name.string = talloc_strdup(mem_ctx, server_info->account_name);
+       sam->full_name.string = talloc_strdup(mem_ctx, server_info->full_name);
+       sam->logon_script.string = talloc_strdup(mem_ctx, server_info->account_name);
+       sam->profile_path.string = talloc_strdup(mem_ctx, server_info->profile_path);
+       sam->home_directory.string = talloc_strdup(mem_ctx, server_info->home_directory);
+       sam->home_drive.string = talloc_strdup(mem_ctx, server_info->home_drive);
+       
+       sam->logon_count = server_info->logon_count;
+       sam->bad_password_count = sam->bad_password_count;
+       sam->rid = server_info->user_sid->sub_auths[server_info->user_sid->num_auths-1];
+       sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
+       sam->group_count = 0;
+       sam->groupids = NULL;
+       
+       sam->acct_flags = server_info->acct_flags;
+       
+       sam->logon_server.string = lp_netbios_name();
+       
+       sam->domain.string = talloc_strdup(mem_ctx, server_info->domain);
+       
+       sam->domain_sid = dom_sid_dup(mem_ctx, server_info->user_sid);
+       sam->domain_sid->num_auths--;
+
+       sam->sidcount = 0;
+       sam->sids = NULL;
+       
+       if (server_info->user_session_key.length == sizeof(sam->key.key)) {
+               memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
+       } else {
+               ZERO_STRUCT(sam->key.key);
+       }
+       
+       if (memcmp(sam->key.key, zeros,  
+                  sizeof(sam->key.key)) != 0) {
+               /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
+               creds_arcfour_crypt(pipe_state->creds, 
+                                   sam->key.key, 
+                                   sizeof(sam->key.key));
+       }
+       
+       if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
+               memcpy(sam->LMSessKey.key, server_info->lm_session_key.data, 
+                      sizeof(sam->LMSessKey.key));
+       } else {
+               ZERO_STRUCT(sam->LMSessKey.key);
+       }
+       
+       if (memcmp(sam->LMSessKey.key, zeros,  
+                  sizeof(sam->LMSessKey.key)) != 0) {
+               creds_arcfour_crypt(pipe_state->creds, 
+                                   sam->LMSessKey.key, 
+                                   sizeof(sam->LMSessKey.key));
+       }
+
        switch (r->in.validation_level) {
        case 2:
        {
-               struct netr_SamInfo *sam;
-               sam = talloc_p(mem_ctx, struct netr_SamInfo);
-               r->out.validation.sam = sam;
-                       
-               sam->last_logon = server_info->last_logon;
-               sam->last_logoff = server_info->last_logoff;
-               sam->acct_expiry = server_info->acct_expiry;
-               sam->last_password_change = server_info->last_password_change;
-               sam->allow_password_change = server_info->allow_password_change;
-               sam->force_password_change = server_info->force_password_change;
-
-               sam->account_name.string = talloc_strdup(mem_ctx, server_info->account_name);
-               sam->full_name.string = talloc_strdup(mem_ctx, server_info->full_name);
-               sam->logon_script.string = talloc_strdup(mem_ctx, server_info->account_name);
-               sam->profile_path.string = talloc_strdup(mem_ctx, server_info->profile_path);
-               sam->home_directory.string = talloc_strdup(mem_ctx, server_info->home_directory);
-               sam->home_drive.string = talloc_strdup(mem_ctx, server_info->home_drive);
-
-               sam->logon_count = server_info->logon_count;
-               sam->bad_password_count = sam->bad_password_count;
-               sam->rid = server_info->user_sid->sub_auths[server_info->user_sid->num_auths-1];
-               sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
-               sam->group_count = 0;
-               sam->groupids = NULL;
-
-               sam->acct_flags = server_info->acct_flags;
-
-               sam->domain.string = talloc_strdup(mem_ctx, server_info->domain);
-
-               /* need to finish */
+               sam2 = talloc_p(mem_ctx, struct netr_SamInfo2);
+               r->out.validation.sam2 = sam2;
+               sam2->last_logon = sam->last_logon;
+               sam2->last_logoff = sam->last_logoff;
+               sam2->acct_expiry = sam->acct_expiry;
+               
+               sam2->last_password_change = sam->last_password_change;
+               sam2->allow_password_change =   sam->allow_password_change;
+
+               sam2->force_password_change =   sam->force_password_change;
+
+       
+               sam2->account_name = sam->account_name;
+               sam2->full_name = sam->full_name;
+               sam2->logon_script = sam->logon_script;
+               sam2->profile_path = sam->profile_path;
+               sam2->home_directory = sam->home_directory;
+               sam2->home_drive = sam->home_drive;
+       
+               sam2->logon_count = sam->logon_count;
+               sam2->bad_password_count = sam->bad_password_count;
+               sam2->rid = sam->rid;
+               sam2->primary_gid = sam->primary_gid;
+               sam2->group_count = sam->group_count;
+               sam2->groupids = sam->groupids;
+       
+               sam2->acct_flags = sam->acct_flags;
+       
+               sam2->key = sam->key;
+
+               sam2->logon_server = sam->logon_server;
+       
+               sam2->domain = sam->domain;
+       
+               sam2->domain_sid = sam->domain_sid;
+               
+               sam2->LMSessKey = sam->LMSessKey;
+       
+               sam2->AccountControl = sam->AccountControl;
+
+               /* can we implicit memcpy an array? */
+               
+               sam2->unknown1 = sam->unknown1;
+               sam2->unknown2 = sam->unknown2;
+               sam2->unknown3 = sam->unknown3;
+               sam2->unknown4 = sam->unknown4;
+               sam2->unknown5 = sam->unknown5;
+               sam2->unknown6 = sam->unknown6;
+               sam2->unknown7 = sam->unknown7;
 
                break;
        }
        case 3:
        {
-               struct netr_SamInfo2 *sam;
-               sam = talloc_p(mem_ctx, struct netr_SamInfo2);
-               r->out.validation.sam2 = sam;
-               
+               r->out.validation.sam3 = sam;
                break;
        }
        default:
@@ -550,13 +642,6 @@ static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CT
 
        return NT_STATUS_OK;
 }
-#else 
-static NTSTATUS netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
-                      struct netr_LogonSamLogon *r)
-{
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-#endif
 
 /* 
   netr_LogonSamLogoff 
index a0b49d91eb0550c8485d649f729e87d039f10392..a336ef7acbb99f0fbba3c77223306d3cae4ffa39 100644 (file)
@@ -355,7 +355,7 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
                ZERO_STRUCT(samlogon_state->auth2);
                creds_client_authenticator(&samlogon_state->creds, &samlogon_state->auth);
                
-               r->out.authenticator = NULL;
+               r->out.return_authenticator = NULL;
                status = dcerpc_netr_LogonSamLogon(samlogon_state->p, samlogon_state->mem_ctx, r);
                if (!NT_STATUS_IS_OK(status)) {
                        if (error_string) {
@@ -363,8 +363,8 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
                        }
                }
                
-               if (!r->out.authenticator || 
-                   !creds_client_check(&samlogon_state->creds, &r->out.authenticator->cred)) {
+               if (!r->out.return_authenticator || 
+                   !creds_client_check(&samlogon_state->creds, &r->out.return_authenticator->cred)) {
                        printf("Credential chaining failed\n");
                }
 
@@ -377,30 +377,19 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
                if (r->in.validation_level == 2) {
                        static const char zeros[16];
                        
-                       if (memcmp(r->out.validation.sam->LMSessKey.key, zeros,  
-                                  sizeof(r->out.validation.sam->LMSessKey.key)) != 0) {
+                       if (memcmp(r->out.validation.sam2->key.key, zeros,  
+                                  sizeof(r->out.validation.sam2->key.key)) != 0) {
                                creds_arcfour_crypt(&samlogon_state->creds, 
-                                                   r->out.validation.sam->LMSessKey.key, 
-                                                   sizeof(r->out.validation.sam->LMSessKey.key));
-                       }
-                       
-                       if (lm_key) {
-                               memcpy(lm_key, r->out.validation.sam->LMSessKey.key, 8);
-                       }
-                       
-                       if (memcmp(r->out.validation.sam->key.key, zeros,  sizeof(r->out.validation.sam->key.key)) != 0) {
-                               creds_arcfour_crypt(&samlogon_state->creds, 
-                                                   r->out.validation.sam->key.key, 
-                                                   sizeof(r->out.validation.sam->key.key));
+                                                   r->out.validation.sam2->key.key, 
+                                                   sizeof(r->out.validation.sam2->key.key));
                        }
                        
                        if (user_session_key) {
-                               memcpy(user_session_key, r->out.validation.sam->key.key, 16);
+                               memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
                        }
                        
-               } else if (r->in.validation_level == 3) {
-                       static const char zeros[16];
-                       if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros,  sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
+                       if (memcmp(r->out.validation.sam2->LMSessKey.key, zeros,  
+                                  sizeof(r->out.validation.sam2->LMSessKey.key)) != 0) {
                                creds_arcfour_crypt(&samlogon_state->creds, 
                                                    r->out.validation.sam2->LMSessKey.key, 
                                                    sizeof(r->out.validation.sam2->LMSessKey.key));
@@ -410,15 +399,30 @@ static NTSTATUS check_samlogon(struct samlogon_state *samlogon_state,
                                memcpy(lm_key, r->out.validation.sam2->LMSessKey.key, 8);
                        }
                        
-                       if (memcmp(r->out.validation.sam2->key.key, zeros,  sizeof(r->out.validation.sam2->key.key)) != 0) {
+               } else if (r->in.validation_level == 3) {
+                       static const char zeros[16];
+                       if (memcmp(r->out.validation.sam3->key.key, zeros,  
+                                  sizeof(r->out.validation.sam3->key.key)) != 0) {
                                creds_arcfour_crypt(&samlogon_state->creds, 
-                                                   r->out.validation.sam2->key.key, 
-                                                   sizeof(r->out.validation.sam2->key.key));
+                                                   r->out.validation.sam3->key.key, 
+                                                   sizeof(r->out.validation.sam3->key.key));
                        }
                        
                        if (user_session_key) {
-                               memcpy(user_session_key, r->out.validation.sam2->key.key, 16);
+                               memcpy(user_session_key, r->out.validation.sam3->key.key, 16);
                        }
+
+                       if (memcmp(r->out.validation.sam3->LMSessKey.key, zeros, 
+                                  sizeof(r->out.validation.sam3->LMSessKey.key)) != 0) {
+                               creds_arcfour_crypt(&samlogon_state->creds, 
+                                                   r->out.validation.sam3->LMSessKey.key, 
+                                                   sizeof(r->out.validation.sam3->LMSessKey.key));
+                       }
+                       
+                       if (lm_key) {
+                               memcpy(lm_key, r->out.validation.sam3->LMSessKey.key, 8);
+                       }
+                       
                }
        }
 
@@ -912,7 +916,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        samlogon_state.r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
        samlogon_state.r.in.workstation = TEST_MACHINE_NAME;
        samlogon_state.r.in.credential = &samlogon_state.auth;
-       samlogon_state.r.in.authenticator = &samlogon_state.auth2;
+       samlogon_state.r.in.return_authenticator = &samlogon_state.auth2;
 
        for (i=2;i<=3;i++) {
                samlogon_state.r.in.validation_level = i;