r17439: Fix logic error in checking TALLOC return. Spotted by Volker.
[ira/wip.git] / source / rpc_server / srv_samr_nt.c
index 2786a740ffb309fe1e683a02e93f837e336a815a..31e434cbfb1cf7b48f7ad505e7083c51d5f55043 100644 (file)
@@ -1435,7 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
                }
        }
 
-       init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
+       init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status);
 
        DEBUG(5,("_samr_lookup_names: %d\n", __LINE__));
 
@@ -1619,12 +1619,14 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
 {
        const char **names;
        enum SID_NAME_USE *attrs = NULL;
+       uint32 *wire_attrs = NULL;
        UNIHDR *hdr_name = NULL;
        UNISTR2 *uni_name = NULL;
        DOM_SID pol_sid;
        int num_rids = q_u->num_rids1;
        uint32 acc_granted;
-       
+       int i;
+
        r_u->status = NT_STATUS_OK;
 
        DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
@@ -1640,9 +1642,10 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
        }
 
        names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids);
-       attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
+       attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, enum SID_NAME_USE, num_rids);
+       wire_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids);
 
-       if ((num_rids != 0) && ((names == NULL) || (attrs == NULL)))
+       if ((num_rids != 0) && ((names == NULL) || (attrs == NULL) || (wire_attrs==NULL)))
                return NT_STATUS_NO_MEMORY;
 
        become_root();  /* lookup_sid can require root privs */
@@ -1658,7 +1661,12 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
                                  &hdr_name, &uni_name))
                return NT_STATUS_NO_MEMORY;
 
-       init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, attrs);
+       /* Convert from enum SID_NAME_USE to uint32 for wire format. */
+       for (i = 0; i < num_rids; i++) {
+               wire_attrs[i] = (uint32)attrs[i];
+       }
+
+       init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, wire_attrs);
 
        DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
 
@@ -2463,8 +2471,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
                return NT_STATUS_NO_MEMORY;
        }
 
-       strlower_m(account);
-
        nt_status = can_create(p->mem_ctx, account);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
@@ -2500,7 +2506,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
        }
                
        DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
-               p->pipe_user_name, can_add_account ? "True":"False" ));
+                 uidtoname(p->pipe_user.ut.uid),
+                 can_add_account ? "True":"False" ));
                
        /********** BEGIN Admin BLOCK **********/
 
@@ -3102,9 +3109,11 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
        }
 
        /* we need to separately check for an account rename first */
+       
        if (rpcstr_pull(new_name, id21->uni_user_name.buffer, 
-                       sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) && 
-          (!strequal(new_name, pdb_get_username(pwd)))) {
+               sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) 
+               && (!strequal(new_name, pdb_get_username(pwd)))) 
+       {
 
                /* check to see if the new username already exists.  Note: we can't
                   reliably lock all backends, so there is potentially the 
@@ -3203,7 +3212,7 @@ static NTSTATUS set_user_info_23(TALLOC_CTX *mem_ctx, SAM_USER_INFO_23 *id23,
        if (    ( (acct_ctrl &  ACB_DOMTRUST) == ACB_DOMTRUST ) ||
                ( (acct_ctrl &  ACB_WSTRUST) ==  ACB_WSTRUST) ||
                ( (acct_ctrl &  ACB_SVRTRUST) ==  ACB_SVRTRUST) ) {
-               DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
+               DEBUG(5, ("Changing trust account.  Not updating /etc/passwd\n"));
        } else  {
                /* update the UNIX password */
                if (lp_unix_password_sync() ) {
@@ -3329,13 +3338,20 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25,
 
        copy_id25_to_sam_passwd(pwd, id25);
  
+       /* write the change out */
+       if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
+               TALLOC_FREE(pwd);
+               return status;
+       }
+
        /*
-        * The funny part about the previous two calls is
-        * that pwd still has the password hashes from the
-        * passdb entry.  These have not been updated from
-        * id21.  I don't know if they need to be set.    --jerry
+        * We need to "pdb_update_sam_account" before the unix primary group
+        * is set, because the idealx scripts would also change the
+        * sambaPrimaryGroupSid using the ldap replace method. pdb_ldap uses
+        * the delete explicit / add explicit, which would then fail to find
+        * the previous primaryGroupSid value.
         */
+
        if ( IS_SAM_CHANGED(pwd, PDB_GROUPSID) ) {
                status = pdb_set_unix_primary_group(mem_ctx, pwd);
                if ( !NT_STATUS_IS_OK(status) ) {
@@ -3343,16 +3359,6 @@ static NTSTATUS set_user_info_25(TALLOC_CTX *mem_ctx, SAM_USER_INFO_25 *id25,
                }
        }
        
-       /* Don't worry about writing out the user account since the
-          primary group SID is generated solely from the user's Unix 
-          primary group. */
-
-       /* write the change out */
-       if(!NT_STATUS_IS_OK(status = pdb_update_sam_account(pwd))) {
-               TALLOC_FREE(pwd);
-               return status;
-       }
-
        /* WARNING: No TALLOC_FREE(pwd), we are about to set the password
         * hereafter! */
 
@@ -3385,10 +3391,25 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
        if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
                return NT_STATUS_INVALID_HANDLE;
 
-       /* observed when joining an XP client to a Samba domain */
+       /* This is tricky.  A WinXP domain join sets 
+         (SA_RIGHT_USER_SET_PASSWORD|SA_RIGHT_USER_SET_ATTRIBUTES|SA_RIGHT_USER_ACCT_FLAGS_EXPIRY)
+         The MMC lusrmgr plugin includes these perms and more in the SamrOpenUser().  But the 
+         standard Win32 API calls just ask for SA_RIGHT_USER_SET_PASSWORD in the SamrOpenUser().  
+         This should be enough for levels 18, 24, 25,& 26.  Info level 23 can set more so 
+         we'll use the set from the WinXP join as the basis. */
+       
+       switch (switch_value) {
+       case 18:
+       case 24:
+       case 25:
+       case 26:
+               acc_required = SA_RIGHT_USER_SET_PASSWORD;
+               break;
+       default:
+               acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;
+               break;
+       }
        
-       acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;     
-
        if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) {
                return r_u->status;
        }
@@ -3427,7 +3448,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
        }
        
        DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
