Patch to add security descriptors to the SAMR pipe.
authorAndrew Bartlett <abartlet@samba.org>
Thu, 4 Jul 2002 08:45:45 +0000 (08:45 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 4 Jul 2002 08:45:45 +0000 (08:45 +0000)
This is not the final solution, I think this will probably changed with the
move to the new SAM subsystem, but it allows some research and gives us
somthing to start with.

It should also help with getting proper NT_TOKEN passing set-up.

Original patch by "Kai Krueger" <kai@kruegernetz.de>, which I have modified to
pass back NTSTATUS returns in more places and to use a little more common code.

Andrew Bartlett
(This used to be commit 43b72493708e74e089989db42a003a3862c793e6)

source3/include/rpc_samr.h
source3/rpc_server/srv_samr_nt.c

index 1bb7a87b351e1a0fd4166c97ca89389c44e6503d..9df3e7fe1958d808326cabd93a2ef492f95fe4a2 100644 (file)
@@ -145,6 +145,170 @@ SamrTestPrivateFunctionsUser
 #define SAMR_CONNECT           0x39
 #define SAMR_SET_USERINFO      0x3A
 
+//Access bits to the SAM-object
+#define SAMR_ACCESS_UNKNOWN_1        0x00000001
+#define SAMR_ACCESS_SHUTDOWN_SERVER  0x00000002
+#define SAMR_ACCESS_UNKNOWN_4        0x00000004
+#define SAMR_ACCESS_UNKNOWN_8        0x00000008
+#define SAMR_ACCESS_ENUM_DOMAINS     0x00000010
+#define SAMR_ACCESS_OPEN_DOMAIN      0x00000020
+
+#define SAMR_ALL_ACCESS  ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
+                           SAMR_ACCESS_OPEN_DOMAIN         | \
+                          SAMR_ACCESS_ENUM_DOMAINS        | \
+                          SAMR_ACCESS_UNKNOWN_8           | \
+                          SAMR_ACCESS_UNKNOWN_4           | \
+                          SAMR_ACCESS_SHUTDOWN_SERVER     | \
+                          SAMR_ACCESS_UNKNOWN_1 )
+                          
+#define SAMR_READ        ( STANDARD_RIGHTS_READ_ACCESS     | \
+                           SAMR_ACCESS_ENUM_DOMAINS )
+
+#define SAMR_WRITE       ( STANDARD_RIGHTS_WRITE_ACCESS    | \
+                           SAMR_ACCESS_UNKNOWN_8           | \
+                          SAMR_ACCESS_UNKNOWN_4           | \
+                          SAMR_ACCESS_SHUTDOWN_SERVER )
+
+#define SAMR_EXECUTE     ( STANDARD_RIGHTS_EXECUTE_ACCESS  | \
+                           SAMR_ACCESS_OPEN_DOMAIN         | \
+                          SAMR_ACCESS_UNKNOWN_1 )            
+
+//Access bits to Domain-objects
+#define DOMAIN_ACCESS_LOOKUP_INFO_1  0x000000001
+#define DOMAIN_ACCESS_SET_INFO_1     0x000000002
+#define DOMAIN_ACCESS_LOOKUP_INFO_2  0x000000004
+#define DOMAIN_ACCESS_SET_INFO_2     0x000000008
+#define DOMAIN_ACCESS_CREATE_USER    0x000000010
+#define DOMAIN_ACCESS_CREATE_GROUP   0x000000020
+#define DOMAIN_ACCESS_CREATE_ALIAS   0x000000040
+#define DOMAIN_ACCESS_UNKNOWN_80     0x000000080
+#define DOMAIN_ACCESS_ENUM_ACCOUNTS  0x000000100
+#define DOMAIN_ACCESS_OPEN_ACCOUNT   0x000000200
+#define DOMAIN_ACCESS_SET_INFO_3     0x000000400
+
+#define DOMAIN_ALL_ACCESS  ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
+                             DOMAIN_ACCESS_SET_INFO_3        | \
+                            DOMAIN_ACCESS_OPEN_ACCOUNT      | \
+                            DOMAIN_ACCESS_ENUM_ACCOUNTS     | \
+                            DOMAIN_ACCESS_UNKNOWN_80        | \
+                            DOMAIN_ACCESS_CREATE_ALIAS      | \
+                            DOMAIN_ACCESS_CREATE_GROUP      | \
+                            DOMAIN_ACCESS_CREATE_USER       | \
+                            DOMAIN_ACCESS_SET_INFO_2        | \
+                            DOMAIN_ACCESS_LOOKUP_INFO_2     | \
+                            DOMAIN_ACCESS_SET_INFO_1        | \
+                            DOMAIN_ACCESS_LOOKUP_INFO_1 )
+                          
+#define DOMAIN_READ        ( STANDARD_RIGHTS_READ_ACCESS     | \
+                             DOMAIN_ACCESS_UNKNOWN_80        | \
+                            DOMAIN_ACCESS_LOOKUP_INFO_2 )
+
+#define DOMAIN_WRITE       ( STANDARD_RIGHTS_WRITE_ACCESS    | \
+                             DOMAIN_ACCESS_SET_INFO_3        | \
+                            DOMAIN_ACCESS_CREATE_ALIAS      | \
+                            DOMAIN_ACCESS_CREATE_GROUP      | \
+                            DOMAIN_ACCESS_CREATE_USER       | \
+                            DOMAIN_ACCESS_SET_INFO_2        | \
+                            DOMAIN_ACCESS_SET_INFO_1 )
+
+#define DOMAIN_EXECUTE     ( STANDARD_RIGHTS_EXECUTE_ACCESS  | \
+                             DOMAIN_ACCESS_OPEN_ACCOUNT      | \
+                            DOMAIN_ACCESS_ENUM_ACCOUNTS     | \
+                            DOMAIN_ACCESS_LOOKUP_INFO_1 )            
+
+//Access bits to User-objects
+#define USER_ACCESS_GET_NAME_ETC     0x000000001
+#define USER_ACCESS_GET_LOCALE       0x000000002
+#define USER_ACCESS_SET_LOC_COM      0x000000004
+#define USER_ACCESS_GET_LOGONINFO    0x000000008
+#define USER_ACCESS_UNKNOWN_10       0x000000010
+#define USER_ACCESS_SET_ATTRIBUTES   0x000000020
+#define USER_ACCESS_CHANGE_PASSWORD  0x000000040
+#define USER_ACCESS_SET_PASSWORD     0x000000080
+#define USER_ACCESS_GET_GROUPS       0x000000100
+#define USER_ACCESS_UNKNOWN_200      0x000000200
+#define USER_ACCESS_UNKNOWN_400      0x000000400
+
+#define USER_ALL_ACCESS    ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
+                             USER_ACCESS_UNKNOWN_400       | \
+                            USER_ACCESS_UNKNOWN_200       | \
+                            USER_ACCESS_GET_GROUPS        | \
+                            USER_ACCESS_SET_PASSWORD      | \
+                            USER_ACCESS_CHANGE_PASSWORD   | \
+                            USER_ACCESS_SET_ATTRIBUTES    | \
+                            USER_ACCESS_UNKNOWN_10        | \
+                            USER_ACCESS_GET_LOGONINFO     | \
+                            USER_ACCESS_SET_LOC_COM       | \
+                            USER_ACCESS_GET_LOCALE        | \
+                            USER_ACCESS_GET_NAME_ETC )
+                          
+#define USER_READ          ( STANDARD_RIGHTS_READ_ACCESS     | \
+                             USER_ACCESS_UNKNOWN_200         | \
+                            USER_ACCESS_GET_GROUPS          | \
+                            USER_ACCESS_UNKNOWN_10          | \
+                            USER_ACCESS_GET_LOGONINFO       | \
+                            USER_ACCESS_GET_LOCALE )
+
+#define USER_WRITE         ( STANDARD_RIGHTS_WRITE_ACCESS    | \
+                             USER_ACCESS_CHANGE_PASSWORD     | \
+                            USER_ACCESS_SET_LOC_COM )
+                            
+#define USER_EXECUTE       ( STANDARD_RIGHTS_EXECUTE_ACCESS  | \
+                             USER_ACCESS_CHANGE_PASSWORD     | \
+                            USER_ACCESS_GET_NAME_ETC )
+
+//Access bits to Group-objects                      
+#define GROUP_ACCESS_LOOKUP_INFO     0x00000001
+#define GROUP_ACCESS_SET_INFO        0x00000002
+#define GROUP_ACCESS_ADD_MEMBER      0x00000004
+#define GROUP_ACCESS_REMOVE_MEMBER   0x00000008
+#define GROUP_ACCESS_GET_MEMBERS     0x00000010
+
+#define GROUP_ALL_ACCESS   ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
+                             GROUP_ACCESS_GET_MEMBERS        | \
+                            GROUP_ACCESS_REMOVE_MEMBER      | \
+                            GROUP_ACCESS_ADD_MEMBER         | \
+                            GROUP_ACCESS_SET_INFO           | \
+                            GROUP_ACCESS_LOOKUP_INFO )
+                          
+#define GROUP_READ         ( STANDARD_RIGHTS_READ_ACCESS     | \
+                             GROUP_ACCESS_GET_MEMBERS )
+
+#define GROUP_WRITE        ( STANDARD_RIGHTS_WRITE_ACCESS    | \
+                             GROUP_ACCESS_REMOVE_MEMBER      | \
+                            GROUP_ACCESS_ADD_MEMBER         | \
+                            GROUP_ACCESS_SET_INFO )
+                            
+#define GROUP_EXECUTE      ( STANDARD_RIGHTS_EXECUTE_ACCESS  | \
+                             GROUP_ACCESS_LOOKUP_INFO )
+                            
+//Access bits to Alias-objects
+#define ALIAS_ACCESS_ADD_MEMBER      0x00000001
+#define ALIAS_ACCESS_REMOVE_MEMBER   0x00000002
+#define ALIAS_ACCESS_GET_MEMBERS     0x00000004
+#define ALIAS_ACCESS_LOOKUP_INFO     0x00000008
+#define ALIAS_ACCESS_SET_INFO        0x00000010
+
+#define ALIAS_ALL_ACCESS   ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
+                             ALIAS_ACCESS_GET_MEMBERS        | \
+                            ALIAS_ACCESS_REMOVE_MEMBER      | \
+                            ALIAS_ACCESS_ADD_MEMBER         | \
+                            ALIAS_ACCESS_SET_INFO           | \
+                            ALIAS_ACCESS_LOOKUP_INFO )
+                          
+#define ALIAS_READ         ( STANDARD_RIGHTS_READ_ACCESS     | \
+                             ALIAS_ACCESS_GET_MEMBERS )
+
+#define ALIAS_WRITE        ( STANDARD_RIGHTS_WRITE_ACCESS    | \
+                             ALIAS_ACCESS_REMOVE_MEMBER      | \
+                            ALIAS_ACCESS_ADD_MEMBER         | \
+                            ALIAS_ACCESS_SET_INFO )
+                            
+#define ALIAS_EXECUTE      ( STANDARD_RIGHTS_EXECUTE_ACCESS  | \
+                             ALIAS_ACCESS_LOOKUP_INFO )
+
+
+
 
 typedef struct _DISP_USER_INFO {
        SAM_ACCOUNT *sam;
index 9393917cdef7dd49dab5adbbc7efdf0ebdbbd677..7a23a55b2ace488064729ae99287c226f86494e9 100644 (file)
@@ -54,11 +54,69 @@ struct samr_info {
        /* 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;
 
        TALLOC_CTX *mem_ctx;
 };
 
+struct generic_mapping sam_generic_mapping = {SAMR_READ, SAMR_WRITE, SAMR_EXECUTE, SAMR_ALL_ACCESS};
+struct generic_mapping dom_generic_mapping = {DOMAIN_READ, DOMAIN_WRITE, DOMAIN_EXECUTE, DOMAIN_ALL_ACCESS};
+struct generic_mapping usr_generic_mapping = {USER_READ, USER_WRITE, USER_EXECUTE, USER_ALL_ACCESS};
+struct generic_mapping grp_generic_mapping = {GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, GROUP_ALL_ACCESS};
+struct generic_mapping ali_generic_mapping = {ALIAS_READ, ALIAS_WRITE, ALIAS_EXECUTE, ALIAS_ALL_ACCESS};
+
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *d_size);
+
+
+/*******************************************************************
+ Checks if access to an object should be granted, and returns that
+ level of access for further checks.
+********************************************************************/
+
+NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_token, uint32 des_access, 
+                                 uint32 *acc_granted, const char *debug) 
+{
+       NTSTATUS status = NT_STATUS_ACCESS_DENIED;
+
+       if (!se_access_check(psd, nt_user_token, des_access, acc_granted, &status)) {
+               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));
+               }
+       }
+       return status;
+}
+
+/*******************************************************************
+ Checks if access to a function can be granted
+********************************************************************/
+
+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, acc_granted, acc_required));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+       return NT_STATUS_OK;
+}
+
+
 /*******************************************************************
  Create a samr_info struct.
 ********************************************************************/
