Access control to SAM / _samr_query_sec_obj

Kai Krueger kai at kruegernetz.de
Wed Jun 5 10:55:02 GMT 2002


This is the first version of the patch to implement access control to SAM.

It implements checks of the desired access in all open functions (those that create handles)
against the appropriate default SDs of the previous patch and associates the granted access bits
with the handle. These granted access bits are then used in the other functions to check if the
current handle (user) is allowed to run the function. 

However, I'm not sure if the nt_user_token works correctly, especially if root by default
belongs to the administrators alias. So to stop the patch braking write access to the sam,
I've commented out all return nt_status_access_denied. I haven't had the possibility to test
the nt_user_token, as the attempts to join my win2k workstation to the samba PDC
always fails :(
In effect the patch therefore currently doesn't do much except logging but can be used for
testing. If it works, the changes are then minimal.

But the patch should at least be enough to see if it is conceptionally acceptable, so any
comments or improvements are welcome.

Kai



--- ./samba-orig/source/rpc_server/srv_samr_nt.c Fri May 31 19:51:43 2002
+++ ./samba/source/rpc_server/srv_samr_nt.c Wed Jun  5 10:12:39 2002
@@ -52,9 +52,47 @@
  /* for use by the \PIPE\samr policy */
  DOM_SID sid;
  uint32 status; /* some sort of flag.  best to record it.  comes from opnum 0x39 */
+ uint32 acc_granted;
  DISP_INFO disp_info;
 };
 
+struct generic_mapping sam_generic_mapping = {
+ 0x20010,
+ 0x2000e,
+ 0x20021,
+ 0xf003f
+};
+
+struct generic_mapping dom_generic_mapping = {
+ 0x20084,
+ 0x2047a,
+ 0x20301,
+ 0xf07ff
+};
+
+struct generic_mapping usr_generic_mapping = {
+ 0x2031a,
+ 0x20044,
+ 0x20041,
+ 0xf07ff
+};
+
+struct generic_mapping grp_generic_mapping = {
+ 0x20010,
+ 0x2000e,
+ 0x20001,
+ 0xf001f
+};
+
+struct generic_mapping ali_generic_mapping = {
+ 0x20004,
+ 0x20013,
+ 0x20008,
+ 0xf001f
+};
+
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size);
+
 /*******************************************************************
  Create a samr_info struct.
 ********************************************************************/
@@ -352,17 +390,45 @@
 
 NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u)
 {
- struct samr_info *info;
+ struct    samr_info *info;
+ SEC_DESC *psd = NULL;
+ uint32    acc_granted;
+ uint32    acc_required;
+ uint32    des_access = q_u->flags;
+ size_t    sd_size;
+ NTSTATUS  status;
 
  r_u->status = NT_STATUS_OK;
 
  /* find the connection policy handle. */
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
   return NT_STATUS_INVALID_HANDLE;
 
+ /*check if function is granted*/
+ acc_granted = info->acc_granted;
+ acc_required = 0x00000020; //SAMR: open domain
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_open_domain: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
+ /*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);
+ if(!se_access_check(psd,p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+ {
+  DEBUG(2,("_samr_open_domain: ACCESS should be DENIED  (requested: %#010x)\n",
+      des_access));
+  //return r_u->status = status;    
+ }
+  
+ 
  /* associate the domain SID with the (unique) handle. */
  if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL)
   return NT_STATUS_NO_MEMORY;
+ info->acc_granted = acc_granted;
 
  /* get a (unique) handle.  open a policy on it. */
  if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info))
@@ -525,10 +591,49 @@
 }
 
 /*******************************************************************
+ 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, 0x20011);
+ 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, 0xf001f);
+ 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, 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, DOM_SID *usr_sid)
+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;
@@ -563,7 +668,7 @@
  return NT_STATUS_OK;
 }
 
-static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid)
+static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted)
 {
  struct samr_info *info = NULL;
 
@@ -575,6 +680,7 @@
   return False;
 
  *sid = info->sid;
+ *acc_granted = info->acc_granted;
  return True;
 }
 
@@ -589,13 +695,15 @@
  SEC_DESC * psd = NULL;
  size_t sd_size;
  int rid;
+ uint32 acc_granted;
 
  r_u->status = NT_STATUS_OK;
 
  /* Get the SID. */
-
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
+ 
+ 
 
  DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", sid_to_string(str_sid, &pol_sid)));
 
