From 9f6fb43eeefb18578040a0f3b5af941460ec5ca9 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 19 Jul 2006 20:59:04 +0000 Subject: r17150: MMC User & group plugins fixes: * 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 | 29 ++++++++++++++++++++++++++--- source3/passdb/pdb_ldap.c | 14 +++++++++++--- source3/passdb/pdb_tdb.c | 20 +++++++++++++++----- source3/rpc_server/srv_samr_nt.c | 32 +++++++++++++++++++++++++------- 4 files changed, 77 insertions(+), 18 deletions(-) (limited to 'source3') diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 20aa72d24e..7f2a8f25b3 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -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) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 83f8d7183c..7dc76dafe7 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -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); diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index ac8cbbe91a..b16368baf1 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -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)); diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 9c453b04a4..3a70c93a1c 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -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); -- cgit