there is no unknown field in LSA_SEC_QOS
authorJean-François Micouleau <jfm@samba.org>
Mon, 17 Dec 2001 23:03:23 +0000 (23:03 +0000)
committerJean-François Micouleau <jfm@samba.org>
Mon, 17 Dec 2001 23:03:23 +0000 (23:03 +0000)
some cleanup of the lsa_open_policy and lsa_open_policy2 parser. the
length fields are not correct but that's what NT send. We don't anymore
underflow or overflow the decoding.

added the domain admins group to the default SD.

we are now checking the desired access flag in the lsa_open_policy_X()
calls and in most functions also.

        J.F.
(This used to be commit a217c4e4ff4d13122703d22258792fe5e8e9f02f)

source3/include/rpc_lsa.h
source3/libsmb/cli_lsarpc.c
source3/rpc_parse/parse_lsa.c
source3/rpc_server/srv_lsa_nt.c

index 5ed321230e5fbada9281eff49f8a3debf55e8b23..4f72aa13161419552faae4ae23e0527a642bfc3c 100644 (file)
@@ -131,7 +131,6 @@ typedef struct seq_qos_info
        uint16 sec_imp_level; /* 0x02 - impersonation level */
        uint8  sec_ctxt_mode; /* 0x01 - context tracking mode */
        uint8  effective_only; /* 0x00 - effective only */
-       uint32 unknown;        /* 0x2000 0000 - not known */
 
 } LSA_SEC_QOS;
 