@@ -276,17 +334,37 @@ NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HN
 
 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    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;
 
+       if (!NT_STATUS_IS_OK(status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN,"_samr_open_domain"))) {
+               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);
+
+       if (!NT_STATUS_IS_OK(status = 
+                            access_check_samr_object(psd, p->pipe_user.nt_user_token, 
+                                                     des_access, &acc_granted, "_samr_open_domain"))) {
+               return 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))
@@ -326,11 +404,90 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
        return r_u->status;
 }
 
+
+/*******************************************************************
+ samr_make_sam_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_sam_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, SAMR_EXECUTE | SAMR_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, SAMR_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, NULL, NULL, NULL, psa, sd_size)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ 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;
+       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, DOMAIN_EXECUTE | DOMAIN_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, DOMAIN_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, 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_BUF **buf, DOM_SID *usr_sid)
+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;
@@ -340,8 +497,6 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI
        SEC_ACCESS mask;
 
        SEC_ACL *psa = NULL;
-       SEC_DESC *psd = NULL;
-       size_t sd_size;
 
        sid_copy(&adm_sid, &global_sid_Builtin);
        sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
@@ -349,29 +504,107 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI
        sid_copy(&act_sid, &global_sid_Builtin);
        sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
 
-       init_sec_access(&mask, 0x2035b);
+       /*basic access for every one*/
+       init_sec_access(&mask, USER_EXECUTE | USER_READ);
        init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
 
