r14182: Ensure we know that dom_sid cannot be null.
[kai/samba-autobuild/.git] / source / rpc_server / srv_netlog_nt.c
index 52f2c2e34c0f204283ef9a539389856a70d9b942..8dbd4ff33f33c49bc5dcbd28f0e17618874903a6 100644 (file)
@@ -206,7 +206,7 @@ static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
 
 static BOOL get_md4pw(char *md4pw, char *mach_acct)
 {
-       SAM_ACCOUNT *sampass = NULL;
+       struct samu *sampass = NULL;
        const uint8 *pass;
        BOOL ret;
        uint32 acct_ctrl;
@@ -229,8 +229,9 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
        }
 #endif /* 0 */
 
-       if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
+       if ( !(sampass = samu_new( NULL )) ) {
                return False;
+       }
 
        /* JRA. This is ok as it is only used for generating the challenge. */
        become_root();
@@ -239,7 +240,7 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
  
        if (ret==False) {
                DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
-               pdb_free_sam(&sampass);
+               TALLOC_FREE(sampass);
                return False;
        }
 
@@ -251,12 +252,12 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
            ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
                memcpy(md4pw, pass, 16);
                dump_data(5, md4pw, 16);
-               pdb_free_sam(&sampass);
+               TALLOC_FREE(sampass);
                return True;
        }
        
        DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
-       pdb_free_sam(&sampass);
+       TALLOC_FREE(sampass);
        return False;
 
 }
@@ -281,10 +282,6 @@ NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u
                        q_u->uni_logon_clnt.buffer,
                        sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
 
-       /* Remember the workstation name. This is what we'll use to look
-          up the secrets.tdb record later. */
-       fstrcpy(p->wks, p->dc->remote_machine);
-
        /* Save the client challenge to the server. */
        memcpy(p->dc->clnt_chal.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
 
@@ -342,7 +339,7 @@ NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
                        p->dc,
                        &p->dc->clnt_chal,      /* Stored client chal. */
                        &p->dc->srv_chal,       /* Stored server chal. */
-                       (const char *)p->dc->mach_pw,
+                       p->dc->mach_pw,
                        &srv_chal_out); 
 
        /* Check client credentials are valid. */
@@ -389,6 +386,8 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
 
        rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
                                q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
+
+       /* We use this as the key to store the creds. */
        rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
                                q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
 
@@ -420,7 +419,7 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
                        p->dc,
                        &p->dc->clnt_chal,      /* Stored client chal. */
                        &p->dc->srv_chal,       /* Stored server chal. */
-                       (const char *)p->dc->mach_pw,
+                       p->dc->mach_pw,
                        &srv_chal_out); 
 
        /* Check client credentials are valid. */
@@ -448,7 +447,9 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
 
        /* Store off the state so we can continue after client disconnect. */
        become_root();
-       secrets_store_schannel_session_info(p->mem_ctx, p->dc);
+       secrets_store_schannel_session_info(p->mem_ctx,
+                                       remote_machine,
+                                       p->dc);
        unbecome_root();
 
        return r_u->status;
@@ -461,8 +462,8 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
 NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
 {
        NTSTATUS status = NT_STATUS_ACCESS_DENIED;
-       fstring workstation;
-       SAM_ACCOUNT *sampass=NULL;
+       fstring remote_machine;
+       struct samu *sampass=NULL;
        BOOL ret = False;
        unsigned char pwd[16];
        int i;
@@ -472,15 +473,24 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
 
        DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
 
-       /* We need the workstation name for the creds lookup. */
-       rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
-                   sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
+       /* We need the remote machine name for the creds lookup. */
+       rpcstr_pull(remote_machine,q_u->clnt_id.login.uni_comp_name.buffer,
+                   sizeof(remote_machine),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
+
+       if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+               /* 'server schannel = yes' should enforce use of
+                  schannel, the client did offer it in auth2, but
+                  obviously did not use it. */
+               DEBUG(0,("_net_srv_pwset: client %s not using schannel for netlogon\n",
+                       remote_machine ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
        if (!p->dc) {
                /* Restore the saved state of the netlogon creds. */
                become_root();
                ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
-                                                       workstation,
+                                                       remote_machine,
                                                        &p->dc);
                unbecome_root();
                if (!ret) {
@@ -492,24 +502,30 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       DEBUG(3,("_net_srv_pwset: Server Password Set by Wksta:[%s] on account [%s]\n",
-                       workstation, p->dc->mach_acct));
+       DEBUG(3,("_net_srv_pwset: Server Password Set by remote machine:[%s] on account [%s]\n",
+                       remote_machine, p->dc->mach_acct));
        
        /* Step the creds chain forward. */
        if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) {
                DEBUG(2,("_net_srv_pwset: creds_server_step failed. Rejecting auth "
                        "request from client %s machine account %s\n",
-                       p->dc->remote_machine, p->dc->mach_acct ));
+                       remote_machine, p->dc->mach_acct ));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* We must store the creds state after an update. */
        become_root();
-       secrets_store_schannel_session_info(p->pipe_state_mem_ctx, p->dc);
-       pdb_init_sam(&sampass);
-       ret=pdb_getsampwnam(sampass, p->dc->mach_acct);
+       secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+                                               remote_machine,
+                                               p->dc);
+       if ( (sampass = samu_new( NULL )) != NULL ) {
+               ret = pdb_getsampwnam(sampass, p->dc->mach_acct);
+       }
        unbecome_root();
 
+       if ( !sampass ) 
+               return NT_STATUS_NO_MEMORY;
+
        /* Ensure the account exists and is a machine account. */
        
        acct_ctrl = pdb_get_acct_ctrl(sampass);
@@ -518,12 +534,12 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
              && (acct_ctrl & ACB_WSTRUST ||
                      acct_ctrl & ACB_SVRTRUST ||
                      acct_ctrl & ACB_DOMTRUST))) {
-               pdb_free_sam(&sampass);
+               TALLOC_FREE(sampass);
                return NT_STATUS_NO_SUCH_USER;
        }
        
        if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