@@ -684,16 +792,29 @@
 
 NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, SAMR_R_ENUM_DOM_USERS *r_u)
 {
+ struct samr_info *info;
  SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
  int num_entries = 0;
  int total_entries = 0;
+ uint32 acc_granted;
+ uint32 acc_required;
  
  r_u->status = NT_STATUS_OK;
 
  /* find the policy handle.  open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
   return NT_STATUS_INVALID_HANDLE;
 
+ /*Access check on funktion*/
+ acc_granted = info->acc_granted;
+ acc_required = 0x00000100; //Domain: enum accounts
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_enum_dom_users: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
  DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
 
  become_root();
@@ -958,11 +1079,22 @@
  DOMAIN_GRP *grp=NULL;
  uint32 num_entries;
  DOM_SID sid;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  r_u->status = NT_STATUS_OK;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
+ 
+ /*Access check on funktion*/
+ acc_required = 0x00000100; //Domain: enum accounts
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_enum_dom_groups: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
 
@@ -990,12 +1122,23 @@
  fstring sid_str;
  DOM_SID sid;
  NTSTATUS status;
+ uint32  acc_granted;
+ uint32  acc_required;
  
  r_u->status = NT_STATUS_OK;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
 
+ /*Access check on funktion*/
+ acc_required = 0x00000100; //Domain: enum accounts
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_enum_dom_aliases: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
  sid_to_string(sid_str, &sid);
  DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
 
@@ -1208,21 +1351,33 @@
 NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u)
 {
  struct samr_info *info = NULL;
+ DOM_SID   sid;
  GROUP_MAP map;
+ uint32    acc_granted;
+ uint32    acc_required;
 
  r_u->status = NT_STATUS_OK;
 
  DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__));
 
  /* find the policy handle.  open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
+ 
+ /*Access check on funktion*/
+ acc_required = 0x00000008; //Alias: query info
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_query_aliasinfo: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
- if (!sid_check_is_in_our_domain(&info->sid) &&
-     !sid_check_is_in_builtin(&info->sid))
+ if (!sid_check_is_in_our_domain(&sid) &&
+     !sid_check_is_in_builtin(&sid))
   return NT_STATUS_OBJECT_TYPE_MISMATCH;
 
- if(!get_local_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
+ if(!get_local_group_from_sid(sid, &map, MAPPING_WITHOUT_PRIV))
   return NT_STATUS_NO_SUCH_ALIAS;
 
  switch (q_u->switch_level) {
@@ -1319,6 +1474,7 @@
  int num_rids = q_u->num_names2;
  DOM_SID pol_sid;
  fstring sid_str;
+ uint32  acc_granted;
 
  r_u->status = NT_STATUS_OK;
 
@@ -1327,7 +1483,7 @@
  ZERO_ARRAY(rid);
  ZERO_ARRAY(type);
 
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid)) {
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted)) {
   init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH);
   return r_u->status;
  }
@@ -1474,13 +1630,14 @@
  DOM_SID pol_sid;
  int num_rids = q_u->num_rids1;
  int i;
+ uint32 acc_granted;
 
  r_u->status = NT_STATUS_OK;
 
  DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
 
  /* find the policy handle.  open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
 
  if (num_rids > MAX_SAM_ENTRIES) {
@@ -1542,22 +1699,43 @@
  POLICY_HND domain_pol = q_u->domain_pol;
  POLICY_HND *user_pol = &r_u->user_pol;
  struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32    acc_granted;
+ uint32    acc_required;
+ uint32    des_access = q_u->access_mask;
+ size_t    sd_size;
+ NTSTATUS  status;
  BOOL ret;
 
  r_u->status = NT_STATUS_OK;
 
- /* find the domain policy handle. */
- if (!find_policy_by_hnd(p, &domain_pol, NULL))
-  return NT_STATUS_INVALID_HANDLE;
-
- /* Get the domain SID stored in the domain policy */
- if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
+ /* 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))
   return NT_STATUS_INVALID_HANDLE;
 
  /* append the user's RID to it */
  if(!sid_append_rid(&sid, q_u->user_rid))
   return NT_STATUS_NO_SUCH_USER;
 
+ /*check if function is granted*/
+ acc_required = 0x00000200; //Domain: open accounts, lookup names
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_api_samr_open_user: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
+ /*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(!se_access_check(psd,p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+ {
+  DEBUG(2,("_api_samr_open_usr: ACCESS should be DENIED  (requested: %#010x)\n",
+      des_access));
+  //return r_u->status = status;    
+ }
+ 
  pdb_init_sam(&sampass);
 
  become_root();
@@ -1572,9 +1750,10 @@
 
  pdb_free_sam(&sampass);
 
- /* associate the user's SID with the new handle. */
+ /* associate the user's SID and access bits with the new handle. */
  if ((info = get_samr_info_by_sid(&sid)) == NULL)
   return NT_STATUS_NO_MEMORY;