-       init_sec_access(&mask, 0xf07ff);
+       /*full access for builtin aliases Administrators and Account Operators*/
+       init_sec_access(&mask, USER_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);
 
-       init_sec_access(&mask,0x20044);
+       /*extended access for the user*/
+       init_sec_access(&mask,READ_CONTROL_ACCESS | USER_ACCESS_CHANGE_PASSWORD | USER_ACCESS_SET_LOC_COM);
        init_sec_ace(&ace[3], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
 
-       if((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
+       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, NULL, NULL, NULL, psa, &sd_size)) == NULL)
+       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_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, GROUP_EXECUTE | 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, 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((*buf = make_sec_desc_buf(ctx, sd_size, psd)) == NULL)
+       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;
 }
 
-static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid)
+/*******************************************************************
+ 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, ALIAS_EXECUTE | 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, 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, 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)
 {
        struct samr_info *info = NULL;
 
@@ -383,6 +616,7 @@ static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *s
                return False;
 
        *sid = info->sid;
+       *acc_granted = info->acc_granted;
        return True;
 }
 
@@ -394,17 +628,52 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
 {
        DOM_SID pol_sid;
        fstring str_sid;
+       SEC_DESC * psd = NULL;
+       size_t sd_size;
+       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)));
 
-       r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &r_u->buf, &pol_sid);
+       /* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */
+
+       /* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */
+       if (pol_sid.sid_rev_num == 0)
+       {
+               DEBUG(5,("_samr_query_sec_obj: querying security on SAM\n"));
+               r_u->status = samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+       }
+       else if (sid_equal(&pol_sid,get_global_sam_sid()))  //check if it is our domain SID
+
+       {
+               DEBUG(5,("_samr_query_sec_obj: querying security on Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+               r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+       }
+       else if (sid_equal(&pol_sid,&global_sid_Builtin)) //check if it is the Builtin  Domain
+       {
+               /* TODO: Builtin probably needs a different SD with restricted write access*/
+               DEBUG(5,("_samr_query_sec_obj: querying security on Builtin Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+               r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+       }
+       else if (sid_check_is_in_our_domain(&pol_sid) ||
+                sid_check_is_in_builtin(&pol_sid))
+       {
+               /* TODO: different SDs have to be generated for aliases groups and users.
+                        Currently all three get a default user SD  */
+               DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+               r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &psd,&sd_size, &pol_sid);
+       }
+       else return NT_STATUS_OBJECT_TYPE_MISMATCH;
+
+       if ((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
+               return NT_STATUS_NO_MEMORY;
 
        if (NT_STATUS_IS_OK(r_u->status))
                r_u->ptr = 1;
@@ -496,9 +765,14 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
                return NT_STATUS_INVALID_HANDLE;
 
-       if (!get_lsa_policy_samr_sid(p, &q_u->pol, &domain_sid))
-               return NT_STATUS_INVALID_HANDLE;
+       domain_sid = info->sid;
 
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, 
+                                       DOMAIN_ACCESS_ENUM_ACCOUNTS, 
+                                       "_samr_enum_dom_users"))) {
+               return r_u->status;
+       }
+       
        DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
 
        become_root();
@@ -782,11 +1056,16 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM
        DOMAIN_GRP *grp=NULL;
        uint32 num_entries;
        DOM_SID sid;
+       uint32 acc_granted;
 
        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;
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_groups"))) {
+               return r_u->status;
+       }
 
        DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
 
@@ -814,12 +1093,17 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S
        fstring sid_str;
        DOM_SID sid;
        NTSTATUS status;
+       uint32  acc_granted;
        
        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;
 
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_aliases"))) {
+               return r_u->status;
+       }
+       
        sid_to_string(sid_str, &sid);
        DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
 
@@ -867,8 +1151,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
        if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
                return NT_STATUS_INVALID_HANDLE;
 
-       if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &domain_sid))
-               return NT_STATUS_INVALID_HANDLE;
+       domain_sid = info->sid;
 
        /*
         * calculate how many entries we will return.
@@ -1036,22 +1319,26 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
 
 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;
 
        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;
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_LOOKUP_INFO, "_samr_query_aliasinfo"))) {
+               return r_u->status;
+       }
 
-       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) {
@@ -1148,6 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
        int num_rids = q_u->num_names2;
        DOM_SID pol_sid;
        fstring sid_str;
+       uint32  acc_granted;
 
        r_u->status = NT_STATUS_OK;
 
@@ -1156,10 +1444,14 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
        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;
        }
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, 0, "_samr_lookup_names"))) { /* Don't know the acc_bits yet */
+               return r_u->status;
+       }
 
        if (num_rids > MAX_SAM_ENTRIES) {
                num_rids = MAX_SAM_ENTRIES;
@@ -1303,13 +1595,14 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
        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) {
@@ -1371,27 +1664,40 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN
        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    des_access = q_u->access_mask;
+       size_t    sd_size;
        BOOL ret;
        NTSTATUS nt_status;
 
        r_u->status = NT_STATUS_OK;
 
-       /* find the domain policy handle. */
-       if (!find_policy_by_hnd(p, &domain_pol, NULL))
+       /* 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))
                return NT_STATUS_INVALID_HANDLE;
+       
+       if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_user"))) {
+               return nt_status;
+       }
 
        nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass);
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
-       /* Get the domain SID stored in the domain policy */
-       if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
-               return NT_STATUS_INVALID_HANDLE;
-
        /* append the user's RID to it */
-       if(!sid_append_rid(&sid, q_u->user_rid))
+       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"))) {
+               return nt_status;
+       }
 
        become_root();
        ret=pdb_getsampwsid(sampass, &sid);