index ff4c4dfe30168889925d9d6ec511e89643c66dec..0720cadfbd418c0701b32d2080dbc51c7b7ebf41 100644 (file)
@@ -75,7 +75,7 @@ NTSTATUS cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        /* Initialise input parameters */
 
        if (sec_qos) {
-               init_lsa_sec_qos(&qos, 2, 1, 0, des_access);
+               init_lsa_sec_qos(&qos, 2, 1, 0);
                init_q_open_pol(&q, '\\', 0, des_access, &qos);
        } else {
                init_q_open_pol(&q, '\\', 0, des_access, NULL);
@@ -131,7 +131,7 @@ NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        /* Initialise input parameters */
 
        if (sec_qos) {
-               init_lsa_sec_qos(&qos, 2, 1, 0, des_access);
+               init_lsa_sec_qos(&qos, 2, 1, 0);
                init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access, 
                                  &qos);
        } else {
index 6aa696369ac9950bbc1b385ed9c5b549304ba7e7..12b0ec2e1672b7f5a852d7df77b0b9f18c1435b8 100644 (file)
@@ -138,8 +138,7 @@ static BOOL lsa_io_dom_r_ref(char *desc, DOM_R_REF *r_r, prs_struct *ps,
  Inits an LSA_SEC_QOS structure.
 ********************************************************************/
 
-void init_lsa_sec_qos(LSA_SEC_QOS *qos, uint16 imp_lev, uint8 ctxt, uint8 eff,
-                     uint32 unknown)
+void init_lsa_sec_qos(LSA_SEC_QOS *qos, uint16 imp_lev, uint8 ctxt, uint8 eff)
 {
        DEBUG(5, ("init_lsa_sec_qos\n"));
 
@@ -147,7 +146,6 @@ void init_lsa_sec_qos(LSA_SEC_QOS *qos, uint16 imp_lev, uint8 ctxt, uint8 eff,
        qos->sec_imp_level = imp_lev;
        qos->sec_ctxt_mode = ctxt;
        qos->effective_only = eff;
-       qos->unknown = unknown;
 }
 
 /*******************************************************************
@@ -178,13 +176,10 @@ static BOOL lsa_io_sec_qos(char *desc,  LSA_SEC_QOS *qos, prs_struct *ps,
                return False;
        if(!prs_uint8 ("effective_only", ps, depth, &qos->effective_only))
                return False;
-       if(!prs_uint32("unknown       ", ps, depth, &qos->unknown))
-               return False;
 
        if (qos->len != prs_offset(ps) - start) {
                DEBUG(3,("lsa_io_sec_qos: length %x does not match size %x\n",
                         qos->len, prs_offset(ps) - start));
-               return False;
        }
 
        return True;
@@ -255,7 +250,11 @@ static BOOL lsa_io_obj_attr(char *desc, LSA_OBJ_ATTR *attr, prs_struct *ps,
        }
 #endif
 
-       if (attr->ptr_sec_qos != 0 && attr->sec_qos != NULL) {
+       if (attr->ptr_sec_qos != 0) {
+               if (UNMARSHALLING(ps))
+                       if (!(attr->sec_qos = (LSA_SEC_QOS *)prs_alloc_mem(ps,sizeof(LSA_SEC_QOS))))
+                               return False;
+
                if(!lsa_io_sec_qos("sec_qos", attr->sec_qos, ps, depth))
                        return False;
        }
@@ -277,8 +276,7 @@ void init_q_open_pol(LSA_Q_OPEN_POL *r_q, uint16 system_name,
 
        r_q->ptr = 1; /* undocumented pointer */
 
-       if (qos == NULL)
-               r_q->des_access = desired_access;
+       r_q->des_access = desired_access;
 
        r_q->system_name = system_name;
        init_lsa_obj_attr(&r_q->attr, attributes, qos);
@@ -304,10 +302,8 @@ BOOL lsa_io_q_open_pol(char *desc, LSA_Q_OPEN_POL *r_q, prs_struct *ps,
        if(!lsa_io_obj_attr("", &r_q->attr, ps, depth))
                return False;
 
-       if (r_q->attr.ptr_sec_qos == 0) {
-               if(!prs_uint32("des_access", ps, depth, &r_q->des_access))
-                       return False;
-       }
+       if(!prs_uint32("des_access", ps, depth, &r_q->des_access))
+               return False;
 
        return True;
 }
@@ -344,8 +340,7 @@ void init_q_open_pol2(LSA_Q_OPEN_POL2 *r_q, char *server_name,
 
        r_q->ptr = 1; /* undocumented pointer */
 
-       if (qos == NULL)
-               r_q->des_access = desired_access;
+       r_q->des_access = desired_access;
 
        init_unistr2(&r_q->uni_server_name, server_name, 
                     strlen(server_name) + 1);
@@ -371,10 +366,8 @@ BOOL lsa_io_q_open_pol2(char *desc, LSA_Q_OPEN_POL2 *r_q, prs_struct *ps,
        if(!lsa_io_obj_attr("", &r_q->attr, ps, depth))
                return False;
 
-       if (r_q->attr.ptr_sec_qos == 0) {
-               if(!prs_uint32("des_access", ps, depth, &r_q->des_access))
-                       return False;
-       }
+       if(!prs_uint32("des_access", ps, depth, &r_q->des_access))
+               return False;
 
        return True;
 }
@@ -1608,6 +1601,9 @@ BOOL lsa_io_q_unk_get_connuser(char *desc, LSA_Q_UNK_GET_CONNUSER *q_c, prs_stru
        if(!smb_io_unistr2("uni2_srvname", &q_c->uni2_srvname, q_c->ptr_srvname, ps, depth)) /* server name to be looked up */
                return False;
 
+       if (!prs_align(ps))
+         return False;
+
        if(!prs_uint32("unk1", ps, depth, &q_c->unk1))
                return False;
        if(!prs_uint32("unk2", ps, depth, &q_c->unk2))
index d5ea156eb67d82aae9994c225aed6d57fba7b4f9..fa95e9f79f73a9b8d733bb9ef80916284cc8aab1 100644 (file)
@@ -36,6 +36,13 @@ struct lsa_info {
     uint32 access;
 };
 
+struct generic_mapping lsa_generic_mapping = {
+       POLICY_READ,
+       POLICY_WRITE,
+       POLICY_EXECUTE,
+       POLICY_ALL_ACCESS
+};
+
 /*******************************************************************
  Function to free the per handle data.
  ********************************************************************/
@@ -290,16 +297,73 @@ static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
                r_l->status = NT_STATUS_OK;
 }
 
+static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size)
+{
+       extern DOM_SID global_sid_World;
+       extern DOM_SID global_sid_Builtin;
+       DOM_SID local_adm_sid;
+       DOM_SID adm_sid;
+
+       SEC_ACE ace[3];
+       SEC_ACCESS mask;
+
+       SEC_ACL *psa = NULL;
+
+       init_sec_access(&mask, POLICY_EXECUTE);
+       init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+       sid_copy(&adm_sid, &global_sam_sid);
+       sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
+       init_sec_access(&mask, POLICY_ALL_ACCESS);
+       init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+       sid_copy(&local_adm_sid, &global_sid_Builtin);
+       sid_append_rid(&local_adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+       init_sec_access(&mask, POLICY_ALL_ACCESS);
+       init_sec_ace(&ace[2], &local_adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+       if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, &adm_sid, NULL, NULL, psa, sd_size)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       return NT_STATUS_OK;
+}
+
 /***************************************************************************
  _lsa_open_policy2.
  ***************************************************************************/
 
 NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL2 *r_u)
 {
-       /* lkclXXXX having decoded it, ignore all fields in the open policy! */
+       struct lsa_info *info;
+       SEC_DESC *psd = NULL;
+       size_t sd_size;
+       uint32 des_access=q_u->des_access;
+       uint32 acc_granted;
+       NTSTATUS status;
+
+
+       /* map the generic bits to the lsa policy ones */
+       se_map_generic(&des_access, &lsa_generic_mapping);
+
+       /* get the generic lsa policy SD until we store it */
+       lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
+
+       if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+               return status;
+
+       /* associate the domain SID with the (unique) handle. */
+       if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       ZERO_STRUCTP(info);
+       info->sid = global_sam_sid;
+       info->access = acc_granted;
 
        /* set up the LSA QUERY INFO response */
-       if (!create_policy_hnd(p, &r_u->pol, NULL, NULL))
+       if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;
@@ -311,10 +375,33 @@ NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL
 
 NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *r_u)
 {
-       /* lkclXXXX having decoded it, ignore all fields in the open policy! */
+       struct lsa_info *info;
+       SEC_DESC *psd = NULL;
+       size_t sd_size;
+       uint32 des_access=q_u->des_access;
+       uint32 acc_granted;
+       NTSTATUS status;
+
+
+       /* map the generic bits to the lsa policy ones */
+       se_map_generic(&des_access, &lsa_generic_mapping);
+
+       /* get the generic lsa policy SD until we store it */
+       lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
+
+       if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
+               return status;
+
+       /* associate the domain SID with the (unique) handle. */
+       if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       ZERO_STRUCTP(info);
+       info->sid = global_sam_sid;
+       info->access = acc_granted;
 
        /* set up the LSA QUERY INFO response */
-       if (!create_policy_hnd(p, &r_u->pol, NULL, NULL))
+       if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info))
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 
        return NT_STATUS_OK;
@@ -326,13 +413,18 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *
 
 NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
 {
+       struct lsa_info *info;
        uint32 enum_context = 0;
        char *dom_name = NULL;
        DOM_SID *dom_sid = NULL;
 
-       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 the user have enough rights */
+       if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
        /* set up the LSA QUERY INFO response */
        init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, dom_name, dom_sid,
              dom_name != NULL ? NT_STATUS_OK : NT_STATUS_NO_MORE_ENTRIES);
@@ -346,6 +438,7 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
 
 NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INFO *r_u)
 {
+       struct lsa_info *handle;
        LSA_INFO_UNION *info = &r_u->dom;
        DOM_SID domain_sid;
        char *name = NULL;
@@ -353,24 +446,32 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
 
        r_u->status = NT_STATUS_OK;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
        switch (q_u->info_class) {
        case 0x02:
                {
-                       unsigned int i;
-                       /* fake info: We audit everything. ;) */
-                       info->id2.auditing_enabled = 1;
-            info->id2.count1 = 7;
-            info->id2.count2 = 7;
-                       if ((info->id2.auditsettings = (uint32 *)talloc(p->mem_ctx,7*sizeof(uint32))) == NULL)
-                               return NT_STATUS_NO_MEMORY;
-            for (i = 0; i < 7; i++)
-                info->id2.auditsettings[i] = 3;
-            break;
+               unsigned int i;
+               /* check if the user have enough rights */
+               if (!(handle->access & POLICY_VIEW_AUDIT_INFORMATION))
+                       return NT_STATUS_ACCESS_DENIED;
+
+               /* fake info: We audit everything. ;) */
+               info->id2.auditing_enabled = 1;
+               info->id2.count1 = 7;
+               info->id2.count2 = 7;
+               if ((info->id2.auditsettings = (uint32 *)talloc(p->mem_ctx,7*sizeof(uint32))) == NULL)
+                       return NT_STATUS_NO_MEMORY;
+               for (i = 0; i < 7; i++)
+                       info->id2.auditsettings[i] = 3;
+               break;
                }
        case 0x03:
+               /* check if the user have enough rights */
+               if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+                       return NT_STATUS_ACCESS_DENIED;
+
                /* Request PolicyPrimaryDomainInformation. */
                switch (lp_server_role()) {
                        case ROLE_DOMAIN_PDC:
@@ -397,6 +498,10 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
                init_dom_query(&r_u->dom.id3, name, sid);
                break;
        case 0x05:
+               /* check if the user have enough rights */
+               if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+                       return NT_STATUS_ACCESS_DENIED;
+
                /* Request PolicyAccountDomainInformation. */
                switch (lp_server_role()) {
                        case ROLE_DOMAIN_PDC:
@@ -418,6 +523,10 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
                init_dom_query(&r_u->dom.id5, name, sid);
                break;
        case 0x06:
+               /* check if the user have enough rights */
+               if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+                       return NT_STATUS_ACCESS_DENIED;
+
                switch (lp_server_role()) {
                        case ROLE_DOMAIN_BDC:
                                /*
@@ -455,15 +564,20 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
 
 NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_SIDS *r_u)
 {
+       struct lsa_info *handle;
        DOM_SID2 *sid = q_u->sids.sid;
        int num_entries = q_u->sids.num_entries;
        DOM_R_REF *ref = NULL;
        LSA_TRANS_NAME_ENUM *names = NULL;
        uint32 mapped_count = 0;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+       if (!(handle->access & POLICY_LOOKUP_NAMES))
+               return NT_STATUS_ACCESS_DENIED;
+
        ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
        names = (LSA_TRANS_NAME_ENUM *)talloc_zero(p->mem_ctx, sizeof(LSA_TRANS_NAME_ENUM));
 
@@ -483,15 +597,20 @@ lsa_reply_lookup_names
 
 NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP_NAMES *r_u)
 {
+       struct lsa_info *handle;
        UNISTR2 *names = q_u->uni_name;
        int num_entries = q_u->num_entries;
        DOM_R_REF *ref;
        DOM_RID2 *rids;
        uint32 mapped_count = 0;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+       if (!(handle->access & POLICY_LOOKUP_NAMES))
+               return NT_STATUS_ACCESS_DENIED;
+
        ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
        rids = (DOM_RID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_RID2)*MAX_LOOKUP_SIDS);
 
@@ -533,15 +652,24 @@ _lsa_enum_privs.
 
 NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIVS *r_u)
 {
+       struct lsa_info *handle;
        uint32 i;
 
        uint32 enum_context=q_u->enum_context;
        LSA_PRIV_ENTRY *entry;
        LSA_PRIV_ENTRY *entries=NULL;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+
+       /*
+        * I don't know if it's the right one. not documented.
+        */
+       if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
        if (enum_context >= PRIV_ALL_INDEX)
                return NT_STATUS_NO_MORE_ENTRIES;
 
@@ -579,12 +707,21 @@ _lsa_priv_get_dispname.
 
 NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, LSA_R_PRIV_GET_DISPNAME *r_u)
 {
+       struct lsa_info *handle;
        fstring name_asc;
        int i=1;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+
+       /*
+        * I don't know if it's the right one. not documented.
+        */
+       if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
        unistr2_to_ascii(name_asc, &q_u->name, sizeof(name_asc));
 
        DEBUG(10,("_lsa_priv_get_dispname: %s", name_asc));
@@ -613,14 +750,23 @@ _lsa_enum_accounts.
 
 NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENUM_ACCOUNTS *r_u)
 {
+       struct lsa_info *handle;
        GROUP_MAP *map=NULL;
        int num_entries=0;
        LSA_SID_ENUM *sids=&r_u->sids;
        int i=0,j=0;
 
-       if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+
+       /*
+        * I don't know if it's the right one. not documented.
+        */
+       if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
        /* get the list of mapped groups (domain, local, builtin) */
        if(!enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
                return NT_STATUS_OK;
@@ -652,32 +798,32 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU
 
 NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA_R_UNK_GET_CONNUSER *r_u)
 {
-  fstring username, domname;
-  int ulen, dlen;
-  user_struct *vuser = get_valid_user_struct(p->vuid);
+       fstring username, domname;
+       int ulen, dlen;
+       user_struct *vuser = get_valid_user_struct(p->vuid);
   
-  if (vuser == NULL)
-    return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       if (vuser == NULL)
+               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
   
-  fstrcpy(username, vuser->user.smb_name);
-  fstrcpy(domname, vuser->user.domain);
+       fstrcpy(username, vuser->user.smb_name);
+       fstrcpy(domname, vuser->user.domain);
   
-  ulen = strlen(username) + 1;
-  dlen = strlen(domname) + 1;
+       ulen = strlen(username) + 1;
+       dlen = strlen(domname) + 1;
   
-  init_uni_hdr(&r_u->hdr_user_name, ulen);
-  r_u->ptr_user_name = 1;
-  init_unistr2(&r_u->uni2_user_name, username, ulen);
+       init_uni_hdr(&r_u->hdr_user_name, ulen);
+       r_u->ptr_user_name = 1;
+       init_unistr2(&r_u->uni2_user_name, username, ulen);
 
-  r_u->unk1 = 1;
+       r_u->unk1 = 1;
   
-  init_uni_hdr(&r_u->hdr_dom_name, dlen);
-  r_u->ptr_dom_name = 1;
-  init_unistr2(&r_u->uni2_dom_name, domname, dlen);
+       init_uni_hdr(&r_u->hdr_dom_name, dlen);
+       r_u->ptr_dom_name = 1;
+       init_unistr2(&r_u->uni2_dom_name, domname, dlen);
 
-  r_u->status = NT_STATUS_OK;
+       r_u->status = NT_STATUS_OK;
   
-  return r_u->status;
+       return r_u->status;
 }
 
 /***************************************************************************
@@ -686,14 +832,24 @@ NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA
 
 NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENACCOUNT *r_u)
 {
+       struct lsa_info *handle;
        struct lsa_info *info;
 
        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 **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+
+       /*
+        * I don't know if it's the right one. not documented.
+        * but guessed with rpcclient.
+        */
+       if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
        /* associate the user/group SID with the (unique) handle. */
        if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -919,54 +1075,39 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP
 
 NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUERY_SEC_OBJ *r_u)
 {
-       struct lsa_info *info=NULL;
-       extern DOM_SID global_sid_World;
-       extern DOM_SID global_sid_Builtin;
-       DOM_SID adm_sid;
-
-       SEC_ACE ace[2];
-       SEC_ACCESS mask;
-
-       SEC_ACL *psa = NULL;
+       struct lsa_info *handle=NULL;
        SEC_DESC *psd = NULL;
        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, (void **)&info))
+       if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
                return NT_STATUS_INVALID_HANDLE;
 
+       /* check if the user have enough rights */
+       if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+               return NT_STATUS_ACCESS_DENIED;
+
 
        switch (q_u->sec_info) {
        case 1:
                /* SD contains only the owner */
 
-               sid_copy(&adm_sid, &global_sid_Builtin);
-               sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
-               if((psd = make_sec_desc(p->mem_ctx, SEC_DESC_REVISION, &adm_sid, NULL, NULL, NULL, &sd_size)) == NULL)
+               status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
+               if(!NT_STATUS_IS_OK(status))
                        return NT_STATUS_NO_MEMORY;
 
+
                if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
                        return NT_STATUS_NO_MEMORY;
                break;
        case 4:
                /* SD contains only the ACL */
 
-               init_sec_access(&mask, POLICY_EXECUTE);
-               init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
-               sid_copy(&adm_sid, &global_sid_Builtin);
-               sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
-               init_sec_access(&mask, POLICY_ALL_ACCESS);
-               init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
-               if((psa = make_sec_acl(p->mem_ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
-                       return NT_STATUS_NO_MEMORY;
-
-               if((psd = make_sec_desc(p->mem_ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, &sd_size)) == NULL)
+               status=lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
+               if(!NT_STATUS_IS_OK(status))
                        return NT_STATUS_NO_MEMORY;
 
                if((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)