summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/passdb/pdb_ldap.c47
-rw-r--r--source3/passdb/pdb_smbpasswd.c57
-rw-r--r--source3/passdb/pdb_tdb.c10
-rw-r--r--source3/rpc_server/srv_samr_nt.c20
4 files changed, 130 insertions, 4 deletions
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);