@@ -1404,9 +1710,10 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN
 
        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))
@@ -1685,9 +1992,10 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
 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;
        BOOL ret;
 
        /*
@@ -1707,16 +2015,20 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
        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 (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_usergroups"))) {
+               return r_u->status;
+       }
 
-       if (!sid_check_is_in_our_domain(&info->sid))
+       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) {
@@ -1866,11 +2178,19 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
        BOOL ret;
        NTSTATUS nt_status;
        struct passwd *pw;
+       uint32 acc_granted;
+       SEC_DESC *psd;
+       size_t    sd_size;
+       uint32    des_access;
 
-       /* 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;
 
+       if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_USER, "_samr_create_user"))) {
+               return nt_status;
+       }
+
        /* 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
@@ -1939,7 +2259,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
        else 
                pstrcpy(add_script, lp_adduser_script());
 
-       if(*add_script) {
+       if (*add_script) {
                int add_ret;
                all_string_sub(add_script, "%u", account, sizeof(account));
                add_ret = smbrun(add_script,NULL);
@@ -1988,6 +2308,14 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
        /* Get the user's SID */
        sid_copy(&sid, pdb_get_user_sid(sam_pass));
        
+       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_create_user"))) {
+               return nt_status;
+       }
+
        /* associate the user's SID with the new handle. */
        if ((info = get_samr_info_by_sid(&sid)) == NULL) {
                pdb_free_sam(&sam_pass);
@@ -1996,6 +2324,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
 
        ZERO_STRUCTP(info);
        info->sid = sid;
+       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)) {
@@ -2019,29 +2348,29 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
 {
        struct samr_info *info = NULL;
 
-    /* Access check */
+       /* Access check */
 
-    if (!pipe_access_check(p)) {
-           DEBUG(3, ("access denied to samr_connect_anon\n"));
-           r_u->status = NT_STATUS_ACCESS_DENIED;
-           return r_u->status;
-    }
+       if (!pipe_access_check(p)) {
+               DEBUG(3, ("access denied to samr_connect_anon\n"));
+               r_u->status = NT_STATUS_ACCESS_DENIED;
+               return r_u->status;
+       }
 
-    /* set up the SAMR connect_anon response */
+       /* set up the SAMR connect_anon response */
 
-    r_u->status = NT_STATUS_OK;
+       r_u->status = NT_STATUS_OK;
 
-    /* associate the user's SID with the new handle. */
-    if ((info = get_samr_info_by_sid(NULL)) == NULL)
-        return NT_STATUS_NO_MEMORY;
+       /* associate the user's SID with the new handle. */
+       if ((info = get_samr_info_by_sid(NULL)) == NULL)
+               return NT_STATUS_NO_MEMORY;
 
-    info->status = q_u->unknown_0;
+       info->status = q_u->unknown_0;
 
-    /* get a (unique) handle.  open a policy on it. */
-    if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
-        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       /* get a (unique) handle.  open a policy on it. */
+       if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
-    return r_u->status;
+       return r_u->status;
 }
 
 /*******************************************************************
@@ -2051,32 +2380,47 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
 NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u)
 {
        struct samr_info *info = NULL;
+       SEC_DESC *psd = NULL;
+       uint32    acc_granted;
+       uint32    des_access = q_u->access_mask;
+       size_t    sd_size;
+       NTSTATUS  nt_status;
 
-    DEBUG(5,("_samr_connect: %d\n", __LINE__));
 
-    /* Access check */
+       DEBUG(5,("_samr_connect: %d\n", __LINE__));
 
-    if (!pipe_access_check(p)) {
-           DEBUG(3, ("access denied to samr_connect\n"));
-           r_u->status = NT_STATUS_ACCESS_DENIED;
-           return r_u->status;
-    }
+       /* Access check */
 
-    r_u->status = NT_STATUS_OK;
+       if (!pipe_access_check(p)) {
+               DEBUG(3, ("access denied to samr_connect\n"));
+               r_u->status = NT_STATUS_ACCESS_DENIED;
+               return r_u->status;
+       }
+
+       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"))) {
+               return nt_status;
+       }
+
+       r_u->status = NT_STATUS_OK;
 
