From b3757eadf05a4e47a5cd19049ee2c5eecf140c37 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 19 Jan 2005 16:52:19 +0000 Subject: r4849: * finish SeAddUsers support in srv_samr_nt.c * define some const SE_PRIV structure for use when you need a SE_PRIV* to a privilege * fix an annoying compiler warngin in smbfilter.c * translate SIDs to names in 'net rpc rights list accounts' * fix a seg fault in cli_lsa_enum_account_rights caused by me forgetting the precedence of * vs. [] (This used to be commit d25fc84bc2b14da9fcc0f3c8d7baeca83f0ea708) --- source3/include/privileges.h | 53 ++---- source3/lib/privileges.c | 25 ++- source3/rpc_client/cli_lsarpc.c | 9 +- source3/rpc_server/srv_samr_nt.c | 358 ++++++++++++++++++++++++++++----------- source3/utils/net_rpc_rights.c | 56 ++++-- source3/utils/smbfilter.c | 4 +- 6 files changed, 346 insertions(+), 159 deletions(-) (limited to 'source3') diff --git a/source3/include/privileges.h b/source3/include/privileges.h index 85087f624f..76cabf3ba9 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -25,6 +25,15 @@ #ifndef PRIVILEGES_H #define PRIVILEGES_H +/* privilege bitmask */ + +#define SE_PRIV_MASKSIZE 4 + +typedef struct { + uint32 mask[SE_PRIV_MASKSIZE]; +} SE_PRIV; + + /* common privilege defines */ #define SE_END { { 0x00000000, 0x00000000, 0x00000000, 0x00000000 } } @@ -48,36 +57,14 @@ #define SE_DISK_OPERATOR { { 0x00000080, 0x00000000, 0x00000000, 0x00000000 } } #define SE_REMOTE_SHUTDOWN { { 0x00000100, 0x00000000, 0x00000000, 0x00000000 } } -#if 0 /* not needed currently */ - -#define SE_ASSIGN_PRIMARY_TOKEN -#define SE_CREATE_TOKEN -#define SE_LOCK_MEMORY -#define SE_INCREASE_QUOTA -#define SE_UNSOLICITED_INPUT -#define SE_TCB -#define SE_SECURITY -#define SE_TAKE_OWNERSHIP -#define SE_LOAD_DRIVER -#define SE_SYSTEM_PROFILE -#define SE_SYSTEM_TIME -#define SE_PROF_SINGLE_PROCESS -#define SE_INC_BASE_PRIORITY -#define SE_CREATE_PAGEFILE -#define SE_CREATE_PERMANENT -#define SE_BACKUP -#define SE_RESTORE -#define SE_SHUTDOWN -#define SE_DEBUG -#define SE_AUDIT -#define SE_SYSTEM_ENVIRONMENT -#define SE_CHANGE_NOTIFY -#define SE_REMOTE_SHUTDOWN -#define SE_UNDOCK -#define SE_SYNC_AGENT -#define SE_ENABLE_DELEGATION - -#endif /* not needed currently */ +/* defined in lib/privilegs.c */ + +extern const SE_PRIV se_machine_account; +extern const SE_PRIV se_print_operator; +extern const SE_PRIV se_add_users; +extern const SE_PRIV se_disk_operators; +extern const SE_PRIV se_remote_shutdown; + /* * These are used in Lsa replies (srv_lsa_nt.c) @@ -115,12 +102,6 @@ typedef struct privilege_set LUID_ATTR *set; } PRIVILEGE_SET; -#define SE_PRIV_MASKSIZE 4 - -typedef struct { - uint32 mask[SE_PRIV_MASKSIZE]; -} SE_PRIV; - typedef struct _PRIVS { SE_PRIV se_priv; const char *name; diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index df785f801e..628b2dd325 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -31,6 +31,15 @@ static SE_PRIV se_priv_all = SE_ALL_PRIVS; static SE_PRIV se_priv_end = SE_END; static SE_PRIV se_priv_none = SE_NONE; +/* Define variables for all privileges so we can use the + SE_PRIV* in the various se_priv_XXX() functions */ + +const SE_PRIV se_machine_account = SE_MACHINE_ACCOUNT; +const SE_PRIV se_print_operator = SE_PRINT_OPERATOR; +const SE_PRIV se_add_users = SE_ADD_USERS; +const SE_PRIV se_disk_operators = SE_DISK_OPERATOR; +const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN; + PRIVS privs[] = { #if 0 /* usrmgr will display these twice if you include them. We don't use them but we'll keep the bitmasks reserved in privileges.h anyways */ @@ -56,7 +65,6 @@ PRIVS privs[] = { {SE_LOCK_MEMORY, "SeLockMemoryPrivilege", "Lock Memory"}, {SE_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota"}, {SE_UNSOLICITED_INPUT, "SeUnsolicitedInputPrivilege", "Unsolicited Input"}, - {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Can add Machine Accounts to the Domain"}, {SE_TCB, "SeTcbPrivilege", "Act as part of the operating system"}, {SE_SECURITY, "SeSecurityPrivilege", "Security Privilege"}, {SE_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take Ownership Privilege"}, @@ -92,7 +100,7 @@ typedef struct priv_sid_list { copy an SE_PRIV structure ****************************************************************************/ -BOOL se_priv_copy( SE_PRIV *dst, SE_PRIV *src ) +BOOL se_priv_copy( SE_PRIV *dst, const SE_PRIV *src ) { if ( !dst || !src ) return False; @@ -106,7 +114,7 @@ BOOL se_priv_copy( SE_PRIV *dst, SE_PRIV *src ) combine 2 SE_PRIV structures and store the resulting set in mew_mask ****************************************************************************/ -static void se_priv_add( SE_PRIV *mask, SE_PRIV *addpriv ) +static void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv ) { int i; @@ -120,7 +128,7 @@ static void se_priv_add( SE_PRIV *mask, SE_PRIV *addpriv ) in mew_mask ****************************************************************************/ -static void se_priv_remove( SE_PRIV *mask, SE_PRIV *removepriv ) +static void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv ) { int i; @@ -133,7 +141,7 @@ static void se_priv_remove( SE_PRIV *mask, SE_PRIV *removepriv ) invert a given SE_PRIV and store the set in new_mask ****************************************************************************/ -static void se_priv_invert( SE_PRIV *new_mask, SE_PRIV *mask ) +static void se_priv_invert( SE_PRIV *new_mask, const SE_PRIV *mask ) { SE_PRIV allprivs; @@ -146,7 +154,7 @@ static void se_priv_invert( SE_PRIV *new_mask, SE_PRIV *mask ) check if 2 SE_PRIV structure are equal ****************************************************************************/ -static BOOL se_priv_equal( SE_PRIV *mask1, SE_PRIV *mask2 ) +static BOOL se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 ) { return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 ); } @@ -156,7 +164,7 @@ static BOOL se_priv_equal( SE_PRIV *mask1, SE_PRIV *mask2 ) dump an SE_PRIV structure to the log files ****************************************************************************/ -void dump_se_priv( int dbg_cl, int dbg_lvl, SE_PRIV *mask ) +void dump_se_priv( int dbg_cl, int dbg_lvl, const SE_PRIV *mask ) { int i; @@ -624,6 +632,9 @@ NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_l BOOL user_has_privileges(NT_USER_TOKEN *token, SE_PRIV *privilege) { + if ( !token ) + return False; + return is_privilege_assigned( &token->privileges, privilege ); } diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index bf2c0353c0..98c2475a65 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1218,7 +1218,7 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID *sid, - uint32 *count, char ***privs_name) + uint32 *count, char ***priv_names) { prs_struct qbuf, rbuf; LSA_Q_ENUM_ACCT_RIGHTS q; @@ -1226,6 +1226,7 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result; int i; fstring *privileges; + char **names; ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1260,15 +1261,17 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, privileges = TALLOC_ARRAY(mem_ctx, fstring, *count); - *privs_name = TALLOC_ARRAY(mem_ctx, char *, *count); + names = TALLOC_ARRAY(mem_ctx, char *, *count); for ( i=0; i<*count; i++ ) { /* ensure NULL termination ... what a hack */ pull_ucs2(NULL, privileges[i], r.rights.strings[i].string.buffer, sizeof(fstring), r.rights.strings[i].string.uni_str_len*2 , 0); /* now copy to the return array */ - *privs_name[i] = talloc_strdup( mem_ctx, privileges[i] ); + names[i] = talloc_strdup( mem_ctx, privileges[i] ); } + + *priv_names = names; done: diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 70c0de7da7..5fd5137cf1 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1,14 +1,14 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Marc Jacobsen 1999, - * Copyright (C) Jeremy Allison 2001-2002, - * Copyright (C) Jean François Micouleau 1998-2001, + * Copyright (C) Jeremy Allison 2001-2002, + * Copyright (C) Jean François Micouleau 1998-2001, * Copyright (C) Jim McDonough 2002, - * Copyright (C) Gerald (Jerry) Carter 2003 - 2004, + * Copyright (C) Gerald (Jerry) Carter 2003-2004, * * 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 @@ -2221,8 +2221,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA uint32 new_rid = 0; /* check this, when giving away 'add computer to domain' privs */ uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS; - BOOL can_add_machines = False; - SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; + BOOL can_add_account; + SE_PRIV se_rights; /* Get the domain SID stored in the domain policy */ if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted)) @@ -2246,14 +2246,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0); strlower_m(account); - - /* check to see if we are a domain admin */ - - can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); - - DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", - p->pipe_user_name, can_add_machines ? "" : " not")); - + pdb_init_sam(&sam_pass); become_root(); @@ -2266,13 +2259,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA } pdb_free_sam(&sam_pass); - - /* - * NB. VERY IMPORTANT ! This call must be done as the current pipe user, - * *NOT* surrounded by a become_root()/unbecome_root() call. This ensures - * that only people with write access to the smbpasswd file will be able - * to create a user. JRA. - */ /********************************************************************* * HEADS UP! If we have to create a new user account, we have to get @@ -2287,26 +2273,37 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA pw = Get_Pwnam(account); - /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ + /* + * we can't check both the ending $ and the acb_info. + * + * UserManager creates trust accounts (ending in $, + * normal that hidden accounts) with the acb_info equals to ACB_NORMAL. + * JFM, 11/29/2001 + */ + + if (account[strlen(account)-1] == '$') { + se_priv_copy( &se_rights, &se_machine_account ); + pstrcpy(add_script, lp_addmachine_script()); + } + else { + se_priv_copy( &se_rights, &se_add_users ); + pstrcpy(add_script, lp_adduser_script()); + } + + can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + DEBUG(5, ("_samr_create_user: %s can add this account : %s\n", + p->pipe_user_name, can_add_account ? "True":"False" )); + + /********** BEGIN Admin BLOCK **********/ - if ( can_add_machines ) + if ( can_add_account ) become_root(); - + if ( !pw ) { - /* - * we can't check both the ending $ and the acb_info. - * - * UserManager creates trust accounts (ending in $, - * normal that hidden accounts) with the acb_info equals to ACB_NORMAL. - * JFM, 11/29/2001 - */ - if (account[strlen(account)-1] == '$') - pstrcpy(add_script, lp_addmachine_script()); - else - pstrcpy(add_script, lp_adduser_script()); - if (*add_script) { int add_ret; + all_string_sub(add_script, "%u", account, sizeof(add_script)); add_ret = smbrun(add_script,NULL); DEBUG(3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); @@ -2323,28 +2320,32 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* implicit call to getpwnam() next. we have a valid SID coming out of this call */ - if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account, new_rid)) ) { - if ( can_add_machines ) - unbecome_root(); - return nt_status; + nt_status = pdb_init_sam_new(&sam_pass, account, new_rid); + + /* this code is order such that we have no unnecessary retuns + out of the admin block of code */ + + if ( NT_STATUS_IS_OK(nt_status) ) { + pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED); + + if ( !(ret = pdb_add_sam_account(sam_pass)) ) { + pdb_free_sam(&sam_pass); + DEBUG(0, ("could not add user/computer %s to passdb. Check permissions?\n", + account)); + nt_status = NT_STATUS_ACCESS_DENIED; + } } - pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED); - - ret = pdb_add_sam_account(sam_pass); - - if ( can_add_machines ) + if ( can_add_account ) unbecome_root(); - - /* ================ END SeMachineAccountPrivilege BLOCK ================ */ - if ( !ret ) { - pdb_free_sam(&sam_pass); - DEBUG(0, ("could not add user/computer %s to passdb. Check permissions?\n", - account)); - return NT_STATUS_ACCESS_DENIED; - } - + /********** END Admin BLOCK **********/ + + /* now check for failure */ + + if ( !NT_STATUS_IS_OK(nt_status) ) + return nt_status; + /* Get the user's SID */ sid_copy(&sid, pdb_get_user_sid(sam_pass)); @@ -3515,6 +3516,10 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD { DOM_SID alias_sid; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; + BOOL ret; + /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) @@ -3525,11 +3530,23 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD } DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid))); + + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - if (!pdb_add_aliasmem(&alias_sid, &q_u->sid.sid)) - return NT_STATUS_ACCESS_DENIED; - - return NT_STATUS_OK; + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + + ret = pdb_add_aliasmem(&alias_sid, &q_u->sid.sid); + + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED; } /********************************************************************* @@ -3540,6 +3557,9 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE { DOM_SID alias_sid; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; + BOOL ret; /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) @@ -3552,10 +3572,22 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", sid_string_static(&alias_sid))); - if (!pdb_del_aliasmem(&alias_sid, &q_u->sid.sid)) - return NT_STATUS_ACCESS_DENIED; + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ - return NT_STATUS_OK; + if ( can_add_accounts ) + become_root(); + + ret = pdb_del_aliasmem(&alias_sid, &q_u->sid.sid); + + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED; } /********************************************************************* @@ -3576,6 +3608,8 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD SAM_ACCOUNT *sam_user=NULL; BOOL check; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) @@ -3636,6 +3670,14 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD return NT_STATUS_MEMBER_IN_GROUP; } + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + /* * ok, the group exist, the user exist, the user is not in the group, * @@ -3644,6 +3686,11 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD smb_add_user_group(grp_name, pwd->pw_name); + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + /* check if the user has been added then ... */ if(!user_in_unix_group_list(pwd->pw_name, grp_name)) { passwd_free(&pwd); @@ -3667,6 +3714,8 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE fstring grp_name; struct group *grp; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; /* * delete the group member named q_u->rid @@ -3710,9 +3759,23 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE pdb_free_sam(&sam_pass); return NT_STATUS_MEMBER_NOT_IN_GROUP; } + + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + smb_delete_user_group(grp_name, pdb_get_username(sam_pass)); + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + /* check if the user has been removed then ... */ if (user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) { pdb_free_sam(&sam_pass); @@ -3764,6 +3827,9 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM DOM_SID user_sid; SAM_ACCOUNT *sam_pass=NULL; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; + BOOL ret; DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__)); @@ -3786,22 +3852,40 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM pdb_free_sam(&sam_pass); return NT_STATUS_NO_SUCH_USER; } + + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - /* First delete the samba side */ - if (!pdb_delete_sam_account(sam_pass)) { + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + + /* First delete the samba side.... + code is order to prevent unnecessary returns out of the admin + block of code */ + + if ( (ret = pdb_delete_sam_account(sam_pass)) == True ) { + /* + * Now delete the unix side .... + * note: we don't check if the delete really happened + * as the script is not necessary present + * and maybe the sysadmin doesn't want to delete the unix side + */ + smb_delete_user( pdb_get_username(sam_pass) ); + } + + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + if ( !ret ) { DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass))); pdb_free_sam(&sam_pass); return NT_STATUS_CANNOT_DELETE; } - /* Now delete the unix side */ - /* - * note: we don't check if the delete really happened - * as the script is not necessary present - * and maybe the sysadmin doesn't want to delete the unix side - */ - smb_delete_user(pdb_get_username(sam_pass)); - pdb_free_sam(&sam_pass); @@ -3825,6 +3909,9 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S struct group *grp; GROUP_MAP map; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; + BOOL ret; DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__)); @@ -3857,17 +3944,33 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S if ( (grp=getgrgid(gid)) == NULL) return NT_STATUS_NO_SUCH_GROUP; + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + /* delete mapping first */ - if(!pdb_delete_group_mapping_entry(group_sid)) - return NT_STATUS_ACCESS_DENIED; - - /* we can delete the UNIX group */ - smb_delete_group(grp->gr_name); + + if ( (ret = pdb_delete_group_mapping_entry(group_sid)) == True ) { + smb_delete_group( grp->gr_name ); + } - /* check if the group has been successfully deleted */ - if ( (grp=getgrgid(gid)) != NULL) + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + if ( !ret ) { + DEBUG(5,("_samr_delete_dom_group: Failed to delete mapping entry for group %s.\n", + group_sid_str)); return NT_STATUS_ACCESS_DENIED; - + } + + /* don't check that the unix group has been deleted. Work like + _samr_delet_dom_user() */ if (!close_policy_hnd(p, &q_u->group_pol)) return NT_STATUS_OBJECT_NAME_INVALID; @@ -3883,6 +3986,9 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S { DOM_SID alias_sid; uint32 acc_granted; + SE_PRIV se_rights; + BOOL can_add_accounts; + BOOL ret; DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__)); @@ -3901,8 +4007,23 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S DEBUG(10, ("lookup on Local SID\n")); + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + /* Have passdb delete the alias */ - if (!pdb_delete_alias(&alias_sid)) + ret = pdb_delete_alias(&alias_sid); + + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + if ( !ret ) return NT_STATUS_ACCESS_DENIED; if (!close_policy_hnd(p, &q_u->alias_pol)) @@ -3925,6 +4046,9 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S struct samr_info *info; uint32 acc_granted; gid_t gid; + SE_PRIV se_rights; + BOOL can_add_accounts; + NTSTATUS result; /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted)) @@ -3937,32 +4061,53 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; - /* TODO: check if allowed to create group and add a become_root/unbecome_root pair.*/ - unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1); /* check if group already exist */ if ((grp=getgrnam(name)) != NULL) return NT_STATUS_GROUP_EXISTS; - /* we can create the UNIX group */ - if (smb_create_group(name, &gid) != 0) - return NT_STATUS_ACCESS_DENIED; - - /* check if the group has been successfully created */ - if ((grp=getgrgid(gid)) == NULL) - return NT_STATUS_ACCESS_DENIED; + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - r_u->rid=pdb_gid_to_group_rid(grp->gr_gid); - - /* add the group to the mapping table */ - sid_copy(&info_sid, get_global_sam_sid()); - sid_append_rid(&info_sid, r_u->rid); - sid_to_string(sid_string, &info_sid); + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + + /* check that we successfully create the UNIX group */ + + result = NT_STATUS_ACCESS_DENIED; + if ( (smb_create_group(name, &gid) == 0) && ((grp=getgrgid(gid)) != NULL) ) { + + /* so far, so good */ + + result = NT_STATUS_OK; + + r_u->rid = pdb_gid_to_group_rid( grp->gr_gid ); - if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL)) - return NT_STATUS_ACCESS_DENIED; + /* add the group to the mapping table */ + + sid_copy( &info_sid, get_global_sam_sid() ); + sid_append_rid( &info_sid, r_u->rid ); + sid_to_string( sid_string, &info_sid ); + + /* reset the error code if we fail to add the mapping entry */ + + if ( !add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL) ) + result = NT_STATUS_ACCESS_DENIED; + } + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + + /* check if we should bail out here */ + + if ( !NT_STATUS_IS_OK(result) ) + return result; + if ((info = get_samr_info_by_sid(&info_sid)) == NULL) return NT_STATUS_NO_MEMORY; @@ -3987,6 +4132,8 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S uint32 acc_granted; gid_t gid; NTSTATUS result; + SE_PRIV se_rights; + BOOL can_add_accounts; /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted)) @@ -3999,13 +4146,24 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S if (!sid_equal(&dom_sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; - /* TODO: check if allowed to create group and add a become_root/unbecome_root pair.*/ - unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1); + se_priv_copy( &se_rights, &se_add_users ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + + /******** BEGIN SeAddUsers BLOCK *********/ + + if ( can_add_accounts ) + become_root(); + /* Have passdb create the alias */ result = pdb_create_alias(name, &r_u->rid); + if ( can_add_accounts ) + unbecome_root(); + + /******** END SeAddUsers BLOCK *********/ + if (!NT_STATUS_IS_OK(result)) return result; diff --git a/source3/utils/net_rpc_rights.c b/source3/utils/net_rpc_rights.c index d5652b8247..feb50b457a 100644 --- a/source3/utils/net_rpc_rights.c +++ b/source3/utils/net_rpc_rights.c @@ -23,6 +23,37 @@ /******************************************************************** ********************************************************************/ +static NTSTATUS sid_to_name(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + DOM_SID *sid, fstring name) +{ + POLICY_HND pol; + uint32 *sid_types; + NTSTATUS result; + char **domains, **names; + + result = cli_lsa_open_policy(cli, mem_ctx, True, + SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); + + if ( !NT_STATUS_IS_OK(result) ) + return result; + + result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types); + + if ( NT_STATUS_IS_OK(result) ) { + if ( *domains[0] ) + fstr_sprintf( name, "%s\\%s", domains[0], names[0] ); + else + fstrcpy( name, names[0] ); + } + + cli_lsa_close(cli, mem_ctx, &pol); + return result; +} + +/******************************************************************** +********************************************************************/ + static NTSTATUS name_to_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_SID *sid, const char *name) @@ -41,20 +72,14 @@ static NTSTATUS name_to_sid(struct cli_state *cli, result = cli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); - if (!NT_STATUS_IS_OK(result)) + if ( !NT_STATUS_IS_OK(result) ) return result; result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types); - if (!NT_STATUS_IS_OK(result)) { - d_printf("Failed to convert \"%s\" to a SID [%s]\n", - name, nt_errstr(result)); - goto done; - } + if ( NT_STATUS_IS_OK(result) ) + sid_copy( sid, &sids[0] ); - sid_copy( sid, &sids[0] ); - -done: cli_lsa_close(cli, mem_ctx, &pol); return result; } @@ -143,6 +168,7 @@ static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state DOM_SID *sids; uint32 count=0; int i; + fstring name; result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, pref_max_length, &count, &sids); @@ -151,8 +177,16 @@ static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state return result; for ( i=0; i