From 1113cad9c0c81e9ecec3a0f4317c950943cfc62a Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Thu, 20 Oct 2005 20:40:47 +0000 Subject: r11236: Implement user rename for smbpasswd and ldap backends. Some cleanup on tdb as well to make naming consistent. (This used to be commit ee91eb9a39cc5e3edd9e97eb040e7557930e4e62) --- source3/passdb/pdb_ldap.c | 47 +++++++++++++++++++++++++++++++++ source3/passdb/pdb_smbpasswd.c | 57 ++++++++++++++++++++++++++++++++++++++++ source3/passdb/pdb_tdb.c | 10 ++++--- source3/rpc_server/srv_samr_nt.c | 20 ++++++++++++++ 4 files changed, 130 insertions(+), 4 deletions(-) (limited to 'source3') diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index ea21a03b51..92ef513325 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -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; diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 6eb4305409..5fca706a83 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -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 */ diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index f04c82a5b1..8bf9b1b282 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -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; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 45a77197ee..598f9db1da 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -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); -- cgit