-               pdb_free_sam(&sampass);
+               TALLOC_FREE(sampass);
                return NT_STATUS_ACCOUNT_DISABLED;
        }
 
@@ -546,17 +562,17 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
 
                /* LM password should be NULL for machines */
                if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
-                       pdb_free_sam(&sampass);
+                       TALLOC_FREE(sampass);
                        return NT_STATUS_NO_MEMORY;
                }
                
                if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
-                       pdb_free_sam(&sampass);
+                       TALLOC_FREE(sampass);
                        return NT_STATUS_NO_MEMORY;
                }
                
                if (!pdb_set_pass_changed_now(sampass)) {
-                       pdb_free_sam(&sampass);
+                       TALLOC_FREE(sampass);
                        /* Not quite sure what this one qualifies as, but this will do */
                        return NT_STATUS_UNSUCCESSFUL; 
                }
@@ -569,7 +585,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
        /* set up the LSA Server Password Set response */
        init_net_r_srv_pwset(r_u, &cred_out, status);
 
-       pdb_free_sam(&sampass);
+       TALLOC_FREE(sampass);
        return r_u->status;
 }
 
@@ -579,22 +595,33 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
 
 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
 {
-       fstring workstation;
+       fstring remote_machine;
+
+       if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+               /* 'server schannel = yes' should enforce use of
+                  schannel, the client did offer it in auth2, but
+                  obviously did not use it. */
+               DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
+                       get_remote_machine_name() ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
 
        if (!get_valid_user_struct(p->vuid))
                return NT_STATUS_NO_SUCH_USER;
 
+       /* Get the remote machine name for the creds store. */
+       rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
+                   sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
+
        if (!p->dc) {
                /* Restore the saved state of the netlogon creds. */
                BOOL ret;
 
-               *workstation = '\0';
-               rpcstr_pull_unistr2_fstring(workstation, &q_u->sam_id.client.login.uni_comp_name);
-
                become_root();
-               secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
-                                                       workstation,
-                                                       &p->dc);
+               ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
+                                               remote_machine,
+                                               &p->dc);
                unbecome_root();
                if (!ret) {
                        return NT_STATUS_INVALID_HANDLE;
@@ -611,23 +638,25 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF
        if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
                DEBUG(2,("_net_sam_logoff: creds_server_step failed. Rejecting auth "
                        "request from client %s machine account %s\n",
-                       p->dc->remote_machine, p->dc->mach_acct ));
+                       remote_machine, p->dc->mach_acct ));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* We must store the creds state after an update. */
        become_root();
-       secrets_store_schannel_session_info(p->pipe_state_mem_ctx, p->dc);
+       secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+                                       remote_machine,
+                                       p->dc);
        unbecome_root();
 
        r_u->status = NT_STATUS_OK;
        return r_u->status;
 }
 
-
 /*******************************************************************
  gets a domain user's groups from their already-calculated NT_USER_TOKEN
  ********************************************************************/
+
 static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx,
                                       const DOM_SID *domain_sid,
                                       size_t num_sids,
@@ -672,12 +701,22 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
        fstring nt_username, nt_domain, nt_workstation;
        auth_usersupplied_info *user_info = NULL;
        auth_serversupplied_info *server_info = NULL;
-       SAM_ACCOUNT *sampw;
+       struct samu *sampw;
        struct auth_context *auth_context = NULL;
