1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

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 db1162241f)
This commit is contained in:
Gerald Carter 2006-03-22 08:04:13 +00:00 committed by Gerald (Jerry) Carter
parent ed9ad1827b
commit 1839b4be14
8 changed files with 162 additions and 27 deletions

View File

@ -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 /* We can only create a mapping if winbind is running
and the nested group functionality has been enabled */ and the nested group functionality has been enabled */
if ( lp_winbind_nested_groups() ) { if ( lp_winbind_nested_groups() && winbind_ping() ) {
become_root(); become_root();
status = create_builtin_administrators( ); status = create_builtin_administrators( );
if ( !NT_STATUS_IS_OK(status) ) { 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 /* We can only create a mapping if winbind is running
and the nested group functionality has been enabled */ and the nested group functionality has been enabled */
if ( lp_winbind_nested_groups() ) { if ( lp_winbind_nested_groups() && winbind_ping() ) {
become_root(); become_root();
status = create_builtin_users( ); status = create_builtin_users( );
if ( !NT_STATUS_IS_OK(status) ) { if ( !NT_STATUS_IS_OK(status) ) {

View File

@ -1164,6 +1164,7 @@ NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
if (!pdb_getgrsid(&map, *sid)) if (!pdb_getgrsid(&map, *sid))
return NT_STATUS_NO_SUCH_ALIAS; return NT_STATUS_NO_SUCH_ALIAS;
fstrcpy(map.nt_name, info->acct_name);
fstrcpy(map.comment, info->acct_desc); fstrcpy(map.comment, info->acct_desc);
return pdb_update_group_mapping_entry(&map); return pdb_update_group_mapping_entry(&map);

View File

@ -1203,6 +1203,10 @@ typedef struct {
uint32 num_member; uint32 num_member;
} ALIAS_INFO1; } ALIAS_INFO1;
typedef struct {
UNISTR4 name;
} ALIAS_INFO2;
typedef struct { typedef struct {
UNISTR4 description; UNISTR4 description;
} ALIAS_INFO3; } ALIAS_INFO3;
@ -1216,6 +1220,7 @@ typedef struct {
uint16 level; uint16 level;
union { union {
ALIAS_INFO1 info1; ALIAS_INFO1 info1;
ALIAS_INFO2 info2;
ALIAS_INFO3 info3; ALIAS_INFO3 info3;
} alias; } alias;
} ALIAS_INFO_CTR; } ALIAS_INFO_CTR;

View File

@ -3212,7 +3212,7 @@ static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
{ {
uint32 low, high; 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; return False;
/* Parse OK */ /* Parse OK */
@ -3229,7 +3229,7 @@ static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
{ {
uint32 low, high; 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; return False;
/* Parse OK */ /* Parse OK */

View File

@ -426,6 +426,13 @@ static int smb_delete_user(const char *unix_user)
pstring del_script; pstring del_script;
int ret; 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()); pstrcpy(del_script, lp_deluser_script());
if (! *del_script) if (! *del_script)
return -1; 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) NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct)
{ {
struct pdb_methods *pdb = pdb_get_methods(); struct pdb_methods *pdb = pdb_get_methods();
uid_t uid = -1;
if ( !pdb ) { if ( !pdb ) {
return NT_STATUS_UNSUCCESSFUL; 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); 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) NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
{ {
struct pdb_methods *pdb = pdb_get_methods(); struct pdb_methods *pdb = pdb_get_methods();
uid_t uid;
if ( !pdb ) { if ( !pdb ) {
return NT_STATUS_NOT_IMPLEMENTED; return NT_STATUS_NOT_IMPLEMENTED;
@ -526,6 +545,16 @@ NTSTATUS pdb_rename_sam_account(struct samu *oldname, const char *newname)
csamuser = NULL; 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); 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 False;
} }
return NT_STATUS_IS_OK(pdb->find_alias(pdb, return NT_STATUS_IS_OK(pdb->find_alias(pdb, name, sid));
name, sid));
} }
NTSTATUS pdb_create_alias(const char *name, uint32 *rid) NTSTATUS pdb_create_alias(const char *name, uint32 *rid)
@ -999,8 +1027,7 @@ BOOL pdb_delete_alias(const DOM_SID *sid)
return False; return False;
} }
return NT_STATUS_IS_OK(pdb->delete_alias(pdb, return NT_STATUS_IS_OK(pdb->delete_alias(pdb, sid));
sid));
} }
@ -1012,8 +1039,7 @@ BOOL pdb_get_aliasinfo(const DOM_SID *sid, struct acct_info *info)
return False; return False;
} }
return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, return NT_STATUS_IS_OK(pdb->get_aliasinfo(pdb, sid, info));
info));
} }
BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *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 False;
} }
return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, return NT_STATUS_IS_OK(pdb->set_aliasinfo(pdb, sid, info));
info));
} }
NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member) 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); 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) BOOL pdb_new_rid(uint32 *rid)
{ {
struct pdb_methods *pdb = pdb_get_methods(); 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 ) { if ( !pdb ) {
return False; return False;
@ -1215,7 +1252,38 @@ BOOL pdb_new_rid(uint32 *rid)
return False; 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;
} }
/*************************************************************** /***************************************************************

View File

@ -1382,19 +1382,12 @@ static NTSTATUS tdbsam_rename_sam_account(struct pdb_methods *my_methods,
BOOL interim_account = False; BOOL interim_account = False;
int rename_ret; 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 */ /* can't do anything without an external script */
pstrcpy(rename_script, lp_renameuser_script() ); pstrcpy(rename_script, lp_renameuser_script() );
if ( ! *rename_script ) if ( ! *rename_script ) {
return NT_STATUS_ACCESS_DENIED; return NT_STATUS_ACCESS_DENIED;
}
/* invalidate the existing TDB iterator if it is open */ /* 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 */ /* 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; 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)); DEBUG(rename_ret ? 0 : 3,("Running the command `%s' gave %d\n", rename_script, rename_ret));
if (rename_ret) if (rename_ret) {
goto done; goto done;
}
/* rewrite the rid->username record */ /* 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; goto done;
}
interim_account = False; interim_account = False;
tdb_unlock_bystring( tdbsam, newname ); tdb_unlock_bystring( tdbsam, newname );

View File

@ -3554,6 +3554,28 @@ BOOL samr_io_alias_info3(const char *desc, ALIAS_INFO3 *al3,
reads or writes a structure. 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) BOOL samr_alias_info_ctr(const char *desc, prs_struct *ps, int depth, ALIAS_INFO_CTR * ctr)
{ {
if ( !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)) if(!samr_io_alias_info1("alias_info1", &ctr->alias.info1, ps, depth))
return False; return False;
break; break;
case 2:
if(!samr_io_alias_info2("alias_info2", &ctr->alias.info2, ps, depth))
return False;
break;
case 3: case 3:
if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth)) if(!samr_io_alias_info3("alias_info3", &ctr->alias.info3, ps, depth))
return False; 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)) if(!prs_align(ps))
return False; return False;
if(!smb_io_pol_hnd("pol", &r_u->pol, ps, depth))
return False;
if(!prs_ntstatus("status", ps, depth, &r_u->status)) if(!prs_ntstatus("status", ps, depth, &r_u->status))
return False; return False;

View File

@ -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)) if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE; 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; 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"))) { if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) {
return r_u->status; 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)) if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE; 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"))) { 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; return r_u->status;
} }
DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid))); 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)) if (!sid_check_is_in_our_domain(&alias_sid))
return NT_STATUS_NO_SUCH_ALIAS; 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; 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) { 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: case 3:
if ( ctr->alias.info3.description.string ) { if ( ctr->alias.info3.description.string ) {
unistr2_to_ascii( info.acct_desc, unistr2_to_ascii( info.acct_desc,