-    /* associate the user's SID with the new handle. */
+       /* associate the user's SID and access granted with the new handle. */
        if ((info = get_samr_info_by_sid(NULL)) == NULL)
-        return NT_STATUS_NO_MEMORY;
+               return NT_STATUS_NO_MEMORY;
 
-    info->status = q_u->access_mask;
+       info->acc_granted = acc_granted;
+       info->status = q_u->access_mask;
 
-    /* get a (unique) handle.  open a policy on it. */
-    if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
-        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       /* get a (unique) handle.  open a policy on it. */
+       if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
-    DEBUG(5,("_samr_connect: %d\n", __LINE__));
+       DEBUG(5,("_samr_connect: %d\n", __LINE__));
 
-    return r_u->status;
+       return r_u->status;
 }
 
 /**********************************************************************
@@ -2085,14 +2429,19 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
 
 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;
 
        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;
 
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN, "_samr_lookup_domain"))) {
+               return r_u->status;
+       }
+
        rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0);
 
        ZERO_STRUCT(sid);
@@ -2152,11 +2501,19 @@ static BOOL make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam,
 
 NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u)
 {
+       struct samr_info *info;
        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;
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_ENUM_DOMAINS, "_samr_enum_domains"))) {
+               return r_u->status;
+       }
 
        switch (lp_server_role()) {
        case ROLE_DOMAIN_PDC:
@@ -2189,21 +2546,35 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
        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    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;
+               
+       if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_alias"))) {
+               return status;
+       }
 
        /* append the alias' RID to it */