+ info->acc_granted = acc_granted;
 
  /* get a (unique) handle.  open a policy on it. */
  if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info))
@@ -1833,9 +2012,11 @@
 NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
 {
  SAM_ACCOUNT *sam_pass=NULL;
+ DOM_SID  sid;
  DOM_GID *gids = NULL;
  int num_groups = 0;
- struct samr_info *info = NULL;
+ uint32 acc_granted;
+ uint32 acc_required;
  BOOL ret;
 
  /*
@@ -1855,16 +2036,25 @@
  DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
 
  /* find the policy handle.  open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
-
- if (!sid_check_is_in_our_domain(&info->sid))
+  
+ /*check if function is granted*/
+ acc_required = 0x00000100; //User: get groups
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_query_usergroups: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
+ if (!sid_check_is_in_our_domain(&sid))
   return NT_STATUS_OBJECT_TYPE_MISMATCH;
 
  pdb_init_sam(&sam_pass);
 
  become_root();
- ret = pdb_getsampwsid(sam_pass, &info->sid);
+ ret = pdb_getsampwsid(sam_pass, &sid);
  unbecome_root();
 
  if (ret == False) {
@@ -2014,11 +2204,22 @@
  BOOL ret;
  NTSTATUS nt_status;
  struct passwd *pw;
+ uint32 acc_granted;
+ uint32 acc_required;
 
- /* find the policy handle.  open a policy on it. */
- if (!find_policy_by_hnd(p, &dom_pol, NULL))
+ /* Get the domain SID stored in the domain policy */
+   if(!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
-
+ 
+ /*Access check on funktion*/
+ acc_required = 0x00000010; //Domain: create user 
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_api_samr_create_user: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
  /* find the account: tell the caller if it exists.
    lkclXXXX i have *no* idea if this is a problem or not
     or even if you are supposed to construct a different
@@ -2133,11 +2334,7 @@
    return NT_STATUS_ACCESS_DENIED;  
   }
   
-  /* Get the domain SID stored in the domain policy */
-   if(!get_lsa_policy_samr_sid(p, &dom_pol, &sid)) {
-    pdb_free_sam(&sam_pass);
-  return NT_STATUS_INVALID_HANDLE;
- }
+  
 
  /* append the user's RID to it */
  if(!sid_append_rid(&sid, pdb_get_user_rid(sam_pass) )) {
@@ -2199,17 +2396,31 @@
 
 NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u)
 {
- struct samr_info *info = NULL;
+    struct samr_info *info = NULL;
+    SEC_DESC         *psd  = NULL;
+    size_t            sd_size;
+    uint32            des_access = q_u->access_mask;
+    uint32            acc_granted;
+    NTSTATUS          status;
 
     DEBUG(5,("_samr_connect: %d\n", __LINE__));
 
     r_u->status = NT_STATUS_OK;
+    
+    /*check if access can be granted as requested by client. */
+    samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+    se_map_generic(&des_access,&sam_generic_mapping);
+    if(!se_access_check(psd,p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+    {
+ DEBUG(2,("_samr_connect: ACCESS should be DENIED\n"));
+ //return r_u->status = status;    
+    }
 
-    /* associate the user's SID with the new handle. */
- if ((info = get_samr_info_by_sid(NULL)) == NULL)
+    /* associate access granted with the new handle. */
+    if ((info = get_samr_info_by_sid(NULL)) == NULL)
         return NT_STATUS_NO_MEMORY;
 
-    info->status = q_u->access_mask;
+    info->acc_granted = acc_granted;
 
     /* get a (unique) handle.  open a policy on it. */
     if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
@@ -2226,13 +2437,26 @@
 
 NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u)
 {
+ struct samr_info *info;
  fstring domain_name;
  DOM_SID sid;
+ uint32  acc_granted;
+ uint32  acc_required;
 
  r_u->status = NT_STATUS_OK;
 
- if (!find_policy_by_hnd(p, &q_u->connect_pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)&info))
   return NT_STATUS_INVALID_HANDLE;
+ 
+ /*Access check on funktion*/
+ acc_granted  = info->acc_granted;
+ acc_required = 0x00000020; //SAMR: open domain / lookup domain
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_lookup_domain: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0);
 
@@ -2293,11 +2517,27 @@
 
 NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u)
 {
+ struct samr_info *info;
+ uint32 acc_granted;
+ uint32 acc_required;
  uint32 num_entries = 2;
  fstring dom[2];
  char *name;
 
  r_u->status = NT_STATUS_OK;
+ 
+ if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
+  return NT_STATUS_INVALID_HANDLE;
+ 
+ /*Access check on funktion*/
+ acc_granted  = info->acc_granted;
+ acc_required = 0x00000010; //SAMR: enum domain
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_enum_domains: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  switch (lp_server_role()) {
  case ROLE_DOMAIN_PDC:
@@ -2330,21 +2570,43 @@
  POLICY_HND domain_pol = q_u->dom_pol;
  uint32 alias_rid = q_u->rid_alias;
  POLICY_HND *alias_pol = &r_u->pol;
- struct samr_info *info = NULL;
+ struct    samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32    acc_granted;
+ uint32    acc_required;
+ uint32    des_access = q_u->access_mask;
+ size_t    sd_size;
+ NTSTATUS  status;
 
  r_u->status = NT_STATUS_OK;
 
- /* get the domain policy. */
- if (!find_policy_by_hnd(p, &domain_pol, NULL))
-  return NT_STATUS_INVALID_HANDLE;
-
- /* Get the domain SID stored in the domain policy */
- if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
+ /* 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))
   return NT_STATUS_INVALID_HANDLE;
 
  /* append the alias' RID to it */
  if(!sid_append_rid(&sid, alias_rid))
   return NT_STATUS_NO_SUCH_USER;
+  
+ /*check if function is granted*/
+ acc_granted = info->acc_granted;
+ acc_required = 0x00000200; //Domain: open accounts, lookup names
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_api_samr_open_alias: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
+ /*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(!se_access_check(psd,p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+ {
+  DEBUG(2,("_api_samr_open_alias: ACCESS should be DENIED  (requested: %#010x)\n",
+      des_access));
+  //return r_u->status = status;    
+ }
 
  /*
   * we should check if the rid really exist !!!
@@ -2627,14 +2889,25 @@
  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;
 
  DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
 
  r_u->status = NT_STATUS_OK;
 
  /* find the policy handle.  open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*Access check on funktion*/
+ acc_required = 0x00000004 | 0x00000020; //User: set comment | set attributes
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_set_userinfo: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value));
 
@@ -2705,15 +2978,26 @@
  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;
 
  DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
 
  r_u->status = NT_STATUS_OK;
 
  /* find the policy handle.  open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
   return NT_STATUS_INVALID_HANDLE;
 
+ /*check if function is granted*/
+ acc_required = 0x00000004 | 0x00000020; //User: set comment | set attributes
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_set_userinfo2: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
  DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", sid_string_static(&sid)));
 
  if (ctr == NULL) {
@@ -2843,10 +3127,21 @@
 
  SAM_ACCOUNT *sam_user = NULL;
  BOOL check;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  /* find the policy handle.  open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000004; //Alias: get members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_query_aliasmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_copy(&als_sid, &alias_sid);
  sid_to_string(alias_sid_str, &alias_sid);
@@ -2939,11 +3234,22 @@
 
  SAM_ACCOUNT *sam_user = NULL;
  BOOL check;
+ uint32 acc_granted;
+ uint32 acc_required;
 
 
  /* find the policy handle.  open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000010; //Group: get members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_query_groupmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  /* todo: change to use sid_compare_front */
 
@@ -3027,10 +3333,21 @@
  NTSTATUS ret;
  SAM_ACCOUNT *sam_user = NULL;
  BOOL check;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000001; //Alias: add members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_add_aliasmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_to_string(alias_sid_str, &alias_sid);
  DEBUG(10, ("sid is %s\n", alias_sid_str));
@@ -3110,10 +3427,21 @@
  fstring grp_name;
  GROUP_MAP map;
  SAM_ACCOUNT *sam_pass=NULL;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+ 
+ /*check if function is granted*/
+ acc_required = 0x00000002; //Alias: get members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_del_aliasmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_to_string(alias_sid_str, &alias_sid);
  DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str));
@@ -3176,10 +3504,21 @@
  NTSTATUS ret;
  SAM_ACCOUNT *sam_user;
  BOOL check;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000004; //Group: add members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_add_groupmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_to_string(group_sid_str, &group_sid);
  DEBUG(10, ("sid is %s\n", group_sid_str));
@@ -3257,6 +3596,8 @@
  GROUP_MAP map;
  fstring grp_name;
  struct group *grp;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  /*
   * delete the group member named q_u->rid
@@ -3265,8 +3606,17 @@
   */
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000008; //Group: delete members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_del_groupmem: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if(!sid_check_is_in_our_domain(&group_sid))
   return NT_STATUS_NO_SUCH_GROUP;
@@ -3336,12 +3686,23 @@
 {
  DOM_SID user_sid;
  SAM_ACCOUNT *sam_pass=NULL;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = DELETE_ACCESS; //User: delete
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_delete_dom_user: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!sid_check_is_in_our_domain(&user_sid))
   return NT_STATUS_CANNOT_DELETE;
@@ -3390,12 +3751,23 @@
  gid_t gid;
  struct group *grp;
  GROUP_MAP map;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = DELETE_ACCESS; //Group: delete
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_delete_dom_group: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_copy(&dom_sid, &group_sid);
  sid_to_string(group_sid_str, &dom_sid);
@@ -3447,12 +3819,23 @@
  gid_t gid;
  struct group *grp;
  GROUP_MAP map;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__));
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = DELETE_ACCESS; //Alias: delete
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_delete_dom_alias: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  sid_copy(&dom_sid, &alias_sid);
  sid_to_string(alias_sid_str, &dom_sid);
