summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/rpc_secdes.h5
-rw-r--r--source3/lib/privileges.c78
-rw-r--r--source3/passdb/pdb_get_set.c2
-rw-r--r--source3/rpc_server/srv_samr_nt.c743
4 files changed, 486 insertions, 342 deletions
diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h
index 56145ac024..1279007220 100644
--- a/source3/include/rpc_secdes.h
+++ b/source3/include/rpc_secdes.h
@@ -401,7 +401,10 @@ typedef struct standard_mapping {
#define GENERIC_RIGHTS_USER_WRITE \
(STANDARD_RIGHTS_WRITE_ACCESS | \
SA_RIGHT_USER_CHANGE_PASSWORD | \
- SA_RIGHT_USER_SET_LOC_COM) /* 0x00020044 */
+ SA_RIGHT_USER_SET_LOC_COM | \
+ SA_RIGHT_USER_SET_ATTRIBUTES | \
+ SA_RIGHT_USER_SET_PASSWORD | \
+ SA_RIGHT_USER_CHANGE_GROUP_MEM) /* 0x000204e4 */
#define GENERIC_RIGHTS_USER_EXECUTE \
(STANDARD_RIGHTS_EXECUTE_ACCESS | \
diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c
index ea81f9fce0..4feb730fee 100644
--- a/source3/lib/privileges.c
+++ b/source3/lib/privileges.c
@@ -114,7 +114,7 @@ BOOL se_priv_copy( SE_PRIV *dst, const SE_PRIV *src )
combine 2 SE_PRIV structures and store the resulting set in mew_mask
****************************************************************************/
-static void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv )
+void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv )
{
int i;
@@ -128,7 +128,7 @@ static void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv )
in mew_mask
****************************************************************************/
-static void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv )
+void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv )
{
int i;
@@ -159,6 +159,23 @@ static BOOL se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 )
return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 );
}
+/***************************************************************************
+ check if a SE_PRIV has any assigned privileges
+****************************************************************************/
+
+static BOOL se_priv_empty( const SE_PRIV *mask )
+{
+ SE_PRIV p1;
+ int i;
+
+ se_priv_copy( &p1, mask );
+
+ for ( i=0; i<SE_PRIV_MASKSIZE; i++ ) {
+ p1.mask[i] &= se_priv_all.mask[i];
+ }
+
+ return se_priv_equal( &p1, &se_priv_none );
+}
/***************************************************************************
dump an SE_PRIV structure to the log files
@@ -252,13 +269,20 @@ static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask )
check if the privilege is in the privilege list
****************************************************************************/
-static BOOL is_privilege_assigned( SE_PRIV *privileges, SE_PRIV *check )
+static BOOL is_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
{
SE_PRIV p1, p2;
if ( !privileges || !check )
return False;
+ /* everyone has privileges if you aren't checking for any */
+
+ if ( se_priv_empty( check ) ) {
+ DEBUG(1,("is_privilege_assigned: no privileges in check_mask!\n"));
+ return True;
+ }
+
se_priv_copy( &p1, check );
/* invert the SE_PRIV we want to check for and remove that from the
@@ -273,6 +297,39 @@ static BOOL is_privilege_assigned( SE_PRIV *privileges, SE_PRIV *check )
}
/****************************************************************************
+ check if the privilege is in the privilege list
+****************************************************************************/
+
+static BOOL is_any_privilege_assigned( SE_PRIV *privileges, const SE_PRIV *check )
+{
+ SE_PRIV p1, p2;
+
+ if ( !privileges || !check )
+ return False;
+
+ /* everyone has privileges if you aren't checking for any */
+
+ if ( se_priv_empty( check ) ) {
+ DEBUG(1,("is_any_privilege_assigned: no privileges in check_mask!\n"));
+ return True;
+ }
+
+ se_priv_copy( &p1, check );
+
+ /* invert the SE_PRIV we want to check for and remove that from the
+ original set. If we are left with the SE_PRIV we are checking
+ for then return True */
+
+ se_priv_invert( &p1, check );
+ se_priv_copy( &p2, privileges );
+ se_priv_remove( &p2, &p1 );
+
+ /* see if we have any bits left */
+
+ return !se_priv_empty( &p2 );
+}
+
+/****************************************************************************
add a privilege to a privilege array
****************************************************************************/
@@ -633,7 +690,7 @@ NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_l
at a time here.
*****************************************************************************/
-BOOL user_has_privileges(NT_USER_TOKEN *token, SE_PRIV *privilege)
+BOOL user_has_privileges(NT_USER_TOKEN *token, const SE_PRIV *privilege)
{
if ( !token )
return False;
@@ -642,6 +699,19 @@ BOOL user_has_privileges(NT_USER_TOKEN *token, SE_PRIV *privilege)
}
/****************************************************************************
+ Does the user have any of the specified privileges ? We only deal with one privilege
+ at a time here.
+*****************************************************************************/
+
+BOOL user_has_any_privilege(NT_USER_TOKEN *token, const SE_PRIV *privilege)
+{
+ if ( !token )
+ return False;
+
+ return is_any_privilege_assigned( &token->privileges, privilege );
+}
+
+/****************************************************************************
Convert a LUID to a named string
****************************************************************************/
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 3430969e71..e0fc0ef280 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -514,7 +514,7 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p
DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
return False;
}
- DEBUG(10, ("element %d -> now SET\n", element));
+ DEBUG(11, ("element %d -> now SET\n", element));
break;
case PDB_DEFAULT:
default:
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 122bde1be5..6815c7147c 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -68,31 +68,240 @@ struct generic_mapping usr_generic_mapping = {GENERIC_RIGHTS_USER_READ, GENERIC_
struct generic_mapping grp_generic_mapping = {GENERIC_RIGHTS_GROUP_READ, GENERIC_RIGHTS_GROUP_WRITE, GENERIC_RIGHTS_GROUP_EXECUTE, GENERIC_RIGHTS_GROUP_ALL_ACCESS};
struct generic_mapping ali_generic_mapping = {GENERIC_RIGHTS_ALIAS_READ, GENERIC_RIGHTS_ALIAS_WRITE, GENERIC_RIGHTS_ALIAS_EXECUTE, GENERIC_RIGHTS_ALIAS_ALL_ACCESS};
-static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size);
+/*******************************************************************
+ samr_make_dom_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid, act_sid, domadmin_sid;
+ SEC_ACE ace[4];
+ SEC_ACCESS mask;
+ size_t i = 0;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_EXECUTE | GENERIC_RIGHTS_DOMAIN_READ);
+ init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+
+ init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS);
+
+ init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /* add domain admins if we are a DC */
+
+ if ( IS_DC ) {
+ sid_copy( &domadmin_sid, get_global_sam_sid() );
+ sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
+ init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ }
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ samr_make_usr_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size, DOM_SID *usr_sid)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid, act_sid, domadmin_sid;
+ size_t i = 0;
+
+ SEC_ACE ace[5];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+
+ init_sec_access(&mask, GENERIC_RIGHTS_USER_EXECUTE | GENERIC_RIGHTS_USER_READ);
+ init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+
+ init_sec_access(&mask, GENERIC_RIGHTS_USER_ALL_ACCESS);
+ init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /* add domain admins if we are a DC */
+
+ if ( IS_DC ) {
+ sid_copy( &domadmin_sid, get_global_sam_sid() );
+ sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
+ init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ }
+
+ /*extended access for the user*/
+
+ init_sec_access(&mask,READ_CONTROL_ACCESS | SA_RIGHT_USER_CHANGE_PASSWORD | SA_RIGHT_USER_SET_LOC_COM);
+ init_sec_ace(&ace[i++], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ samr_make_grp_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, GENERIC_RIGHTS_GROUP_EXECUTE | GENERIC_RIGHTS_GROUP_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, GENERIC_RIGHTS_GROUP_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ samr_make_ali_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_EXECUTE | GENERIC_RIGHTS_ALIAS_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
/*******************************************************************
Checks if access to an object should be granted, and returns that
level of access for further checks.
********************************************************************/
-static NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_token, uint32 des_access,
- uint32 *acc_granted, const char *debug)
+static NTSTATUS access_check_samr_object( SEC_DESC *psd, NT_USER_TOKEN *token,
+ SE_PRIV *rights, uint32 rights_mask,
+ uint32 des_access, uint32 *acc_granted,
+ const char *debug )
{
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
+ uint32 saved_mask = 0;
- if (!se_access_check(psd, nt_user_token, des_access, acc_granted, &status)) {
+ /* check privileges; certain SAM access bits should be overridden
+ by privileges (mostly having to do with creating/modifying/deleting
+ users and groups) */
+
+ if ( rights && user_has_any_privilege( token, rights ) ) {
+
+ saved_mask = (des_access & rights_mask);
+ des_access &= ~saved_mask;
+
+ DEBUG(4,("access_check_samr_object: user rights saved access mask [0x%x]\n",
+ saved_mask));
+ }
+
+
+ /* check the security descriptor first */
+
+ if ( se_access_check(psd, token, des_access, acc_granted, &status) )
+ goto done;
+
+ /* give root a free pass */
+
+ if ( geteuid() == sec_initial_uid() ) {
+
+ DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n", debug, des_access));
+ DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n"));
+
*acc_granted = des_access;
- if (geteuid() == sec_initial_uid()) {
- DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n",
- debug, des_access));
- DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n"));
- status = NT_STATUS_OK;
- }
- else {
- DEBUG(2,("%s: ACCESS DENIED (requested: %#010x)\n",
- debug, des_access));
- }
+
+ status = NT_STATUS_OK;
+ goto done;
}
+
+
+ DEBUG(2,("%s: ACCESS DENIED (requested: %#010x)\n", debug, des_access));
+
+done:
+ /* add in any bits saved during the privilege check (only
+ matters is syayus is ok) */
+
+ *acc_granted |= saved_mask;
+
return status;
}
@@ -102,20 +311,29 @@ static NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_t
static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_required, const char *debug)
{
- DEBUG(5,("%s: access check ((granted: %#010x; required: %#010x)\n",
- debug, acc_granted, acc_required));
- if ((acc_granted & acc_required) != acc_required) {
- if (geteuid() == sec_initial_uid()) {
- DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
- debug, acc_granted, acc_required));
- DEBUGADD(4,("but overwritten by euid == 0\n"));
- return NT_STATUS_OK;
- }
- DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n",
+ DEBUG(5,("%s: access check ((granted: %#010x; required: %#010x)\n",
+ debug, acc_granted, acc_required));
+
+ /* check the security descriptor first */
+
+ if ( (acc_granted&acc_required) == acc_required )
+ return NT_STATUS_OK;
+
+ /* give root a free pass */
+
+ if (geteuid() == sec_initial_uid()) {
+
+ DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
debug, acc_granted, acc_required));
- return NT_STATUS_ACCESS_DENIED;
+ DEBUGADD(4,("but overwritten by euid == 0\n"));
+
+ return NT_STATUS_OK;
}
- return NT_STATUS_OK;
+
+ DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n",
+ debug, acc_granted, acc_required));
+
+ return NT_STATUS_ACCESS_DENIED;
}
@@ -385,26 +603,35 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN
uint32 des_access = q_u->flags;
size_t sd_size;
NTSTATUS status;
+ SE_PRIV se_rights;
r_u->status = NT_STATUS_OK;
/* find the connection policy handle. */
- if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
+
+ if ( !find_policy_by_hnd(p, &q_u->pol, (void**)&info) )
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(status = access_check_samr_function(info->acc_granted, SA_RIGHT_SAM_OPEN_DOMAIN,"_samr_open_domain"))) {
+ status = access_check_samr_function( info->acc_granted,
+ SA_RIGHT_SAM_OPEN_DOMAIN, "_samr_open_domain" );
+
+ if ( !NT_STATUS_IS_OK(status) )
return status;
- }
/*check if access can be granted as requested by client. */
- samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
- se_map_generic(&des_access,&dom_generic_mapping);
+
+ samr_make_dom_obj_sd( p->mem_ctx, &psd, &sd_size );
+ se_map_generic( &des_access, &dom_generic_mapping );
+
+ se_priv_copy( &se_rights, &se_machine_account );
+ se_priv_add( &se_rights, &se_add_users );
- if (!NT_STATUS_IS_OK(status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_open_domain"))) {
+ status = access_check_samr_object( psd, p->pipe_user.nt_user_token,
+ &se_rights, GENERIC_RIGHTS_DOMAIN_WRITE, des_access,
+ &acc_granted, "_samr_open_domain" );
+
+ if ( !NT_STATUS_IS_OK(status) )
return status;
- }
/* associate the domain SID with the (unique) handle. */
if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL)
@@ -449,187 +676,23 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
return r_u->status;
}
-/*******************************************************************
- samr_make_dom_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid, act_sid, domadmin_sid;
- SEC_ACE ace[4];
- SEC_ACCESS mask;
- size_t i = 0;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_EXECUTE | GENERIC_RIGHTS_DOMAIN_READ);
- init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
-
- init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS);
-
- init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /* add domain admins if we are a DC */
-
- if ( IS_DC ) {
- sid_copy( &domadmin_sid, get_global_sam_sid() );
- sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
- init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- }
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
/*******************************************************************
- samr_make_usr_obj_sd
+ _samr_set_sec_obj
********************************************************************/
-static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size, DOM_SID *usr_sid)
+NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u)
{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid, act_sid, domadmin_sid;
- size_t i = 0;
-
- SEC_ACE ace[5];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
-
- init_sec_access(&mask, GENERIC_RIGHTS_USER_EXECUTE | GENERIC_RIGHTS_USER_READ);
- init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
-
- init_sec_access(&mask, GENERIC_RIGHTS_USER_ALL_ACCESS);
- init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /* add domain admins if we are a DC */
-
- if ( IS_DC ) {
- sid_copy( &domadmin_sid, get_global_sam_sid() );
- sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
- init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- }
-
- /*extended access for the user*/
-
- init_sec_access(&mask,READ_CONTROL_ACCESS | SA_RIGHT_USER_CHANGE_PASSWORD | SA_RIGHT_USER_SET_LOC_COM);
- init_sec_ace(&ace[i++], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
+ DEBUG(0,("_samr_set_sec_obj: Not yet implemented!\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
}
-/*******************************************************************
- samr_make_grp_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid;
- DOM_SID act_sid;
-
- SEC_ACE ace[3];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_GROUP_EXECUTE | GENERIC_RIGHTS_GROUP_READ);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
- init_sec_access(&mask, GENERIC_RIGHTS_GROUP_ALL_ACCESS);
- init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
/*******************************************************************
- samr_make_ali_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid;
- DOM_SID act_sid;
-
- SEC_ACE ace[3];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_EXECUTE | GENERIC_RIGHTS_ALIAS_READ);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
- init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_ALL_ACCESS);
- init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
+********************************************************************/
-static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted)
+static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol,
+ DOM_SID *sid, uint32 *acc_granted)
{
struct samr_info *info = NULL;
@@ -646,17 +709,6 @@ static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *s
}
/*******************************************************************
- _samr_set_sec_obj
- ********************************************************************/
-
-NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u)
-{
- DEBUG(0,("_samr_set_sec_obj: Not yet implemented!\n"));
- return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
-/*******************************************************************
_samr_query_sec_obj
********************************************************************/
@@ -1646,34 +1698,45 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
size_t sd_size;
BOOL ret;
NTSTATUS nt_status;
+ SE_PRIV se_rights;
r_u->status = NT_STATUS_OK;
/* find the domain policy handle and get domain SID / access bits in the domain policy. */
- if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted))
+
+ if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted) )
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_user"))) {
+ nt_status = access_check_samr_function( acc_granted,
+ SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_user" );
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
return nt_status;
- }
nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass);
- if (!NT_STATUS_IS_OK(nt_status)) {
+
+ if (!NT_STATUS_IS_OK(nt_status))
return nt_status;
- }
/* append the user's RID to it */
+
if (!sid_append_rid(&sid, q_u->user_rid))
return NT_STATUS_NO_SUCH_USER;
/* check if access can be granted as requested by client. */
+
samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid);
se_map_generic(&des_access, &usr_generic_mapping);
- if (!NT_STATUS_IS_OK(nt_status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_open_user"))) {
+
+ se_priv_copy( &se_rights, &se_machine_account );
+ se_priv_add( &se_rights, &se_add_users );
+
+ nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access,
+ &acc_granted, "_samr_open_user");
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
return nt_status;
- }
become_root();
ret=pdb_getsampwsid(sampass, &sid);
@@ -2396,7 +2459,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
se_map_generic(&des_access, &usr_generic_mapping);
nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_create_user");
+ &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access,
+ &acc_granted, "_samr_create_user");
if ( !NT_STATUS_IS_OK(nt_status) ) {
return nt_status;
@@ -2494,11 +2558,12 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
se_map_generic(&des_access, &sam_generic_mapping);
- if (!NT_STATUS_IS_OK(nt_status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_connect"))) {
+
+ nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ NULL, 0, des_access, &acc_granted, "_samr_connect");
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
return nt_status;
- }
r_u->status = NT_STATUS_OK;
@@ -2544,11 +2609,12 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *
samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
se_map_generic(&des_access, &sam_generic_mapping);
- if (!NT_STATUS_IS_OK(nt_status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_connect"))) {
+
+ nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ NULL, 0, des_access, &acc_granted, "_samr_connect4");
+
+ if ( !NT_STATUS_IS_OK(nt_status) )
return nt_status;
- }
r_u->status = NT_STATUS_OK;
@@ -2693,29 +2759,40 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
uint32 des_access = q_u->access_mask;
size_t sd_size;
NTSTATUS status;
+ SE_PRIV se_rights;
r_u->status = NT_STATUS_OK;
/* find the domain policy and get the SID / access bits stored in the domain policy */
- if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted))
+
+ if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted) )
return NT_STATUS_INVALID_HANDLE;
+
+ status = access_check_samr_function(acc_granted,
+ SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_alias");
- if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_alias"))) {
+ if ( !NT_STATUS_IS_OK(status) )
return status;
- }
/* append the alias' RID to it */
+
if (!sid_append_rid(&sid, alias_rid))
return NT_STATUS_NO_SUCH_USER;
/*check if access can be granted as requested by client. */
+
samr_make_ali_obj_sd(p->mem_ctx, &psd, &sd_size);
se_map_generic(&des_access,&ali_generic_mapping);
- if (!NT_STATUS_IS_OK(status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_open_alias"))) {
+
+ se_priv_add( &se_rights, &se_add_users );
+
+
+ status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ &se_rights, GENERIC_RIGHTS_ALIAS_WRITE, des_access,
+ &acc_granted, "_samr_open_alias");
+
+ if ( !NT_STATUS_IS_OK(status) )
return status;
- }
/*
* we should check if the rid really exist !!!
@@ -2739,20 +2816,8 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
set_user_info_10
********************************************************************/
-static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid)
+static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd =NULL;
- BOOL ret;
-
- pdb_init_sam(&pwd);
-
- ret = pdb_getsampwsid(pwd, sid);
-
- if(ret==False) {
- pdb_free_sam(&pwd);
- return False;
- }
-
if (id10 == NULL) {
DEBUG(5, ("set_user_info_10: NULL id10\n"));
pdb_free_sam(&pwd);
@@ -2779,16 +2844,8 @@ static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid)
set_user_info_12
********************************************************************/
-static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid)
+static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd = NULL;
-
- pdb_init_sam(&pwd);
-
- if(!pdb_getsampwsid(pwd, sid)) {
- pdb_free_sam(&pwd);
- return False;
- }
if (id12 == NULL) {
DEBUG(2, ("set_user_info_12: id12 is NULL\n"));
@@ -2858,22 +2915,13 @@ static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass)
set_user_info_20
********************************************************************/
-static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, DOM_SID *sid)
+static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd = NULL;
-
if (id20 == NULL) {
DEBUG(5, ("set_user_info_20: NULL id20\n"));
return False;
}
- pdb_init_sam(&pwd);
-
- if (!pdb_getsampwsid(pwd, sid)) {
- pdb_free_sam(&pwd);
- return False;
- }
-
copy_id20_to_sam_passwd(pwd, id20);
/* write the change out */
@@ -2890,22 +2938,14 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, DOM_SID *sid)
set_user_info_21
********************************************************************/
-static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid)
+static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd = NULL;
if (id21 == NULL) {
DEBUG(5, ("set_user_info_21: NULL id21\n"));
return False;
}
- pdb_init_sam(&pwd);
-
- if (!pdb_getsampwsid(pwd, sid)) {
- pdb_free_sam(&pwd);
- return False;
- }
-
copy_id21_to_sam_passwd(pwd, id21);
/*
@@ -2933,9 +2973,8 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid)
set_user_info_23
********************************************************************/
-static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
+static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd = NULL;
pstring plaintext_buf;
uint32 len;
uint16 acct_ctrl;
@@ -2945,13 +2984,6 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
return False;
}
- pdb_init_sam(&pwd);
-
- if (!pdb_getsampwsid(pwd, sid)) {
- pdb_free_sam(&pwd);
- return False;
- }
-
DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n",
pdb_get_username(pwd)));
@@ -3008,20 +3040,12 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
set_user_info_pw
********************************************************************/
-static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
+static BOOL set_user_info_pw(char *pass, SAM_ACCOUNT *pwd)
{
- SAM_ACCOUNT *pwd = NULL;
uint32 len;
pstring plaintext_buf;
uint16 acct_ctrl;
- pdb_init_sam(&pwd);
-
- if (!pdb_getsampwsid(pwd, sid)) {
- pdb_free_sam(&pwd);
- return False;
- }
-
DEBUG(5, ("Attempting administrator password change for user %s\n",
pdb_get_username(pwd)));
@@ -3080,14 +3104,16 @@ static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u)
{
+ SAM_ACCOUNT *pwd = NULL;
DOM_SID sid;
POLICY_HND *pol = &q_u->pol;
uint16 switch_value = q_u->switch_value;
SAM_USERINFO_CTR *ctr = q_u->ctr;
uint32 acc_granted;
uint32 acc_required;
- BOOL can_add_machines;
- SE_PRIV se_machineop = SE_MACHINE_ACCOUNT;
+ BOOL ret;
+ BOOL has_enough_rights;
+ SE_PRIV se_rights;
DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
@@ -3118,24 +3144,42 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
DEBUG(5, ("_samr_set_userinfo: NULL info level\n"));
return NT_STATUS_INVALID_INFO_CLASS;
}
+
+ pdb_init_sam(&pwd);
+
+ become_root();
+ ret = pdb_getsampwsid(pwd, &sid);
+ unbecome_root();
+
+ if ( !ret ) {
+ pdb_free_sam(&pwd);
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ /* deal with machine password changes differently from userinfo changes */
+
+ if ( pdb_get_acct_ctrl(pwd) & ACB_WSTRUST )
+ se_priv_copy( &se_rights, &se_machine_account );
+ else
+ se_priv_copy( &se_rights, &se_add_users );
- /* check to see if we are a domain admin */
+ /* check to see if we have the sufficient rights */
- can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop );
+ has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
- DEBUG(5, ("_samr_set_userinfo: %s is%s a member of the Domain Admins group\n",
- p->pipe_user_name, can_add_machines ? "" : " not"));
+ DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
+ p->pipe_user_name, has_enough_rights ? "" : " not"));
/* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
- if ( can_add_machines )
- become_root();
-
+ if ( has_enough_rights )
+ become_root();
+
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch (switch_value) {
- case 0x12:
- if (!set_user_info_12(ctr->info.id12, &sid))
+ case 18:
+ if (!set_user_info_12(ctr->info.id12, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
@@ -3147,7 +3191,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id24->pass, 516);
- if (!set_user_info_pw((char *)ctr->info.id24->pass, &sid))
+ if (!set_user_info_pw((char *)ctr->info.id24->pass, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
@@ -3183,7 +3227,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id23->pass, 516);
- if (!set_user_info_23(ctr->info.id23, &sid))
+ if (!set_user_info_23(ctr->info.id23, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
@@ -3192,7 +3236,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
}
- if ( can_add_machines )
+ if ( has_enough_rights )
unbecome_root();
/* ================ END SeMachineAccountPrivilege BLOCK ================ */
@@ -3206,14 +3250,16 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_SET_USERINFO2 *r_u)
{
+ SAM_ACCOUNT *pwd = NULL;
DOM_SID sid;
SAM_USERINFO_CTR *ctr = q_u->ctr;
POLICY_HND *pol = &q_u->pol;
uint16 switch_value = q_u->switch_value;
uint32 acc_granted;
uint32 acc_required;
- BOOL can_add_machines;
- SE_PRIV se_machineop = SE_MACHINE_ACCOUNT;
+ BOOL ret;
+ BOOL has_enough_rights;
+ SE_PRIV se_rights;
DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
@@ -3237,43 +3283,61 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
switch_value=ctr->switch_value;
- /* check to see if we are a domain admin */
+ pdb_init_sam(&pwd);
- can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop );
+ become_root();
+ ret = pdb_getsampwsid(pwd, &sid);
+ unbecome_root();
- DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n",
- p->pipe_user_name, can_add_machines ? "" : " not"));
+ if ( !ret ) {
+ pdb_free_sam(&pwd);
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ /* deal with machine password changes differently from userinfo changes */
+
+ if ( pdb_get_acct_ctrl(pwd) & ACB_WSTRUST )
+ se_priv_copy( &se_rights, &se_machine_account );
+ else
+ se_priv_copy( &se_rights, &se_add_users );
+
+ /* check to see if we have the sufficient rights */
+
+ has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+
+ DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
+ p->pipe_user_name, has_enough_rights ? "" : " not"));
/* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */
- if ( can_add_machines )
- become_root();
-
+ if ( has_enough_rights )
+ become_root();
+
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch (switch_value) {
case 21:
- if (!set_user_info_21(ctr->info.id21, &sid))
+ if (!set_user_info_21(ctr->info.id21, pwd))
return NT_STATUS_ACCESS_DENIED;
break;
case 20:
- if (!set_user_info_20(ctr->info.id20, &sid))
+ if (!set_user_info_20(ctr->info.id20, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
case 16:
- if (!set_user_info_10(ctr->info.id10, &sid))
+ if (!set_user_info_10(ctr->info.id10, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
case 18:
/* Used by AS/U JRA. */
- if (!set_user_info_12(ctr->info.id12, &sid))
+ if (!set_user_info_12(ctr->info.id12, pwd))
r_u->status = NT_STATUS_ACCESS_DENIED;
break;
default:
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
}
- if ( can_add_machines )
+ if ( has_enough_rights )
unbecome_root();
/* ================ END SeMachineAccountPrivilege BLOCK ================ */
@@ -4413,25 +4477,32 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
NTSTATUS status;
fstring sid_string;
BOOL ret;
+ SE_PRIV se_rights;
if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
- if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_group"))) {
+ status = access_check_samr_function(acc_granted,
+ SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_group");
+
+ if ( !NT_STATUS_IS_OK(status) )
return status;
- }
/*check if access can be granted as requested by client. */
samr_make_grp_obj_sd(p->mem_ctx, &psd, &sd_size);
se_map_generic(&des_access,&grp_generic_mapping);
- if (!NT_STATUS_IS_OK(status =
- access_check_samr_object(psd, p->pipe_user.nt_user_token,
- des_access, &acc_granted, "_samr_open_group"))) {
- return status;
- }
+ se_priv_copy( &se_rights, &se_add_users );
+
+ status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ &se_rights, GENERIC_RIGHTS_GROUP_WRITE, des_access,
+ &acc_granted, "_samr_open_group");
+
+ if ( !NT_STATUS_IS_OK(status) )
+ return status;
/* this should not be hard-coded like this */
+
if (!sid_equal(&sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;