-       if(!sid_append_rid(&sid, alias_rid))
+       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"))) {
+               return status;
+       }
 
        /*
         * we should check if the rid really exist !!!
@@ -2213,6 +2584,8 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
        /* associate the user's SID 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, alias_pol, free_samr_info, (void *)info))
@@ -2486,15 +2859,22 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
        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;
-
+       
+       acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) {
+               return r_u->status;
+       }
+               
        DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value));
 
        if (ctr == NULL) {
@@ -2564,14 +2944,21 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
        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;
+       
+       acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) {
+               return r_u->status;
+       }
 
        DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", sid_string_static(&sid)));
 
@@ -2638,6 +3025,10 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
        /* find the policy handle.  open a policy on it. */
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
                return NT_STATUS_INVALID_HANDLE;
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_useraliases"))) {
+               return r_u->status;
+       }
 
        if (!sid_check_is_domain(&info->sid) &&
            !sid_check_is_builtin(&info->sid))
@@ -2702,11 +3093,16 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
 
        SAM_ACCOUNT *sam_user = NULL;
        BOOL check;
+       uint32 acc_granted;
 
        /* 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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_GET_MEMBERS, "_samr_query_aliasmem"))) {
+               return r_u->status;
+       }
+               
        sid_copy(&als_sid, &alias_sid);
        sid_to_string(alias_sid_str, &alias_sid);
        sid_split_rid(&alias_sid, &alias_rid);
@@ -2798,12 +3194,16 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
 
        SAM_ACCOUNT *sam_user = NULL;
        BOOL check;
-
+       uint32 acc_granted;
 
        /* 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;
-
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_GET_MEMBERS, "_samr_query_groupmem"))) {
+               return r_u->status;
+       }
+               
        /* todo: change to use sid_compare_front */
 
        sid_split_rid(&group_sid, &group_rid);
