r11236: Implement user rename for smbpasswd and ldap backends. Some cleanup on
authorJim McDonough <jmcd@samba.org>
Thu, 20 Oct 2005 20:40:47 +0000 (20:40 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:08 +0000 (11:05 -0500)
tdb as well to make naming consistent.

source/passdb/pdb_ldap.c
source/passdb/pdb_smbpasswd.c
source/passdb/pdb_tdb.c
source/rpc_server/srv_samr_nt.c

index ea21a03b516c58528431e815fdf7fb1c4471a022..92ef5133258ce59b5b038cc69dfb137af2c097ea 100644 (file)
@@ -1870,6 +1870,52 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
        return NT_STATUS_OK;
 }
 
+/***************************************************************************
+ Renames a SAM_ACCOUNT
+ - The "rename user script" has full responsibility for changing everything
+***************************************************************************/
+
+static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
+                                          SAM_ACCOUNT *old_acct, 
+                                          const char *newname)
+{
+       const char *oldname;
+       int rc;
+       pstring rename_script;
+
+       if (!old_acct) {
+               DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       if (!newname) {
+               DEBUG(0, ("ldapsam_rename_sam_account: newname was NULL!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+               
+       oldname = pdb_get_username(old_acct);
+
+        /* rename the posix user */
+        pstrcpy(rename_script, lp_renameuser_script());
+
+       if (!(*rename_script))
+               return NT_STATUS_ACCESS_DENIED;
+
+       DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n", 
+                  oldname, newname));
+
+       pstring_sub(rename_script, "%unew", newname);
+       pstring_sub(rename_script, "%uold", oldname);
+       rc = smbrun(rename_script, NULL);
+
+       DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n", 
+                         rename_script, rc));
+
+       if (rc)
+               return NT_STATUS_UNSUCCESSFUL;
+
+       return NT_STATUS_OK;
+}
+
 /**********************************************************************
  Helper function to determine for update_sam_account whether
  we need LDAP modification.
@@ -4203,6 +4249,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
        (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
        (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
        (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
+       (*pdb_method)->rename_sam_account = ldapsam_rename_sam_account;
 
        (*pdb_method)->getgrsid = ldapsam_getgrsid;
        (*pdb_method)->getgrgid = ldapsam_getgrgid;
index 6eb4305409a3a4b025720468afe430d4a1f03546..5fca706a838106f4cf958f5b32de3ac92741d563 100644 (file)
@@ -1477,6 +1477,62 @@ static NTSTATUS smbpasswd_delete_sam_account (struct pdb_methods *my_methods, SA
        return NT_STATUS_UNSUCCESSFUL;
 }
 
+static NTSTATUS smbpasswd_rename_sam_account (struct pdb_methods *my_methods, 
+                                             SAM_ACCOUNT *old_acct,
+                                             const char *newname)
+{
+       struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
+       pstring rename_script;
+       SAM_ACCOUNT *new_acct = NULL;
+       BOOL interim_account = False;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+       if (!*(lp_renameuser_script()))
+               goto done;
+
+       if (!pdb_copy_sam_account(old_acct, &new_acct) ||
+           !pdb_set_username(new_acct, newname, PDB_CHANGED))
+               goto done;
+
+       ret = smbpasswd_add_sam_account(my_methods, new_acct);
+       if (!NT_STATUS_IS_OK(ret))
+               goto done;
+
+       interim_account = True;
+
+       /* rename the posix user */
+       pstrcpy(rename_script, lp_renameuser_script());
+
+       if (*rename_script) {
+               int rename_ret;
+
+               pstring_sub(rename_script, "%unew", newname);
+               pstring_sub(rename_script, "%uold", 
+                           pdb_get_username(old_acct));
+               rename_ret = smbrun(rename_script, NULL);
+
+               DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
+
+               if (rename_ret) 
+                       goto done; 
+        } else {
+               goto done;
+       }
+
+       smbpasswd_delete_sam_account(my_methods, old_acct);
+       interim_account = False;
+
+done:  
+       /* cleanup */
+       if (interim_account)
+               smbpasswd_delete_sam_account(my_methods, new_acct);
+
+       if (new_acct)
+               pdb_free_sam(&new_acct);
+       
+       return (ret);   
+}
+
 static void free_private_data(void **vp) 
 {
        struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
@@ -1506,6 +1562,7 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
        (*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
        (*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
        (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
+       (*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
 
        /* Setup private data and free function */
 
index f04c82a5b157c8708b6dcd7735b097dbfaf2c304..8bf9b1b2828cdc1f7fbd94a81e858a29765a5b36 100644 (file)
@@ -775,7 +775,8 @@ static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCO
  - unlock the new user record
 ***************************************************************************/
 static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
-                                         SAM_ACCOUNT *oldname, const char *newname)
+                                         SAM_ACCOUNT *old_acct, 
+                                         const char *newname)
 {
        struct tdbsam_privates *tdb_state = 
                (struct tdbsam_privates *)my_methods->private_data;
@@ -788,7 +789,7 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
        if (!*(lp_renameuser_script()))
                goto done;
 
-       if (!pdb_copy_sam_account(oldname, &new_acct) ||
+       if (!pdb_copy_sam_account(old_acct, &new_acct) ||
            !pdb_set_username(new_acct, newname, PDB_CHANGED))
                goto done;
 
@@ -826,7 +827,8 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
                int rename_ret;
 
                pstring_sub(rename_script, "%unew", newname);
-               pstring_sub(rename_script, "%uold", pdb_get_username(oldname));
+               pstring_sub(rename_script, "%uold", 
+                           pdb_get_username(old_acct));
                rename_ret = smbrun(rename_script, NULL);
 
                DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
@@ -843,7 +845,7 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
        interim_account = False;
        tdb_unlock_bystring(pwd_tdb, newname);
 
-       tdb_delete_samacct_only(pwd_tdb, my_methods, oldname);
+       tdb_delete_samacct_only(pwd_tdb, my_methods, old_acct);
 
        ret = NT_STATUS_OK;
 
index 45a77197ee19cadd7bc5ae6171bc23f3092968e7..598f9db1dad3eedceacbe94572b58a1a8a9358c8 100644 (file)
@@ -2429,7 +2429,9 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
 static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
 {
        fstring new_name;
+       SAM_ACCOUNT *check_acct = NULL;
        NTSTATUS rc;
+       BOOL check_rc;
 
        if (id7 == NULL) {
                DEBUG(5, ("set_user_info_7: NULL id7\n"));
@@ -2443,6 +2445,24 @@ static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
                return NT_STATUS_ACCESS_DENIED;
        }
 
+       /* check to see if the new username already exists.  Note: we can't
+          reliably lock all backends, so there is potentially the 
+          possibility that a user can be created in between this check and
+          the rename.  The rename should fail, but may not get the
+          exact same failure status code.  I think this is small enough
+          of a window for this type of operation and the results are
+          simply that the rename fails with a slightly different status
+          code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */
+
+       pdb_init_sam(&check_acct);
+       check_rc = pdb_getsampwnam(check_acct, new_name);
+       pdb_free_sam(&check_acct);
+
+       if (check_rc == True) {
+               /* this account exists: say so */
+               return NT_STATUS_USER_EXISTS;
+       }
+
        rc = pdb_rename_sam_account(pwd, new_name);
 
        pdb_free_sam(&pwd);