@@ -3504,12 +3887,23 @@
  struct group *grp;
  struct samr_info *info;
  PRIVILEGE_SET priv_set;
+ uint32 acc_granted;
+ uint32 acc_required;
 
  init_privilege(&priv_set);
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000020; //Domain: create Group
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_create_dom_group: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!sid_equal(&dom_sid, &global_sam_sid))
   return NT_STATUS_ACCESS_DENIED;
@@ -3562,12 +3956,23 @@
  struct group *grp;
  struct samr_info *info;
  PRIVILEGE_SET priv_set;
+ uint32 acc_granted;
+ uint32  acc_required;
 
  init_privilege(&priv_set);
 
  /* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000040; //Domain: create alias
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_create_dom_alias: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!sid_equal(&dom_sid, &global_sam_sid))
   return NT_STATUS_ACCESS_DENIED;
@@ -3621,9 +4026,20 @@
  uid_t *uid=NULL;
  int num_uids=0;
  GROUP_INFO_CTR *ctr;
+ uint32 acc_granted;
+ uint32 acc_required;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000001; //Group: query info
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_query_groupinfo: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
   return NT_STATUS_INVALID_HANDLE;
@@ -3668,9 +4084,20 @@
  DOM_SID group_sid;
  GROUP_MAP map;
  GROUP_INFO_CTR *ctr;
+ uint32 acc_granted;
+ uint32 acc_required;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000002; //Group: set info
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_set_groupinfo: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
   return NT_STATUS_NO_SUCH_GROUP;
@@ -3710,9 +4137,20 @@
  DOM_SID group_sid;
  GROUP_MAP map;
  ALIAS_INFO_CTR *ctr;
+ uint32 acc_granted;
+ uint32 acc_required;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
+  
+ /*check if function is granted*/
+ acc_required = 0x00000010; //Alias: get members
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_samr_set_aliasinfo: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
 
  if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
   return NT_STATUS_NO_SUCH_GROUP;
@@ -3758,11 +4196,36 @@
  DOM_SID info_sid;
  GROUP_MAP map;
  struct samr_info *info;
+ SEC_DESC         *psd = NULL;
+ uint32            acc_granted;
+ uint32            acc_required;
+ uint32            des_access;
+ size_t            sd_size;
+ NTSTATUS          status;
  fstring sid_string;
 
- if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid)) 
+ if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted)) 
   return NT_STATUS_INVALID_HANDLE;
 
+ /*check if function is granted*/
+ acc_required = 0x00000200; //Domain: open accounts, lookup names
+ if ((acc_granted & acc_required) != acc_required)
+ {
+  DEBUG(2,("_api_samr_open_group: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+      acc_granted, acc_required));
+  //return NT_STATUS_ACCESS_DENIED;
+ }
+ 
+ /*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(!se_access_check(psd,p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+ {
+  DEBUG(2,("_api_samr_open_group: ACCESS should be DENIED  (requested: %#010x)\n",
+      des_access));
+  //return r_u->status = status;    
+ }
+ 
  /* this should not be hard-coded like this */
  if (!sid_equal(&sid, &global_sam_sid))
   return NT_STATUS_ACCESS_DENIED;




More information about the samba-technical mailing list