@@ -2886,11 +3286,16 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
        NTSTATUS ret;
        SAM_ACCOUNT *sam_user = NULL;
        BOOL check;
+       uint32 acc_granted;
 
        /* 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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_ADD_MEMBER, "_samr_add_aliasmem"))) {
+               return r_u->status;
+       }
+               
        sid_to_string(alias_sid_str, &alias_sid);
        DEBUG(10, ("sid is %s\n", alias_sid_str));
 
@@ -2969,11 +3374,16 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
        fstring grp_name;
        GROUP_MAP map;
        SAM_ACCOUNT *sam_pass=NULL;
+       uint32 acc_granted;
 
        /* 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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_REMOVE_MEMBER, "_samr_del_aliasmem"))) {
+               return r_u->status;
+       }
+       
        sid_to_string(alias_sid_str, &alias_sid);
        DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str));
 
@@ -3035,10 +3445,15 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
        NTSTATUS ret;
        SAM_ACCOUNT *sam_user;
        BOOL check;
+       uint32 acc_granted;
 
        /* 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;
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_ADD_MEMBER, "_samr_add_groupmem"))) {
+               return r_u->status;
+       }
 
        sid_to_string(group_sid_str, &group_sid);
        DEBUG(10, ("sid is %s\n", group_sid_str));
@@ -3116,6 +3531,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        GROUP_MAP map;
        fstring grp_name;
        struct group *grp;
+       uint32 acc_granted;
 
        /*
         * delete the group member named q_u->rid
@@ -3124,16 +3540,20 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
         */
 
        /* 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;
-
-       if(!sid_check_is_in_our_domain(&group_sid))
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_REMOVE_MEMBER, "_samr_del_groupmem"))) {
+               return r_u->status;
+       }
+               
+       if (!sid_check_is_in_our_domain(&group_sid))
                return NT_STATUS_NO_SUCH_GROUP;
 
        sid_copy(&user_sid, get_global_sam_sid());
        sid_append_rid(&user_sid, q_u->rid);
 
-       if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
+       if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
                return NT_STATUS_NO_SUCH_GROUP;
 
        if ((grp=getgrgid(map.gid)) == NULL)
@@ -3144,14 +3564,14 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
 
        /* check if the user exists before trying to remove it from the group */
        pdb_init_sam(&sam_pass);
