summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-03-22 08:04:13 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:15:41 -0500
commit1839b4be14e905428257eb999def184d73dcf08f (patch)
tree29560ab3b68ad82990243e0ee40f4f1fc34b04d5
parented9ad1827bcead21483ce59464b5e3da7a509d29 (diff)
downloadsamba-1839b4be14e905428257eb999def184d73dcf08f.tar.gz
samba-1839b4be14e905428257eb999def184d73dcf08f.tar.bz2
samba-1839b4be14e905428257eb999def184d73dcf08f.zip
r14634: Many bug fixes thanks to train rides and overnight stays in airports
* Finally fix parsing idmap uid/gid ranges not to break with spaces surrounding the '-' * Allow local groups to renamed by adding info level 2 to _samr_set_aliasinfo() * Fix parsing bug in _samr_del_dom_alias() reply * Prevent root from being deleted via Samba * Prevent builting groups from being renamed or deleted * Fix bug in pdb_tdb that broke renaming user accounts * Make sure winbindd is running when trying to create the Administrators and Users BUILTIN groups automatically from smbd (and not just check the winbind nexted groups parameter value). * Have the top level rid allocator verify that the RID it is about to grant is not already assigned in our own SAM (retries up to 250 times). This fixes passdb with existing SIDs assigned to users from the RID algorithm but not monotonically allocating the RIDs from passdb. (This used to be commit db1162241f79c2af8afb7d8c26e8ed1c4a4b476f)
-rw-r--r--source3/auth/auth_util.c4
-rw-r--r--source3/groupdb/mapping.c1
-rw-r--r--source3/include/rpc_samr.h5
-rw-r--r--source3/param/loadparm.c4
-rw-r--r--source3/passdb/pdb_interface.c86
-rw-r--r--source3/passdb/pdb_tdb.c20
-rw-r--r--source3/rpc_parse/parse_samr.c29
-rw-r--r--source3/rpc_server/srv_samr_nt.c40
8 files changed, 162 insertions, 27 deletions
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index 2ece2a6150..31bc2664b8 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -834,7 +834,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
/* We can only create a mapping if winbind is running
and the nested group functionality has been enabled */
- if ( lp_winbind_nested_groups() ) {
+ if ( lp_winbind_nested_groups() && winbind_ping() ) {
become_root();
status = create_builtin_administrators( );
if ( !NT_STATUS_IS_OK(status) ) {
@@ -860,7 +860,7 @@ static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
/* We can only create a mapping if winbind is running
and the nested group functionality has been enabled */
- if ( lp_winbind_nested_groups() ) {
+ if ( lp_winbind_nested_groups() && winbind_ping() ) {
become_root();
status = create_builtin_users( );
if ( !NT_STATUS_IS_OK(status) ) {
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 830584979b..5569dbf4ed 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -1164,6 +1164,7 @@ NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
if (!pdb_getgrsid(&map, *sid))
return NT_STATUS_NO_SUCH_ALIAS;
+ fstrcpy(map.nt_name, info->acct_name);
fstrcpy(map.comment, info->acct_desc);
return pdb_update_group_mapping_entry(&map);
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h
index ccb4fc9e44..8a3c4a8420 100644
--- a/source3/include/rpc_samr.h
+++ b/source3/include/rpc_samr.h
@@ -1204,6 +1204,10 @@ typedef struct {
} ALIAS_INFO1;
typedef struct {
+ UNISTR4 name;
+} ALIAS_INFO2;
+
+typedef struct {
UNISTR4 description;
} ALIAS_INFO3;
@@ -1216,6 +1220,7 @@ typedef struct {
uint16 level;
union {
ALIAS_INFO1 info1;
+ ALIAS_INFO2 info2;
ALIAS_INFO3 info3;
} alias;
} ALIAS_INFO_CTR;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 7b831d1e98..0bde5805b0 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -3212,7 +3212,7 @@ static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
{
uint32 low, high;
- if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
+ if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
return False;
/* Parse OK */
@@ -3229,7 +3229,7 @@ static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
{
uint32 low, high;
- if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
+ if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
return False;
/* Parse OK */
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 7ff0214c72..5fdc8ac819 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -426,6 +426,13 @@ static int smb_delete_user(const char *unix_user)
pstring del_script;
int ret;
+ /* safety check */
+
+ if ( strequal( unix_user, "root" ) ) {
+ DEBUG(0,("smb_delete_user: Refusing to delete local system root account!\n"));
+ return -1;
+ }
+
pstrcpy(del_script, lp_deluser_script());
if (! *del_script)
return -1;
@@ -462,11 +469,22 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct)
{
struct pdb_methods *pdb = pdb_get_methods();
+ uid_t uid = -1;
if ( !pdb ) {
return NT_STATUS_UNSUCCESSFUL;
}
+ /* sanity check to make sure we don't delete root */
+
+ if ( !sid_to_uid( pdb_get_user_sid(sam_acct), &uid ) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if ( uid == 0 ) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
return pdb->delete_user(pdb, mem_ctx, sam_acct);
}
@@ -516,6 +534,7 @@ NTSTATUS pdb_delete_sam_account(struct samu *sam_acct)
NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
{
struct pdb_methods *pdb = pdb_get_methods();
+ uid_t uid;
if ( !pdb ) {
return NT_STATUS_NOT_IMPLEMENTED;
@@ -526,6 +545,16 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
csamuser = NULL;
}
+ /* sanity check to make sure we don't rename root */
+
+ if ( !sid_to_uid( pdb_get_user_sid(oldname), &uid ) ) {
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if ( uid == 0 ) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
return pdb->rename_sam_account(pdb, oldname, newname);
}
@@ -976,8 +1005,7 @@ BOOL pdb_find_alias(const char *name, DOM_SID *sid)
return False;
}
- return NT_STATUS_IS_OK(pdb->find_alias(pdb,
- name, sid));
+ return NT_STATUS_IS_OK(pdb->find_alias(pdb, name, sid));
}
NTSTATUS pdb_create_alias(const char *name, uint32 *rid)
@@ -999,8 +1027,7 @@ BOOL pdb_delete_alias(const DOM_SID *sid)
return False;
}
- return NT_STATUS_IS_OK(pdb->delete_alias(pdb,
- sid));
+ return NT_STATUS_IS_OK(pdb->delete_alias(pdb, sid));
}
@@ -1012,8 +1039,7 @@ BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
return False;
}
- return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid,
- info));
+ return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, info));
}
BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
@@ -1024,8 +1050,7 @@ BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
return False;
}
- return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid,
- info));
+ return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, info));
}
NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
@@ -1192,9 +1217,21 @@ BOOL pdb_rid_algorithm(void)
return pdb->rid_algorithm(pdb);
}
+/********************************************************************
+ Allocate a new RID from the passdb backend. Verify that it is free
+ by calling lookup_global_sam_rid() to verify that the RID is not
+ in use. This handles servers that have existing users or groups
+ with add RIDs (assigned from previous algorithmic mappings)
+********************************************************************/
+
BOOL pdb_new_rid(uint32 *rid)
{
struct pdb_methods *pdb = pdb_get_methods();
+ const char *name = NULL;
+ enum SID_NAME_USE type;
+ uint32 allocated_rid = 0;
+ int i;
+ TALLOC_CTX *ctx;
if ( !pdb ) {
return False;
@@ -1215,7 +1252,38 @@ BOOL pdb_new_rid(uint32 *rid)
return False;
}
- return pdb->new_rid(pdb, rid);
+ if ( (ctx = talloc_init("pdb_new_rid")) == NULL ) {
+ DEBUG(0,("pdb_new_rid: Talloc initialization failure\n"));
+ return False;
+ }
+
+ /* Attempt to get an unused RID (max tires is 250...yes that it is
+ and arbitrary number I pulkled out of my head). -- jerry */
+
+ for ( i=0; allocated_rid==0 && i<250; i++ ) {
+ /* get a new RID */
+
+ if ( !pdb->new_rid(pdb, &allocated_rid) ) {
+ return False;
+ }
+
+ /* validate that the RID is not in use */
+
+ if ( lookup_global_sam_rid( ctx, allocated_rid, &name, &type, NULL ) ) {
+ allocated_rid = 0;
+ }
+ }
+
+ TALLOC_FREE( ctx );
+
+ if ( allocated_rid == 0 ) {
+ DEBUG(0,("pdb_new_rid: Failed to find unused RID\n"));
+ return False;
+ }
+
+ *rid = allocated_rid;
+
+ return True;
}
/***************************************************************
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index b7161ff589..94ae328812 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -1382,19 +1382,12 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
BOOL interim_account = False;
int rename_ret;
- /* make sure we have an open handle to the tdb. Should have happened
- at module initialization time */
-
- if ( !tdbsam ) {
- DEBUG(0,("tdbsam_getsampwrid: tdbsam not open!\n"));
- return NT_STATUS_NO_SUCH_USER;
- }
-
/* can't do anything without an external script */
pstrcpy(rename_script, lp_renameuser_script() );
- if ( ! *rename_script )
+ if ( ! *rename_script ) {
return NT_STATUS_ACCESS_DENIED;
+ }
/* invalidate the existing TDB iterator if it is open */
@@ -1421,8 +1414,7 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
/* add the new account and lock it */
- if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) )
- {
+ if ( !tdb_update_samacct_only(new_acct, TDB_INSERT) ) {
goto done;
}
@@ -1441,13 +1433,15 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
- if (rename_ret)
+ if (rename_ret) {
goto done;
+ }
/* rewrite the rid->username record */
- if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) )
+ if ( !tdb_update_ridrec_only( new_acct, TDB_MODIFY) ) {
goto done;
+ }
interim_account = False;
tdb_unlock_bystring( tdbsam, newname );
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index 2f8fe74ed3..2a9daa0e47 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -3554,6 +3554,28 @@ BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 *al3,
reads or writes a structure.
********************************************************************/
+BOOL samr_io_alias_info2(const char *desc, ALIAS_INFO2 *al2,
+ prs_struct *ps, int depth)
+{
+ if (al2 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_alias_info2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if (!prs_unistr4("name", ps, depth, &al2->name))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO_CTR * ctr)
{
if ( !ctr )
@@ -3572,6 +3594,10 @@ BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO
if(!samr_io_alias_info1("alias_info1", &ctr->alias.info1, ps, depth))
return False;
break;
+ case 2:
+ if(!samr_io_alias_info2("alias_info2", &ctr->alias.info2, ps, depth))
+ return False;
+ break;
case 3:
if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth))
return False;
@@ -4474,6 +4500,9 @@ BOOL samr_io_r_delete_dom_alias(const char *desc, SAMR_R_DELETE_DOM_ALIAS * r_u,
if(!prs_align(ps))
return False;
+ if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth))
+ return False;
+
if(!prs_ntstatus("status", ps, depth, &r_u->status))
return False;
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 6a4c9f7133..dc17977041 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -3464,9 +3464,14 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
- /* observed when joining XP client to Samba domain */
+#if 0 /* this really should be applied on a per info level basis --jerry */
+
+ /* observed when joining XP client to Samba domain */
acc_required = SA_RIGHT_USER_SET_PASSWORD | SA_RIGHT_USER_SET_ATTRIBUTES | SA_RIGHT_USER_ACCT_FLAGS_EXPIRY;
+#else
+ acc_required = SA_RIGHT_USER_SET_ATTRIBUTES;
+#endif
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) {
return r_u->status;
@@ -4093,12 +4098,22 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
+ /* copy the handle to the outgoing reply */
+
+ memcpy( &r_u->pol, &q_u->alias_pol, sizeof(r_u->pol) );
+
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_alias"))) {
return r_u->status;
}
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
+ /* Don't let Windows delete builtin groups */
+
+ if ( sid_check_is_in_builtin( &alias_sid ) ) {
+ return NT_STATUS_SPECIAL_ACCOUNT;
+ }
+
if (!sid_check_is_in_our_domain(&alias_sid))
return NT_STATUS_NO_SUCH_ALIAS;
@@ -4453,7 +4468,30 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
ctr=&q_u->ctr;
+ /* get the current group information */
+
+ if ( !pdb_get_aliasinfo( &group_sid, &info ) ) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
switch (ctr->level) {
+ case 2:
+ /* We currently do not support renaming groups in the
+ the BUILTIN domain. Refer to util_builtin.c to understand
+ why. The eventually needs to be fixed to be like Windows
+ where you can rename builtin groups, just not delete them */
+
+ if ( sid_check_is_in_builtin( &group_sid ) ) {
+ return NT_STATUS_SPECIAL_ACCOUNT;
+ }
+
+ if ( ctr->alias.info2.name.string ) {
+ unistr2_to_ascii( info.acct_name, ctr->alias.info2.name.string,
+ sizeof(info.acct_name)-1 );
+ }
+ else
+ fstrcpy( info.acct_name, "" );
+ break;
case 3:
if ( ctr->alias.info3.description.string ) {
unistr2_to_ascii( info.acct_desc,