r17150: MMC User & group plugins fixes:
authorGerald Carter <jerry@samba.org>
Wed, 19 Jul 2006 20:59:04 +0000 (20:59 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:38:16 +0000 (11:38 -0500)
* Make sure to lower case all usernames before
  calling the create, delete, or rename hooks.
* Preserve case for usernames in passdb
* Flush the getpwnam cache after renaming a user
* Add become/unbecome root block in _samr_delete_dom_user()
  when trying to verify the account's existence.
(This used to be commit bbe11b7a950e7d85001f042bbd1ea3bf33ecda7b)

source3/passdb/pdb_interface.c
source3/passdb/pdb_ldap.c
source3/passdb/pdb_tdb.c
source3/rpc_server/srv_samr_nt.c

index 20aa72d24ee37b2a34c9948c96c530736aa5d2d4..7f2a8f25b3d08b22120bd103ffdf8f5f0ce28d53 100644 (file)
@@ -344,6 +344,7 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
        if ( !(pwd = Get_Pwnam_alloc(tmp_ctx, name)) ) {
                pstring add_script;
                int add_ret;
+               fstring name2;
 
                if ((acb_info & ACB_NORMAL) && name[strlen(name)-1] != '$') {
                        pstrcpy(add_script, lp_adduser_script());
@@ -357,7 +358,11 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
                        return NT_STATUS_NO_SUCH_USER;
                }
 
-               all_string_sub(add_script, "%u", name, sizeof(add_script));
+               /* lowercase the username before creating the Unix account for 
+                  compatibility with previous Samba releases */
+               fstrcpy( name2, name );
+               strlower_m( name2 );
+               all_string_sub(add_script, "%u", name2, sizeof(add_script));
                add_ret = smbrun(add_script,NULL);
                DEBUG(add_ret ? 0 : 3, ("_samr_create_user: Running the command `%s' gave %d\n",
                                        add_script, add_ret));
@@ -392,6 +397,10 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
                return NT_STATUS_INTERNAL_ERROR;
        }
 
+       /* Use the username case specified in the original request */
+
+       pdb_set_username( sam_pass, name, PDB_SET );
+
        /* Disable the account on creation, it does not have a reasonable password yet. */
 
        acb_info |= ACB_DISABLED;
@@ -444,6 +453,7 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
                                        struct samu *sam_acct)
 {
        NTSTATUS status;
+       fstring username;
 
        status = pdb_delete_sam_account(sam_acct);
        if (!NT_STATUS_IS_OK(status)) {
@@ -456,7 +466,14 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
         * not necessary present and maybe the sysadmin doesn't want to delete
         * the unix side
         */
-       smb_delete_user( pdb_get_username(sam_acct) );
+
+       /* always lower case the username before handing it off to 
+          external scripts */
+
+       fstrcpy( username, pdb_get_username(sam_acct) );
+       strlower_m( username );
+
+       smb_delete_user( username );
        
        return status;
 }
@@ -513,6 +530,7 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
 {
        struct pdb_methods *pdb = pdb_get_methods();
        uid_t uid;
+       NTSTATUS status;
 
        if (csamuser != NULL) {
                TALLOC_FREE(csamuser);
@@ -529,7 +547,12 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       return pdb->rename_sam_account(pdb, oldname, newname);
+       status = pdb->rename_sam_account(pdb, oldname, newname);
+
+       /* always flush the cache here just to be safe */
+       flush_pwnam_cache();
+
+       return status;
 }
 
 NTSTATUS pdb_update_login_attempts(struct samu *sam_acct, BOOL success)
index 83f8d7183ccf6fe66abdbfb1b7639ceb816334a4..7dc76dafe7b47890cd6159b27f6ef3db23a36fea 100644 (file)
@@ -1831,6 +1831,7 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
        const char *oldname;
        int rc;
        pstring rename_script;
+       fstring oldname_lower, newname_lower;
 
        if (!old_acct) {
                DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
@@ -1852,10 +1853,17 @@ static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
        DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n", 
                   oldname, newname));
 
-       /* we have to allow the account name to end with a '$' */
-       string_sub2(rename_script, "%unew", newname, sizeof(pstring), 
+       /* We have to allow the account name to end with a '$'.
+          Also, follow the semantics in _samr_create_user() and lower case the
+          posix name but preserve the case in passdb */
+
+       fstrcpy( oldname_lower, oldname );
+       strlower_m( oldname_lower );
+       fstrcpy( newname_lower, newname );
+       strlower_m( newname_lower );
+       string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring), 
                    True, False, True);
-       string_sub2(rename_script, "%uold", oldname, sizeof(pstring), 
+       string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring), 
                    True, False, True);
        rc = smbrun(rename_script, NULL);
 
index ac8cbbe91a3d98ab631eb8395a657657ddee88a5..b16368baf17ca76cf2786d97e1d17d5ad5544ed1 100644 (file)
@@ -1399,6 +1399,8 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
        pstring          rename_script;
        BOOL             interim_account = False;
        int              rename_ret;
+       fstring          oldname_lower;
+       fstring          newname_lower;
 
        /* can't do anything without an external script */
        
@@ -1442,11 +1444,19 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
                goto done;
        }
 
-       /* rename the posix user */
-       string_sub2(rename_script, "%unew", newname, sizeof(pstring), 
-                   True, False, True);
-       string_sub2(rename_script, "%uold", pdb_get_username(old_acct), 
-                   sizeof(pstring), True, False, True);
+       /* Rename the posix user.  Follow the semantics of _samr_create_user()
+          so that we lower case the posix name but preserve the case in passdb */
+
+       fstrcpy( oldname_lower, pdb_get_username(old_acct) );
+       strlower_m( oldname_lower );
+
+       fstrcpy( newname_lower, newname );
+       strlower_m( newname_lower );
+
+       string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring), 
+               True, False, True);
+       string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring), 
+               True, False, True);
        rename_ret = smbrun(rename_script, NULL);
 
        DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
index 9c453b04a42a3b5a3012ef19a753024821123640..3a70c93a1c5d5227425773dee1eae261bcba3728 100644 (file)
@@ -2471,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;
@@ -3214,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() ) {
@@ -3396,10 +3394,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;
        }
@@ -4040,6 +4053,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__));
 
@@ -4059,7 +4073,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);