-               
+        
+       if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
+               /* 'server schannel = yes' should enforce use of
+                  schannel, the client did offer it in auth2, but
+                  obviously did not use it. */
+               DEBUG(0,("_net_sam_logon_internal: client %s not using schannel for netlogon\n",
+                       get_remote_machine_name() ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        usr_info = TALLOC_P(p->mem_ctx, NET_USER_INFO_3);
-       if (!usr_info)
+       if (!usr_info) {
                return NT_STATUS_NO_MEMORY;
+       }
 
        ZERO_STRUCTP(usr_info);
 
@@ -695,44 +734,24 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
        if (!get_valid_user_struct(p->vuid))
                return NT_STATUS_NO_SUCH_USER;
 
-       /* We need the workstation name for the creds lookup. */
-    
-       switch (q_u->sam_id.logon_level) {
-       case INTERACTIVE_LOGON_TYPE:
-               uni_samlogon_user = &ctr->auth.id1.uni_user_name;
-               uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
-
-                uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
-            
-               DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
-               break;
-       case NET_LOGON_TYPE:
-               uni_samlogon_user = &ctr->auth.id2.uni_user_name;
-               uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
-               uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
-            
-               DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
-               break;
-       default:
-               DEBUG(2,("SAM Logon: unsupported switch value\n"));
-               return NT_STATUS_INVALID_INFO_CLASS;
-       } /* end switch */
-
-       rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
-       rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
-       rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
+       if (process_creds) {
+               fstring remote_machine;
 
-       DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain));
+               /* Get the remote machine name for the creds store. */
+               /* Note this is the remote machine this request is coming from (member server),
+                  not neccessarily the workstation name the user is logging onto.
+               */
+               rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
+                   sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
 
-       if (process_creds) {
                if (!p->dc) {
                        /* Restore the saved state of the netlogon creds. */
                        BOOL ret;
 
                        become_root();
-                       secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
-                                                               nt_workstation,
-                                                               &p->dc);
+                       ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
+                                       remote_machine,
+                                       &p->dc);
                        unbecome_root();
                        if (!ret) {
                                return NT_STATUS_INVALID_HANDLE;
@@ -742,32 +761,49 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
                if (!p->dc || !p->dc->authenticated) {
                        return NT_STATUS_INVALID_HANDLE;
                }
-       }
 
-       if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
-               /* 'server schannel = yes' should enforce use of
-                  schannel, the client did offer it in auth2, but
-                  obviously did not use it. */
-               DEBUG(0,("_net_sam_logon: client %s not using schannel for netlogon\n",
-                       p->dc->remote_machine ));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       if (process_creds) {
                /* checks and updates credentials.  creates reply credentials */
                if (!creds_server_step(p->dc, &q_u->sam_id.client.cred,  &r_u->srv_creds)) {
                        DEBUG(2,("_net_sam_logon: creds_server_step failed. Rejecting auth "
                                "request from client %s machine account %s\n",
-                               p->dc->remote_machine, p->dc->mach_acct ));
+                               remote_machine, p->dc->mach_acct ));
                        return NT_STATUS_INVALID_PARAMETER;
                }
 
                /* We must store the creds state after an update. */
                become_root();
-               secrets_store_schannel_session_info(p->pipe_state_mem_ctx, p->dc);
+               secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
+                                       remote_machine,
+                                       p->dc);
                unbecome_root();
        }
 
+       switch (q_u->sam_id.logon_level) {
+       case INTERACTIVE_LOGON_TYPE:
+               uni_samlogon_user = &ctr->auth.id1.uni_user_name;
+               uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
+
+                uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
+            
+               DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
+               break;
+       case NET_LOGON_TYPE:
+               uni_samlogon_user = &ctr->auth.id2.uni_user_name;
+               uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
+               uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
+            
+               DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
+               break;
+       default:
+               DEBUG(2,("SAM Logon: unsupported switch value\n"));
+               return NT_STATUS_INVALID_INFO_CLASS;
+       } /* end switch */
+
+       rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
+       rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
+       rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
+
+       DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain));
        fstrcpy(current_user_info.smb_name, nt_username);
        sub_set_smb_name(nt_username);
      
@@ -857,7 +893,7 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
                     && !is_trusted_domain(nt_domain) )
                        r_u->auth_resp = 0; /* We are not authoritative */
 
-               talloc_free(server_info);
+               TALLOC_FREE(server_info);
                return status;
        }
 
@@ -865,7 +901,7 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
                /* We don't like guest domain logons... */
                DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST "
                         "denied.\n"));
-               talloc_free(server_info);
+               TALLOC_FREE(server_info);
                return NT_STATUS_LOGON_FAILURE;
        }
 
@@ -980,12 +1016,12 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
                                    pdb_get_pass_last_set_time(sampw),
                                    pdb_get_pass_can_change_time(sampw),
                                    pdb_get_pass_must_change_time(sampw),
-                                   
                                    0, /* logon_count */
                                    0, /* bad_pw_count */
                                    num_gids,    /* uint32 num_groups */
                                    gids    , /* DOM_GID *gids */
-                                   0x20    , /* uint32 user_flgs (?) */
+                                   LOGON_EXTRA_SIDS, /* uint32 user_flgs (?) */
+                                   pdb_get_acct_ctrl(sampw),
                                    server_info->user_session_key.length ? user_session_key : NULL,
                                    server_info->lm_session_key.length ? lm_session_key : NULL,
                                    my_name     , /* char *logon_srv */
@@ -994,7 +1030,7 @@ static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
                ZERO_STRUCT(user_session_key);
                ZERO_STRUCT(lm_session_key);
        }
-       talloc_free(server_info);
+       TALLOC_FREE(server_info);
        return status;
 }