summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2005-10-11 20:14:04 +0000
committerJim McDonough <jmcd@samba.org>2005-10-11 20:14:04 +0000
commit50d11e944c4465ea090bd961b59fac14926e2017 (patch)
treeb085eee57816c77c9d812da9f259bd93854bc4e2 /source
parent8b1c8d12b14b29a5c11402f3e3b9727e74508ec6 (diff)
downloadsamba-50d11e944c4465ea090bd961b59fac14926e2017.tar.gz
samba-50d11e944c4465ea090bd961b59fac14926e2017.tar.xz
samba-50d11e944c4465ea090bd961b59fac14926e2017.zip
r10911: part of #2861: add rename support for usrmgr.exe when using tdbsam
This gets it working before replacing tdb with the samba4 version.
Diffstat (limited to 'source')
-rw-r--r--source/include/passdb.h6
-rw-r--r--source/param/loadparm.c3
-rw-r--r--source/passdb/pdb_interface.c58
-rw-r--r--source/passdb/pdb_tdb.c248
-rw-r--r--source/rpc_server/srv_samr_nt.c29
5 files changed, 303 insertions, 41 deletions
diff --git a/source/include/passdb.h b/source/include/passdb.h
index e985ab582dc..4964ff37591 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -269,7 +269,7 @@ struct pdb_search {
* this SAMBA will load. Increment this if *ANY* changes are made to the interface.
*/
-#define PASSDB_INTERFACE_VERSION 9
+#define PASSDB_INTERFACE_VERSION 10
typedef struct pdb_context
{
@@ -294,6 +294,8 @@ typedef struct pdb_context
NTSTATUS (*pdb_update_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
NTSTATUS (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username);
+
+ NTSTATUS (*pdb_rename_sam_account)(struct pdb_context *, SAM_ACCOUNT *oldname, const char *newname);
NTSTATUS (*pdb_update_login_attempts)(struct pdb_context *context, SAM_ACCOUNT *sam_acct, BOOL success);
@@ -422,6 +424,8 @@ typedef struct pdb_methods
NTSTATUS (*delete_sam_account)(struct pdb_methods *, SAM_ACCOUNT *username);
+ NTSTATUS (*rename_sam_account)(struct pdb_methods *, SAM_ACCOUNT *oldname, const char *newname);
+
NTSTATUS (*update_login_attempts)(struct pdb_methods *methods, SAM_ACCOUNT *sam_acct, BOOL success);
NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, DOM_SID sid);
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 126d70939c0..dc2784804d5 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -151,6 +151,7 @@ typedef struct
char *szNameResolveOrder;
char *szPanicAction;
char *szAddUserScript;
+ char *szRenameUserScript;
char *szDelUserScript;
char *szAddGroupScript;
char *szDelGroupScript;
@@ -1061,6 +1062,7 @@ static struct parm_struct parm_table[] = {
{N_("Logon Options"), P_SEP, P_SEPARATOR},
{"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED},
+ {"rename user script", P_STRING, P_GLOBAL, &Globals.szRenameUserScript, NULL, NULL, FLAG_ADVANCED},
{"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED},
{"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED},
{"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED},
@@ -1734,6 +1736,7 @@ FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
+FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index a9e41984c3d..485f4055682 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -325,6 +325,41 @@ static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCO
return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
}
+static NTSTATUS context_rename_sam_account(struct pdb_context *context, SAM_ACCOUNT *oldname, const char *newname)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ struct pdb_methods *pdb_selected;
+ if (!context) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ if (!oldname->methods){
+ pdb_selected = context->pdb_methods;
+ /* There's no passdb backend specified for this account.
+ * Try to delete it in every passdb available
+ * Needed to delete accounts in smbpasswd that are not
+ * in /etc/passwd.
+ */
+ while (pdb_selected){
+ if (NT_STATUS_IS_OK(ret = pdb_selected->rename_sam_account(pdb_selected, oldname, newname))) {
+ return ret;
+ }
+ pdb_selected = pdb_selected->next;
+ }
+ return ret;
+ }
+
+ if (!oldname->methods->rename_sam_account){
+ DEBUG(0,("invalid oldname->methods->rename_sam_account\n"));
+ return ret;
+ }
+
+ return oldname->methods->rename_sam_account(oldname->methods, oldname, newname);
+}
+
+
static NTSTATUS context_update_login_attempts(struct pdb_context *context,
SAM_ACCOUNT *sam_acct, BOOL success)
{
@@ -850,6 +885,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_add_sam_account = context_add_sam_account;
(*context)->pdb_update_sam_account = context_update_sam_account;
(*context)->pdb_delete_sam_account = context_delete_sam_account;
+ (*context)->pdb_rename_sam_account = context_rename_sam_account;
(*context)->pdb_update_login_attempts = context_update_login_attempts;
(*context)->pdb_getgrsid = context_getgrsid;
(*context)->pdb_getgrgid = context_getgrgid;
@@ -1103,6 +1139,22 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
}
+NTSTATUS pdb_rename_sam_account(SAM_ACCOUNT *oldname, const char *newname)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (sam_account_cache != NULL) {
+ pdb_free_sam(&sam_account_cache);
+ sam_account_cache = NULL;
+ }
+
+ return pdb_context->pdb_rename_sam_account(pdb_context, oldname, newname);
+}
+
NTSTATUS pdb_update_login_attempts(SAM_ACCOUNT *sam_acct, BOOL success)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
@@ -1440,6 +1492,11 @@ static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM
return NT_STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS pdb_default_rename_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *pwd, const char *newname)
+{
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods, SAM_ACCOUNT *newpwd, BOOL success)
{
return NT_STATUS_OK;
@@ -1983,6 +2040,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->add_sam_account = pdb_default_add_sam_account;
(*methods)->update_sam_account = pdb_default_update_sam_account;
(*methods)->delete_sam_account = pdb_default_delete_sam_account;
+ (*methods)->rename_sam_account = pdb_default_rename_sam_account;
(*methods)->update_login_attempts = pdb_default_update_login_attempts;
(*methods)->getgrsid = pdb_default_getgrsid;
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index 755e33940b8..f04c82a5b15 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -6,6 +6,7 @@
* Copyright (C) Gerald Carter 2000
* Copyright (C) Jeremy Allison 2001
* Copyright (C) Andrew Bartlett 2002
+ * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
@@ -515,6 +516,32 @@ static NTSTATUS tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT *
return tdbsam_getsampwrid(my_methods, user, rid);
}
+static BOOL tdb_delete_samacct_only(TDB_CONTEXT *pwd_tdb,
+ struct pdb_methods *my_methods,
+ SAM_ACCOUNT *sam_pass)
+{
+ TDB_DATA key;
+ fstring keystr;
+ fstring name;
+
+ fstrcpy(name, pdb_get_username(sam_pass));
+ strlower_m(name);
+
+ /* set the search key */
+ slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
+ key.dptr = keystr;
+ key.dsize = strlen (keystr) + 1;
+
+ /* it's outaa here! 8^) */
+ if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
+ DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
+ DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ tdb_close(pwd_tdb);
+ return False;
+ }
+ return True;
+}
+
/***************************************************************************
Delete a SAM_ACCOUNT
****************************************************************************/
@@ -573,50 +600,19 @@ static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_AC
return NT_STATUS_OK;
}
+
/***************************************************************************
- Update the TDB SAM
+ Update the TDB SAM account record only
****************************************************************************/
-
-static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
+static BOOL tdb_update_samacct_only(TDB_CONTEXT *pwd_tdb,
+ struct pdb_methods *my_methods,
+ SAM_ACCOUNT* newpwd, int flag)
{
- struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
- TDB_CONTEXT *pwd_tdb = NULL;
TDB_DATA key, data;
uint8 *buf = NULL;
fstring keystr;
fstring name;
BOOL ret = True;
- uint32 user_rid;
-
- /* invalidate the existing TDB iterator if it is open */
-
- if (tdb_state->passwd_tdb) {
- tdb_close(tdb_state->passwd_tdb);
- tdb_state->passwd_tdb = NULL;
- }
-
- /* open the account TDB passwd*/
-
- pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
-
- if (!pwd_tdb) {
- DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
- tdb_state->tdbsam_location));
- return False;
- }
-
- if (!pdb_get_group_rid(newpwd)) {
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
- pdb_get_username(newpwd)));
- ret = False;
- goto done;
- }
-
- if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
- DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
- ret = False;
- goto done;
- }
/* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) {
@@ -629,7 +625,9 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
fstrcpy(name, pdb_get_username(newpwd));
strlower_m(name);
- DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid));
+ DEBUG(5, ("Storing %saccount %s with RID %d\n",
+ flag == TDB_INSERT ? "(new) " : "", name,
+ pdb_get_user_rid(newpwd)));
/* setup the USER index key */
slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
@@ -640,17 +638,40 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
DEBUG(0, ("Unable to modify passwd TDB!"));
DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
- DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
+ DEBUGADD(0, (" occured while storing the main record (%s)\n",
+ keystr));
ret = False;
goto done;
}
+
+done:
+ /* cleanup */
+ SAFE_FREE(buf);
+ return (ret);
+}
+
+/***************************************************************************
+ Update the TDB SAM RID record only
+****************************************************************************/
+static BOOL tdb_update_ridrec_only(TDB_CONTEXT *pwd_tdb,
+ struct pdb_methods *my_methods,
+ SAM_ACCOUNT* newpwd, int flag)
+{
+ TDB_DATA key, data;
+ fstring keystr;
+ fstring name;
+
+ fstrcpy(name, pdb_get_username(newpwd));
+ strlower_m(name);
+
/* setup RID data */
data.dsize = strlen(name) + 1;
data.dptr = name;
/* setup the RID index key */
- slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid);
+ slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX,
+ pdb_get_user_rid(newpwd));
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
@@ -659,6 +680,56 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
DEBUG(0, ("Unable to modify TDB passwd !"));
DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
+ return False;
+ }
+
+ return True;
+
+}
+
+/***************************************************************************
+ Update the TDB SAM
+****************************************************************************/
+
+static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, int flag)
+{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ BOOL ret = True;
+ uint32 user_rid;
+
+ /* invalidate the existing TDB iterator if it is open */
+
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+
+ /* open the account TDB passwd*/
+
+ pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+
+ if (!pwd_tdb) {
+ DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
+ tdb_state->tdbsam_location));
+ return False;
+ }
+
+ if (!pdb_get_group_rid(newpwd)) {
+ DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",
+ pdb_get_username(newpwd)));
+ ret = False;
+ goto done;
+ }
+
+ if ( !(user_rid = pdb_get_user_rid(newpwd)) ) {
+ DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd)));
+ ret = False;
+ goto done;
+ }
+
+ if (!tdb_update_samacct_only(pwd_tdb, my_methods, newpwd, flag) ||
+ !tdb_update_ridrec_only(pwd_tdb, my_methods, newpwd, flag)) {
ret = False;
goto done;
}
@@ -666,7 +737,6 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
done:
/* cleanup */
tdb_close (pwd_tdb);
- SAFE_FREE(buf);
return (ret);
}
@@ -695,6 +765,103 @@ static NTSTATUS tdbsam_add_sam_account (struct pdb_methods *my_methods, SAM_ACCO
return NT_STATUS_UNSUCCESSFUL;
}
+/***************************************************************************
+ Renames a SAM_ACCOUNT
+ - check for the posix user/rename user script
+ - Add and lock the new user record
+ - rename the posix user
+ - rewrite the rid->username record
+ - delete the old user
+ - unlock the new user record
+***************************************************************************/
+static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
+ SAM_ACCOUNT *oldname, const char *newname)
+{
+ struct tdbsam_privates *tdb_state =
+ (struct tdbsam_privates *)my_methods->private_data;
+ SAM_ACCOUNT *new_acct = NULL;
+ pstring rename_script;
+ TDB_CONTEXT *pwd_tdb = NULL;
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ BOOL interim_account = False;
+
+ if (!*(lp_renameuser_script()))
+ goto done;
+
+ if (!pdb_copy_sam_account(oldname, &new_acct) ||
+ !pdb_set_username(new_acct, newname, PDB_CHANGED))
+ goto done;
+
+ /* invalidate the existing TDB iterator if it is open */
+
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+
+ /* open the account TDB passwd */
+
+ pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
+
+ if (!pwd_tdb) {
+ DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
+ tdb_state->tdbsam_location));
+ goto done;
+ }
+
+ /* add the new account and lock it */
+ if (!tdb_update_samacct_only(pwd_tdb, my_methods, new_acct,
+ TDB_INSERT))
+ goto done;
+ interim_account = True;
+
+ if (tdb_lock_bystring(pwd_tdb, newname, 30) == -1) {
+ goto done;
+ }
+
+ /* 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(oldname));
+ 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;
+ }
+
+ /* rewrite the rid->username record */
+ if (!tdb_update_ridrec_only(pwd_tdb, my_methods, new_acct, TDB_MODIFY))
+ goto done;
+ interim_account = False;
+ tdb_unlock_bystring(pwd_tdb, newname);
+
+ tdb_delete_samacct_only(pwd_tdb, my_methods, oldname);
+
+ ret = NT_STATUS_OK;
+
+
+done:
+ /* cleanup */
+ if (interim_account) {
+ tdb_unlock_bystring(pwd_tdb, newname);
+ tdb_delete_samacct_only(pwd_tdb, my_methods, new_acct);
+ }
+ if (pwd_tdb)
+ tdb_close (pwd_tdb);
+ if (new_acct)
+ pdb_free_sam(&new_acct);
+
+ return (ret);
+}
+
static void free_private_data(void **vp)
{
struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
@@ -736,6 +903,7 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
(*pdb_method)->add_sam_account = tdbsam_add_sam_account;
(*pdb_method)->update_sam_account = tdbsam_update_sam_account;
(*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
+ (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
tdb_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct tdbsam_privates);
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index b69f03a3a28..26a691e9b40 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -2424,6 +2424,32 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
}
/*******************************************************************
+ set_user_info_7
+ ********************************************************************/
+static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
+{
+ fstring new_name;
+ NTSTATUS rc;
+
+ if (id7 == NULL) {
+ DEBUG(5, ("set_user_info_7: NULL id7\n"));
+ pdb_free_sam(&pwd);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if(!rpcstr_pull(new_name, id7->uni_name.buffer, sizeof(new_name), id7->uni_name.uni_str_len*2, 0)) {
+ DEBUG(5, ("set_user_info_7: failed to get new username\n"));
+ pdb_free_sam(&pwd);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ rc = pdb_rename_sam_account(pwd, new_name);
+
+ pdb_free_sam(&pwd);
+ return rc;
+}
+
+/*******************************************************************
set_user_info_16
********************************************************************/
@@ -2924,6 +2950,9 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch (switch_value) {
+ case 7:
+ r_u->status = set_user_info_7(ctr->info.id7, pwd);
+ break;
case 16:
if (!set_user_info_16(ctr->info.id16, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;