-               p->pipe_user_name, has_enough_rights ? "" : " not"));
+                 uidtoname(p->pipe_user.ut.uid),
+                 has_enough_rights ? "" : " not"));
 
        /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
        
@@ -3585,7 +3607,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
        }
        
        DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n",
-               p->pipe_user_name, has_enough_rights ? "" : " not"));
+                 uidtoname(p->pipe_user.ut.uid),
+                 has_enough_rights ? "" : " not"));
 
        /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
        
@@ -3745,7 +3768,9 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
 
        DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
 
+       become_root();
        status = pdb_enum_aliasmem(&alias_sid, &sids, &num_sids);
+       unbecome_root();
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -4027,6 +4052,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
        BOOL can_add_accounts;
        uint32 acb_info;
        DISP_INFO *disp_info = NULL;
+       BOOL ret;
 
        DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
 
@@ -4046,7 +4072,11 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
                return NT_STATUS_NO_MEMORY;
        }
 
-       if(!pdb_getsampwsid(sam_pass, &user_sid)) {
+       become_root();
+       ret = pdb_getsampwsid(sam_pass, &user_sid);
+       unbecome_root();
+
+       if( !ret ) {
                DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", 
                        sid_string_static(&user_sid)));
                TALLOC_FREE(sam_pass);
@@ -4571,12 +4601,20 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
 
        /* get the current group information */
 
-       if ( !pdb_get_aliasinfo( &group_sid, &info ) ) {
+       become_root();
+       ret = pdb_get_aliasinfo( &group_sid, &info );
+       unbecome_root();
+
+       if ( !ret ) {
                return NT_STATUS_NO_SUCH_ALIAS;
        }
 
        switch (ctr->level) {
                case 2:
+               {
+                       fstring group_name;
+                       NTSTATUS status;
+
                        /* We currently do not support renaming groups in the
                           the BUILTIN domain.  Refer to util_builtin.c to understand 
                           why.  The eventually needs to be fixed to be like Windows
@@ -4586,13 +4624,22 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
                                return NT_STATUS_SPECIAL_ACCOUNT;
                        }
 
-                       if ( ctr->alias.info2.name.string ) {
-                               unistr2_to_ascii( info.acct_name, ctr->alias.info2.name.string, 
-                                       sizeof(info.acct_name)-1 );
-                       }
-                       else
-                               fstrcpy( info.acct_name, "" );
+                       /* There has to be a valid name */
+                       if ( !ctr->alias.info2.name.string ) 
+                               return NT_STATUS_INVALID_PARAMETER;
+
+                       unistr2_to_ascii( info.acct_name, ctr->alias.info2.name.string, 
+                               sizeof(info.acct_name)-1 );
+
+                       /* make sure the name doesn't already exist as a user 
+                          or local group */
+
+                       fstr_sprintf( group_name, "%s\\%s", global_myname(), info.acct_name );
+                       status = can_create( p->mem_ctx, group_name );
+                       if ( !NT_STATUS_IS_OK( status ) ) 
+                               return status;
                        break;
+               }
                case 3:
                        if ( ctr->alias.info3.description.string ) {
                                unistr2_to_ascii( info.acct_desc,