-       if(!pdb_getsampwsid(sam_pass, &user_sid)) {
+       if (!pdb_getsampwsid(sam_pass, &user_sid)) {
                DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass)));
                pdb_free_sam(&sam_pass);
                return NT_STATUS_NO_SUCH_USER;
        }
 
        /* if the user is not in the group */
-       if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+       if (!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
                pdb_free_sam(&sam_pass);
                return NT_STATUS_MEMBER_NOT_IN_GROUP;
        }
@@ -3159,7 +3579,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
 
        /* check if the user has been removed then ... */
-       if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+       if (user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
                pdb_free_sam(&sam_pass);
                return NT_STATUS_ACCESS_DENIED;         /* don't know what to reply else */
        }
@@ -3195,13 +3615,18 @@ 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;
 
        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;
-
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_user"))) {
+               return r_u->status;
+       }
+               
        if (!sid_check_is_in_our_domain(&user_sid))
                return NT_STATUS_CANNOT_DELETE;
 
@@ -3249,13 +3674,18 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
        gid_t gid;
        struct group *grp;
        GROUP_MAP map;
+       uint32 acc_granted;
 
        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;
-
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_group"))) {
+               return r_u->status;
+       }
+               
        sid_copy(&dom_sid, &group_sid);
        sid_to_string(group_sid_str, &dom_sid);
        sid_split_rid(&dom_sid, &group_rid);
@@ -3306,13 +3736,18 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
        gid_t gid;
        struct group *grp;
        GROUP_MAP map;
+       uint32 acc_granted;
 
        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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_alias"))) {
+               return r_u->status;
+       }
+               
        sid_copy(&dom_sid, &alias_sid);
        sid_to_string(alias_sid_str, &dom_sid);
        sid_split_rid(&dom_sid, &alias_rid);
@@ -3363,13 +3798,18 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        struct group *grp;
        struct samr_info *info;
        PRIVILEGE_SET priv_set;
+       uint32 acc_granted;
 
        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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_GROUP, "_samr_create_dom_group"))) {
+               return r_u->status;
+       }
+               
        if (!sid_equal(&dom_sid, get_global_sam_sid()))
                return NT_STATUS_ACCESS_DENIED;
 
@@ -3421,13 +3861,18 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
        struct group *grp;
        struct samr_info *info;
        PRIVILEGE_SET priv_set;
+       uint32 acc_granted;
 
        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;
-
+               
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_ALIAS, "_samr_create_alias"))) {
+               return r_u->status;
+       }
+               
        if (!sid_equal(&dom_sid, get_global_sam_sid()))
                return NT_STATUS_ACCESS_DENIED;
 
@@ -3480,10 +3925,15 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
        uid_t *uid=NULL;
        int num_uids=0;
        GROUP_INFO_CTR *ctr;
+       uint32 acc_granted;
 
-       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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_LOOKUP_INFO, "_samr_query_groupinfo"))) {
+               return r_u->status;
+       }
+               
        if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
                return NT_STATUS_INVALID_HANDLE;
 
@@ -3527,10 +3977,15 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
        DOM_SID group_sid;
        GROUP_MAP map;
        GROUP_INFO_CTR *ctr;
+       uint32 acc_granted;
 
-       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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_SET_INFO, "_samr_set_groupinfo"))) {
+               return r_u->status;
+       }
+               
        if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
                return NT_STATUS_NO_SUCH_GROUP;
        
@@ -3569,10 +4024,15 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
        DOM_SID group_sid;
        GROUP_MAP map;
        ALIAS_INFO_CTR *ctr;
+       uint32 acc_granted;
 
-       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;
-
+       
+       if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_SET_INFO, "_samr_set_aliasinfo"))) {
+               return r_u->status;
+       }
+               
        if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
                return NT_STATUS_NO_SUCH_GROUP;
        
@@ -3628,10 +4088,29 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
        DOM_SID info_sid;
        GROUP_MAP map;
        struct samr_info *info;
+       SEC_DESC         *psd = NULL;
+       uint32            acc_granted;
+       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;
+       
+       if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_group"))) {
+               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;
+       }
+
 
        /* this should not be hard-coded like this */
        if (!sid_equal(&sid, get_global_sam_sid()))
@@ -3643,6 +4122,8 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
 
        if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
+               
+       info->acc_granted = acc_granted;
 
        DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string));