Win9x user level security.
authorMatthew Chapman <matty@samba.org>
Wed, 24 Feb 1999 01:52:30 +0000 (01:52 +0000)
committerMatthew Chapman <matty@samba.org>
Wed, 24 Feb 1999 01:52:30 +0000 (01:52 +0000)
* Added SAMR_LOOKUP_DOMAIN (-> SamrLookupDomainInSamServer)

* Added real SAMR_ENUM_DOM_GROUPS (corresponding to
SamrEnumerateGroupsInDomain). The existing one is just an alias for
SamrQueryDisplayInformation (see below).

* Added three extra info levels to SAMR_QUERY_DISPINFO. Info level 3 is
what was previously SAMR_ENUM_DOM_GROUPS; info levels 4 and 5 are
simple user/group list requests used by Win9x and I suspect (haven't
checked) the "low speed connection" User Manager.

* Added another two aliases for SAMR_QUERY_DISPINFO, opcodes 0x30 and
0x33. Usually the first is with info level 3 and the second 4 but there is
some overlap so indeed these should be implemented as just aliases.

* Return ERRDOS/ERRmoredata on extra data instead of
STATUS_BUFFER_OVERFLOW for Win95's benefit. On a named pipe this results
in an SMBreadX as usual.

Still need to fix SAMR_QUERY_DOMAIN_INFO which has a hard-coded number of
users and groups - which Win95 proceeds to truncate at.
(This used to be commit 7d03e6e21908f3a759a4e65c5edd850622335e3e)

source3/include/proto.h
source3/include/rpc_samr.h
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_samr.c
source3/rpc_server/srv_samr.c
source3/rpcclient/cmd_samr.c
source3/smbd/ipc.c

index edc087be3f5552196fbb0350dee325f3ee4c5b4a..f31d17884276ecf0a0981e8a4703fc0f8aa7e624 100644 (file)
@@ -1731,6 +1731,9 @@ BOOL samr_set_groupinfo(struct cli_state *cli, uint16 fnum,
 BOOL samr_open_domain(struct cli_state *cli, uint16 fnum, 
                                POLICY_HND *connect_pol, uint32 flags, DOM_SID *sid,
                                POLICY_HND *domain_pol);
+BOOL samr_query_lookup_domain(struct cli_state *cli, uint16 fnum, 
+                             POLICY_HND *pol, const char *dom_name,
+                             DOM_SID *dom_sid);
 BOOL samr_query_lookup_names(struct cli_state *cli, uint16 fnum, 
                                POLICY_HND *pol, uint32 flags,
                                uint32 num_names, const char **names,
@@ -2160,6 +2163,10 @@ void smb_io_rpc_auth_ntlmssp_chk(char *desc, RPC_AUTH_NTLMSSP_CHK *chk, prs_stru
 void make_samr_q_close_hnd(SAMR_Q_CLOSE_HND *q_c, POLICY_HND *hnd);
 void samr_io_q_close_hnd(char *desc,  SAMR_Q_CLOSE_HND *q_u, prs_struct *ps, int depth);
 void samr_io_r_close_hnd(char *desc,  SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int depth);
+void make_samr_q_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
+               POLICY_HND *pol, const char *dom_name);
+void samr_io_q_lookup_domain(char *desc, SAMR_Q_LOOKUP_DOMAIN *q_u, prs_struct *ps, int depth);
+void samr_io_r_lookup_domain(char *desc, SAMR_R_LOOKUP_DOMAIN *r_u, prs_struct *ps, int depth);
 void make_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
                                POLICY_HND *connect_pol, uint32 flags,
                                DOM_SID *sid);
@@ -2201,17 +2208,29 @@ void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u,
                uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status);
 void samr_io_r_enum_dom_users(char *desc,  SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth);
 void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol,
-                               uint16 switch_level, uint32 start_idx, uint32 size);
+                               uint16 switch_level, uint32 start_idx,
+                               uint32 max_entries);
 void samr_io_q_query_dispinfo(char *desc,  SAMR_Q_QUERY_DISPINFO *q_e, prs_struct *ps, int depth);
-void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask,
-               uint32 start_idx, uint32 num_sam_entries,
-               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
-void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask,
-               uint32 start_idx, uint32 num_sam_entries,
-               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_sam_dispinfo_1(SAM_DISPINFO_1 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_sam_dispinfo_2(SAM_DISPINFO_2 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_sam_dispinfo_3(SAM_DISPINFO_3 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        DOMAIN_GRP *grp);
+void make_sam_dispinfo_4(SAM_DISPINFO_4 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]);
+void make_sam_dispinfo_5(SAM_DISPINFO_5 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        DOMAIN_GRP *grp);
 void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
-               uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status);
-void samr_io_r_query_dispinfo(char *desc,  SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth);
+                               uint32 num_entries, uint32 data_size,
+                               uint16 switch_level, SAM_DISPINFO_CTR *ctr,
+                               uint32 status);
+void samr_io_r_query_dispinfo(char *desc, SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth);
 void make_samr_q_open_group(SAMR_Q_OPEN_GROUP *q_c,
                                POLICY_HND *hnd, uint32 unk, uint32 rid);
 void samr_io_q_open_group(char *desc,  SAMR_Q_OPEN_GROUP *q_u, prs_struct *ps, int depth);
@@ -2266,20 +2285,18 @@ void samr_io_q_query_groupmem(char *desc,  SAMR_Q_QUERY_GROUPMEM *q_u, prs_struc
 void make_samr_r_query_groupmem(SAMR_R_QUERY_GROUPMEM *r_u,
                uint32 num_entries, uint32 *rid, uint32 *attr, uint32 status);
 void samr_io_r_query_groupmem(char *desc,  SAMR_R_QUERY_GROUPMEM *r_u, prs_struct *ps, int depth);
-void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
-                               uint16 switch_level, uint32 start_idx, uint32 size);
-void samr_io_q_enum_dom_groups(char *desc,  SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth);
-void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
-               uint32 start_idx, uint32 num_sam_entries,
-               DOMAIN_GRP *grp,
-               uint32 status);
-void samr_io_r_enum_dom_groups(char *desc,  SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth);
 void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
                                POLICY_HND *hnd);
 void samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth);
 void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
                uint32 num_gids, DOM_GID *gid, uint32 status);
 void samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth);
+void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol, uint32 size);
+void samr_io_q_enum_dom_groups(char *desc, SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth);
+void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
+               uint32 num_sam_entries, DOMAIN_GRP *grps,
+               uint32 status);
+void samr_io_r_enum_dom_groups(char *desc, SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth);
 void make_samr_q_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_e, POLICY_HND *pol, uint32 size);
 void samr_io_q_enum_dom_aliases(char *desc,  SAMR_Q_ENUM_DOM_ALIASES *q_e, prs_struct *ps, int depth);
 void make_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u,
@@ -2432,7 +2449,8 @@ void samr_io_r_chgpasswd_user(char *desc, SAMR_R_CHGPASSWD_USER *r_u, prs_struct
 
 void init_sec_access(SEC_ACCESS *t, uint32 mask);
 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth);
-void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag);
+void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask,
+                               uint8 flag);
 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth);
 void free_sec_acl(SEC_ACL **ppsa);
 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth);
@@ -2696,6 +2714,7 @@ void cmd_reg_shutdown(struct client_info *info);
 
 void cmd_sam_ntchange_pwd(struct client_info *info);
 void cmd_sam_test(struct client_info *info);
+void cmd_sam_lookup_domain(struct client_info *info);
 void cmd_sam_del_aliasmem(struct client_info *info);
 void cmd_sam_delete_dom_alias(struct client_info *info);
 void cmd_sam_add_aliasmem(struct client_info *info);
index d70702f8a68cd239e7e9965f8ad734ea5c7a6cbc..ea6a1f7919e861497aa3d894a13a8d98d2590024 100644 (file)
@@ -81,11 +81,13 @@ SamrTestPrivateFunctionsUser
 #define SAMR_CLOSE_HND         0x01
 
 #define SAMR_UNKNOWN_3         0x03
+#define SAMR_LOOKUP_DOMAIN     0x05
 #define SAMR_OPEN_DOMAIN       0x07
 
 #define SAMR_QUERY_DOMAIN_INFO 0x08
 
 #define SAMR_CREATE_DOM_GROUP  0x0a
+#define SAMR_ENUM_DOM_GROUPS   0x0b
 #define SAMR_ENUM_DOM_USERS    0x0d
 #define SAMR_CREATE_DOM_ALIAS  0x0e
 #define SAMR_ENUM_DOM_ALIASES  0x0f
@@ -117,8 +119,11 @@ SamrTestPrivateFunctionsUser
 #define SAMR_QUERY_DISPINFO    0x28
 
 #define SAMR_UNKNOWN_2C        0x2c
-#define SAMR_ENUM_DOM_GROUPS   0x30
+#define SAMR_QUERY_DISPINFO3   0x30 /* Alias for SAMR_QUERY_DISPINFO
+                                      with info level 3 */
 #define SAMR_UNKNOWN_32        0x32
+#define SAMR_QUERY_DISPINFO4   0x33 /* Alias for SAMR_QUERY_DISPINFO
+                                      with info level 4 */
 #define SAMR_UNKNOWN_34        0x34
 
 #define SAMR_CHGPASSWD_USER    0x37
@@ -446,6 +451,28 @@ typedef struct r_samr_query_domain_info
 } SAMR_R_QUERY_DOMAIN_INFO;
 
 
+/* SAMR_Q_LOOKUP_DOMAIN - obtain SID for a local domain */
+typedef struct q_samr_lookup_domain_info
+{
+       POLICY_HND connect_pol;
+
+       UNIHDR  hdr_domain;
+       UNISTR2 uni_domain;
+
+} SAMR_Q_LOOKUP_DOMAIN;
+
+
+/* SAMR_R_LOOKUP_DOMAIN */
+typedef struct r_samr_lookup_domain_info
+{
+       uint32   ptr_sid;
+       DOM_SID2 dom_sid;
+
+       uint32 status;
+
+} SAMR_R_LOOKUP_DOMAIN;
+
+
 /****************************************************************************
 SAMR_Q_OPEN_DOMAIN - unknown_0 values seen associated with SIDs:
 
@@ -481,6 +508,7 @@ typedef struct samr_entry_info
 
 } SAM_ENTRY;
 
+
 /* SAMR_Q_ENUM_DOM_USERS - SAM rids and names */
 typedef struct q_samr_enum_dom_users_info
 {
@@ -516,37 +544,15 @@ typedef struct r_samr_enum_dom_users_info
 } SAMR_R_ENUM_DOM_USERS;
 
 
-typedef struct samr_entry_info3
-{
-       uint32 grp_idx;
-
-       uint32 rid_grp;
-       uint32 attr;
-
-       UNIHDR hdr_grp_name;
-       UNIHDR hdr_grp_desc;
-
-} SAM_ENTRY3;
-
-typedef struct samr_str_entry_info3
-{
-       UNISTR2 uni_grp_name;
-       UNISTR2 uni_grp_desc;
-
-} SAM_STR3;
-
 /* SAMR_Q_ENUM_DOM_GROUPS - SAM rids and names */
 typedef struct q_samr_enum_dom_groups_info
 {
        POLICY_HND pol;          /* policy handle */
 
-       /* these are possibly an enumeration context handle... */
-       uint16 switch_level;      /* 0x0003 */
-       uint16 unknown_0;         /* 0x0000 */
-       uint32 start_idx;       /* presumably the start enumeration index */
-       uint32 unknown_1;       /* 0x0000 07d0 */
+       /* this is possibly an enumeration context handle... */
+       uint32 unknown_0;         /* 0x0000 0000 */
 
-       uint32 max_size;        /* 0x0000 7fff */
+       uint32 max_size;              /* 0x0000 ffff */
 
 } SAMR_Q_ENUM_DOM_GROUPS;
 
@@ -554,24 +560,24 @@ typedef struct q_samr_enum_dom_groups_info
 /* SAMR_R_ENUM_DOM_GROUPS - SAM rids and names */
 typedef struct r_samr_enum_dom_groups_info
 {
-       uint32 unknown_0;        /* 0x0000 0492 or 0x0000 00be */
-       uint32 unknown_1;        /* 0x0000 049a or 0x0000 00be */
-       uint32 switch_level;     /* 0x0000 0003 */
-
        uint32 num_entries;
        uint32 ptr_entries;
 
        uint32 num_entries2;
+       uint32 ptr_entries2;
 
-       SAM_ENTRY3 sam[MAX_SAM_ENTRIES];
-       SAM_STR3   str[MAX_SAM_ENTRIES];
+       uint32 num_entries3;
+
+       SAM_ENTRY sam[MAX_SAM_ENTRIES];
+       UNISTR2 uni_grp_name[MAX_SAM_ENTRIES];
+
+       uint32 num_entries4;
 
        uint32 status;
 
 } SAMR_R_ENUM_DOM_GROUPS;
 
 
-
 /* SAMR_Q_ENUM_DOM_ALIASES - SAM rids and names */
 typedef struct q_samr_enum_dom_aliases_info
 {
@@ -584,6 +590,7 @@ typedef struct q_samr_enum_dom_aliases_info
 
 } SAMR_Q_ENUM_DOM_ALIASES;
 
+
 /* SAMR_R_ENUM_DOM_ALIASES - SAM rids and names */
 typedef struct r_samr_enum_dom_aliases_info
 {
@@ -605,20 +612,7 @@ typedef struct r_samr_enum_dom_aliases_info
 } SAMR_R_ENUM_DOM_ALIASES;
 
 
-
-/* SAMR_Q_QUERY_DISPINFO - SAM rids, names and descriptions */
-typedef struct q_samr_query_disp_info
-{
-       POLICY_HND pol;        /* policy handle */
-
-       uint16 switch_level;    /* 0x0001 and 0x0002 seen */
-       uint16 unknown_0;       /* 0x0000 and 0x2000 seen */
-       uint32 start_idx;       /* presumably the start enumeration index */
-       uint32 unknown_1;       /* 0x0000 07d0, 0x0000 0400 and 0x0000 0200 seen */
-
-       uint32 max_size;        /* 0x0000 7fff, 0x0000 7ffe and 0x0000 3fff seen*/
-
-} SAMR_Q_QUERY_DISPINFO;
+/* -- Level 1 Display Info - User Information -- */
 
 typedef struct samr_entry_info1
 {
@@ -644,15 +638,13 @@ typedef struct samr_str_entry_info1
 
 typedef struct sam_entry_info_1
 {
-       uint32 num_entries;
-       uint32 ptr_entries;
-       uint32 num_entries2;
-
        SAM_ENTRY1 sam[MAX_SAM_ENTRIES];
        SAM_STR1   str[MAX_SAM_ENTRIES];
 
+} SAM_DISPINFO_1;
 
-} SAM_INFO_1;
+
+/* -- Level 2 Display Info - Trust Account Information -- */
 
 typedef struct samr_entry_info2
 {
@@ -676,36 +668,135 @@ typedef struct samr_str_entry_info2
 
 typedef struct sam_entry_info_2
 {
-       uint32 num_entries;
-       uint32 ptr_entries;
-       uint32 num_entries2;
-
        SAM_ENTRY2 sam[MAX_SAM_ENTRIES];
        SAM_STR2   str[MAX_SAM_ENTRIES];
 
-} SAM_INFO_2;
+} SAM_DISPINFO_2;
+
 
-typedef struct sam_info_ctr_info
+/* -- Level 3 Display Info - Domain Group Information -- */
+
+typedef struct samr_entry_info3
+{
+       uint32 grp_idx;
+
+       uint32 rid_grp;
+       uint32 attr;     /* SE_GROUP_xxx, usually 7 */
+
+       UNIHDR hdr_grp_name;
+       UNIHDR hdr_grp_desc;
+
+} SAM_ENTRY3;
+
+typedef struct samr_str_entry_info3
+{
+       UNISTR2 uni_grp_name;
+       UNISTR2 uni_grp_desc;
+
+} SAM_STR3;
+
+typedef struct sam_entry_info_3
+{
+       SAM_ENTRY3 sam[MAX_SAM_ENTRIES];
+       SAM_STR3   str[MAX_SAM_ENTRIES];
+
+} SAM_DISPINFO_3;
+
+
+/* -- Level 4 Display Info - User List (ASCII) -- */
+
+typedef struct samr_entry_info4
+{
+       uint32 user_idx;
+       STRHDR hdr_acct_name;
+
+} SAM_ENTRY4;
+
+typedef struct samr_str_entry_info4
+{
+       STRING2 acct_name;
+
+} SAM_STR4;
+
+typedef struct sam_entry_info_4
+{
+       SAM_ENTRY4 sam[MAX_SAM_ENTRIES];
+       SAM_STR4   str[MAX_SAM_ENTRIES];
+
+} SAM_DISPINFO_4;
+
+
+/* -- Level 5 Display Info - Group List (ASCII) -- */
+
+typedef struct samr_entry_info5
+{
+       uint32 grp_idx;
+       STRHDR hdr_grp_name;
+
+} SAM_ENTRY5;
+
+typedef struct samr_str_entry_info5
+{
+       STRING2 grp_name;
+
+} SAM_STR5;
+
+typedef struct sam_entry_info_5
+{
+       SAM_ENTRY5 sam[MAX_SAM_ENTRIES];
+       SAM_STR5   str[MAX_SAM_ENTRIES];
+
+} SAM_DISPINFO_5;
+
+
+typedef struct sam_dispinfo_ctr_info
 {
        union
        {
-               SAM_INFO_1 *info1; /* server info */
-               SAM_INFO_2 *info2; /* user info */
+               SAM_DISPINFO_1 *info1; /* users/names/descriptions */
+               SAM_DISPINFO_2 *info2; /* trust accounts */
+               SAM_DISPINFO_3 *info3; /* domain groups/descriptions */
+               SAM_DISPINFO_4 *info4; /* user list (ASCII) - used by Win95 */
+               SAM_DISPINFO_5 *info5; /* group list (ASCII) */
                void       *info; /* allows assignment without typecasting, */
 
        } sam;
 
-} SAM_INFO_CTR;
+} SAM_DISPINFO_CTR;
+
+
+/* SAMR_Q_QUERY_DISPINFO - SAM rids, names and descriptions */
+typedef struct q_samr_query_disp_info
+{
+       POLICY_HND domain_pol;
+
+       uint16 switch_level;    /* see SAM_DISPINFO_CTR above */
+       /* align */
+
+       uint32 start_idx;       /* start enumeration index */
+       uint32 max_entries;     /* maximum number of entries to return */
+       uint32 max_size;        /* recommended data size; if exceeded server
+                                  should return STATUS_MORE_ENTRIES */
 
-/* SAMR_R_QUERY_DISPINFO - SAM rids, names and descriptions */
+} SAMR_Q_QUERY_DISPINFO;
+
+
+/* SAMR_R_QUERY_DISPINFO  */
 typedef struct r_samr_query_dispinfo_info
 {
-       uint32 unknown_0;        /* container length? 0x0000 0492 or 0x0000 00be */
-       uint32 unknown_1;        /* container length? 0x0000 049a or 0x0000 00be */
-       uint16 switch_level;     /* 0x0001 or 0x0002 */
-       /*uint8 pad[2] */
+       uint32 total_size;     /* total data size for all matching entries
+                                 (0 = uncalculated) */
+       uint32 data_size;      /* actual data size returned = size of SAM_ENTRY
+                                 structures + total length of strings */
+
+       uint16 switch_level;   /* see SAM_DISPINFO_CTR above */
+       /* align */
+
+       uint32 num_entries;    /* number of entries returned */
+       uint32 ptr_entries;
+       uint32 num_entries2;
 
-       SAM_INFO_CTR *ctr;
+       SAM_DISPINFO_CTR *ctr;
 
        uint32 status;
 
index 6791195e710c2d1971bf970f2681f587a7ad7f0f..d95bd99eac74d91ac8d16c641d33aa314c5cc434 100644 (file)
@@ -405,6 +405,7 @@ BOOL samr_chgpasswd_user(struct cli_state *cli, uint16 fnum,
        return valid_pwc;
 }
 
+
 /****************************************************************************
 do a SAMR unknown 0x38 command
 ****************************************************************************/
@@ -536,7 +537,7 @@ BOOL samr_enum_dom_groups(struct cli_state *cli, uint16 fnum,
        prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
 
        /* store the parameters */
-       make_samr_q_enum_dom_groups(&q_e, pol, 3, 0, size);
+       make_samr_q_enum_dom_groups(&q_e, pol, size);
 
        /* turn parameters into data stream */
        samr_io_q_enum_dom_groups("", &q_e, &data, 0);
@@ -561,13 +562,12 @@ BOOL samr_enum_dom_groups(struct cli_state *cli, uint16 fnum,
                {
                        int i;
                        int name_idx = 0;
-                       int desc_idx = 0;
 
                        *num_sam_groups = r_e.num_entries2;
                        if (*num_sam_groups > MAX_SAM_ENTRIES)
                        {
                                *num_sam_groups = MAX_SAM_ENTRIES;
-                               DEBUG(2,("samr_enum_dom_groups: sam user entries limited to %d\n",
+                               DEBUG(2,("samr_enum_dom_groups: sam group entries limited to %d\n",
                                          *num_sam_groups));
                        }
 
@@ -580,21 +580,16 @@ BOOL samr_enum_dom_groups(struct cli_state *cli, uint16 fnum,
 
                        for (i = 0; i < *num_sam_groups; i++)
                        {
-                               (*sam)[i].rid = r_e.sam[i].rid_grp;
+                               (*sam)[i].rid = r_e.sam[i].rid;
                                (*sam)[i].acct_name[0] = 0;
                                (*sam)[i].acct_desc[0] = 0;
-                               if (r_e.sam[i].hdr_grp_name.buffer)
+                               if (r_e.sam[i].hdr_name.buffer)
                                {
-                                       unistr2_to_ascii((*sam)[i].acct_name, &r_e.str[name_idx].uni_grp_name, sizeof((*sam)[i].acct_name)-1);
+                                       unistr2_to_ascii((*sam)[i].acct_name, &r_e.uni_grp_name[name_idx], sizeof((*sam)[i].acct_name)-1);
                                        name_idx++;
                                }
-                               if (r_e.sam[i].hdr_grp_desc.buffer)
-                               {
-                                       unistr2_to_ascii((*sam)[i].acct_desc, &r_e.str[name_idx].uni_grp_desc, sizeof((*sam)[i].acct_desc)-1);
-                                       desc_idx++;
-                               }
-                               DEBUG(5,("samr_enum_dom_groups: idx: %4d rid: %8x acct: %s desc: %s\n",
-                                         i, (*sam)[i].rid, (*sam)[i].acct_name, (*sam)[i].acct_desc));
+                               DEBUG(5,("samr_enum_dom_groups: idx: %4d rid: %8x acct: %s\n",
+                                         i, (*sam)[i].rid, (*sam)[i].acct_name));
                        }
                        valid_pol = True;
                }
@@ -1629,6 +1624,63 @@ BOOL samr_open_domain(struct cli_state *cli, uint16 fnum,
        return valid_pol;
 }
 
+/****************************************************************************
+do a SAMR Query Lookup Domain
+****************************************************************************/
+BOOL samr_query_lookup_domain(struct cli_state *cli, uint16 fnum, 
+                             POLICY_HND *pol, const char *dom_name,
+                             DOM_SID *dom_sid)
+{
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_LOOKUP_DOMAIN q_o;
+       BOOL valid_query = False;
+
+       if (pol == NULL || dom_name == NULL || dom_sid == NULL) return False;
+
+       /* create and send a MSRPC command with api SAMR_LOOKUP_DOMAIN */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       DEBUG(4,("SAMR Query Lookup Domain.\n"));
+
+       /* store the parameters */
+       make_samr_q_lookup_domain(&q_o, pol, dom_name);
+
+       /* turn parameters into data stream */
+       samr_io_q_lookup_domain("", &q_o, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, fnum, SAMR_LOOKUP_DOMAIN, &data, &rdata))
+       {
+               SAMR_R_LOOKUP_DOMAIN r_o;
+               BOOL p;
+
+               samr_io_r_lookup_domain("", &r_o, &rdata, 0);
+               p = rdata.offset != 0;
+               
+               if (p && r_o.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(0,("SAMR_R_LOOKUP_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
+                       p = False;
+               }
+
+               if (p && r_o.ptr_sid != 0)
+               {
+                       sid_copy(dom_sid, &r_o.dom_sid.sid);
+                       valid_query = True;
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return valid_query;
+}
+
 /****************************************************************************
 do a SAMR Query Lookup Names
 ****************************************************************************/
index fb9392501133fc5f3854ea5e71b52a5def7657da..0e7c891b792b902512e7e97f10621be4876d8bcf 100644 (file)
@@ -73,6 +73,66 @@ void samr_io_r_close_hnd(char *desc,  SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int
        prs_uint32("status", ps, depth, &(r_u->status));
 }
 
+/*******************************************************************
+makes a SAMR_Q_LOOKUP_DOMAIN structure.
+********************************************************************/
+void make_samr_q_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
+               POLICY_HND *pol, const char *dom_name)
+{
+       int len_name = strlen(dom_name);
+
+       if (q_u == NULL) return;
+
+       DEBUG(5,("make_samr_q_lookup_domain\n"));
+
+       memcpy(&(q_u->connect_pol), pol, sizeof(*pol));
+
+       make_uni_hdr(&(q_u->hdr_domain), len_name, len_name, 1);
+       make_unistr2(&(q_u->uni_domain), dom_name, len_name);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_q_lookup_domain(char *desc, SAMR_Q_LOOKUP_DOMAIN *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_q_lookup_domain");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("connect_pol", &(q_u->connect_pol), ps, depth);
+       prs_align(ps);
+
+       smb_io_unihdr("hdr_domain", &(q_u->hdr_domain), ps, depth);
+       smb_io_unistr2("uni_domain", &(q_u->uni_domain),
+                      q_u->hdr_domain.buffer, ps, depth);
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+void samr_io_r_lookup_domain(char *desc, SAMR_R_LOOKUP_DOMAIN *r_u, prs_struct *ps, int depth)
+{
+       if (r_u == NULL) return;
+
+       prs_debug(ps, depth, desc, "samr_io_r_lookup_domain");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("ptr", ps, depth, &(r_u->ptr_sid));
+
+       if (r_u->ptr_sid != 0)
+       {
+               smb_io_dom_sid2("sid", &(r_u->dom_sid), ps, depth);
+               prs_align(ps);
+       }
+
+       prs_uint32("status", ps, depth, &(r_u->status));
+}
 
 /*******************************************************************
 reads or writes a structure.
@@ -258,6 +318,7 @@ void samr_io_q_query_dom_info(char *desc,  SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_st
        prs_align(ps);
 }
 
+
 /*******************************************************************
 makes a structure.
 ********************************************************************/
@@ -838,6 +899,68 @@ static void sam_io_sam_entry3(char *desc,  SAM_ENTRY3 *sam, prs_struct *ps, int
        smb_io_unihdr("unihdr", &(sam->hdr_grp_desc), ps, depth); /* account name unicode string header */
 }
 
+/*******************************************************************
+makes a SAM_ENTRY4 structure.
+********************************************************************/
+static void make_sam_entry4(SAM_ENTRY4 *sam, uint32 user_idx, 
+                               uint32 len_acct_name)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry4\n"));
+
+       sam->user_idx = user_idx;
+       make_str_hdr(&(sam->hdr_acct_name), len_acct_name, len_acct_name,
+                    len_acct_name != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY4 structure.
+********************************************************************/
+static void sam_io_sam_entry4(char *desc, SAM_ENTRY4 *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry4");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("user_idx", ps, depth, &(sam->user_idx));
+       smb_io_strhdr("strhdr", &(sam->hdr_acct_name), ps, depth);
+}
+
+/*******************************************************************
+makes a SAM_ENTRY5 structure.
+********************************************************************/
+static void make_sam_entry5(SAM_ENTRY5 *sam, uint32 grp_idx, 
+                               uint32 len_grp_name)
+{
+       if (sam == NULL) return;
+
+       DEBUG(5,("make_sam_entry5\n"));
+
+       sam->grp_idx = grp_idx;
+       make_str_hdr(&(sam->hdr_grp_name), len_grp_name, len_grp_name,
+                    len_grp_name != 0);
+}
+
+/*******************************************************************
+reads or writes a SAM_ENTRY5 structure.
+********************************************************************/
+static void sam_io_sam_entry5(char *desc, SAM_ENTRY5 *sam, prs_struct *ps, int depth)
+{
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_entry5");
+       depth++;
+
+       prs_align(ps);
+
+       prs_uint32("grp_idx", ps, depth, &(sam->grp_idx));
+       smb_io_strhdr("strhdr", &(sam->hdr_grp_name), ps, depth);
+}
+
 /*******************************************************************
 makes a SAM_ENTRY structure.
 ********************************************************************/
@@ -1015,20 +1138,20 @@ void samr_io_r_enum_dom_users(char *desc,  SAMR_R_ENUM_DOM_USERS *r_u, prs_struc
 makes a SAMR_Q_QUERY_DISPINFO structure.
 ********************************************************************/
 void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol,
-                               uint16 switch_level, uint32 start_idx, uint32 size)
+                               uint16 switch_level, uint32 start_idx,
+                               uint32 max_entries)
 {
        if (q_e == NULL || pol == NULL) return;
 
        DEBUG(5,("make_samr_q_query_dispinfo\n"));
 
-       memcpy(&(q_e->pol), pol, sizeof(*pol));
+       memcpy(&(q_e->domain_pol), pol, sizeof(*pol));
 
        q_e->switch_level = switch_level;
 
-       q_e->unknown_0 = 0;
        q_e->start_idx = start_idx;
-       q_e->unknown_1 = 0x000007d0;
-       q_e->max_size  = size;
+       q_e->max_entries = max_entries;
+       q_e->max_size = 0xffff; /* Not especially useful */
 }
 
 /*******************************************************************
@@ -1043,183 +1166,370 @@ void samr_io_q_query_dispinfo(char *desc,  SAMR_Q_QUERY_DISPINFO *q_e, prs_struc
 
        prs_align(ps);
 
-       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       smb_io_pol_hnd("domain_pol", &(q_e->domain_pol), ps, depth); 
        prs_align(ps);
 
        prs_uint16("switch_level", ps, depth, &(q_e->switch_level));
-       prs_uint16("unknown_0   ", ps, depth, &(q_e->unknown_0   ));
+       prs_align(ps);
+
        prs_uint32("start_idx   ", ps, depth, &(q_e->start_idx   ));
-       prs_uint32("unknown_1   ", ps, depth, &(q_e->unknown_1   ));
+       prs_uint32("max_entries ", ps, depth, &(q_e->max_entries ));
        prs_uint32("max_size    ", ps, depth, &(q_e->max_size    ));
-
-       prs_align(ps);
 }
 
 
 /*******************************************************************
-makes a SAM_INFO_2 structure.
+makes a SAM_DISPINFO_1 structure.
 ********************************************************************/
-void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask,
-               uint32 start_idx, uint32 num_sam_entries,
-               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+void make_sam_dispinfo_1(SAM_DISPINFO_1 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+{
+       uint32 len_sam_name, len_sam_full, len_sam_desc;
+       uint32 max_entries, max_data_size;
+       uint32 dsize = 0;
+       int i;
+
+       if (sam == NULL || num_entries == NULL || data_size == NULL) return;
+
+       DEBUG(5,("make_sam_dispinfo_1\n"));
+
+       max_entries = *num_entries;
+       max_data_size = *data_size;
+
+       for (i = 0; (i < max_entries) && (dsize < max_data_size); i++)
+       {
+               len_sam_name = pass[i].uni_user_name.uni_str_len;
+               len_sam_full = pass[i].uni_full_name.uni_str_len;
+               len_sam_desc = pass[i].uni_acct_desc.uni_str_len;
+
+               make_sam_entry1(&(sam->sam[i]), start_idx + i + 1,
+                               len_sam_name, len_sam_full, len_sam_desc,
+                               pass[i].user_rid, pass[i].acb_info);
+
+               copy_unistr2(&(sam->str[i].uni_acct_name), &(pass[i].uni_user_name));
+               copy_unistr2(&(sam->str[i].uni_full_name), &(pass[i].uni_full_name));
+               copy_unistr2(&(sam->str[i].uni_acct_desc), &(pass[i].uni_acct_desc));
+
+               dsize += sizeof(SAM_ENTRY1);
+               dsize += len_sam_name + len_sam_full + len_sam_desc;
+       }
+
+       *num_entries = i;
+        *data_size = dsize;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_sam_dispinfo_1(char *desc, SAM_DISPINFO_1 *sam, uint32 num_entries, prs_struct *ps, int depth)
 {
        int i;
-       int entries_added;
 
        if (sam == NULL) return;
 
-       DEBUG(5,("make_sam_info_2\n"));
+       prs_debug(ps, depth, desc, "sam_io_sam_dispinfo_1");
+       depth++;
+
+       prs_align(ps);
 
-       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       SMB_ASSERT_ARRAY(sam->sam, num_entries);
+
+       for (i = 0; i < num_entries; i++)
        {
-               num_sam_entries = MAX_SAM_ENTRIES;
-               DEBUG(5,("limiting number of entries to %d\n", 
-                        num_sam_entries));
+               prs_grow(ps);
+               sam_io_sam_entry1("", &(sam->sam[i]), ps, depth);
        }
 
-       for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
+       for (i = 0; i < num_entries; i++)
        {
-               if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask))
-               {
-                       make_sam_entry2(&(sam->sam[entries_added]),
-                                       start_idx + entries_added + 1,
-                                       pass[i].uni_user_name.uni_str_len,
-                                       pass[i].uni_acct_desc.uni_str_len,
-                                       pass[i].user_rid,
-                                       pass[i].acb_info);
+               prs_grow(ps);
+               sam_io_sam_str1 ("", &(sam->str[i]),
+                                sam->sam[i].hdr_acct_name.buffer,
+                                sam->sam[i].hdr_user_name.buffer,
+                                sam->sam[i].hdr_user_desc.buffer,
+                                ps, depth);
+       }
+}
 
-                       copy_unistr2(&(sam->str[entries_added].uni_srv_name), &(pass[i].uni_user_name));
-                       copy_unistr2(&(sam->str[entries_added].uni_srv_desc), &(pass[i].uni_acct_desc));
 
-                       entries_added++;
-               }
+/*******************************************************************
+makes a SAM_DISPINFO_2 structure.
+********************************************************************/
+void make_sam_dispinfo_2(SAM_DISPINFO_2 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+{
+       uint32 len_sam_name, len_sam_desc;
+       uint32 max_entries, max_data_size;
+       uint32 dsize = 0;
+       int i;
+
+       if (sam == NULL || num_entries == NULL || data_size == NULL) return;
+
+       DEBUG(5,("make_sam_dispinfo_2\n"));
+
+       max_entries = *num_entries;
+       max_data_size = *data_size;
+
+       for (i = 0; (i < max_entries) && (dsize < max_data_size); i++)
+       {
+               len_sam_name = pass[i].uni_user_name.uni_str_len;
+               len_sam_desc = pass[i].uni_acct_desc.uni_str_len;
 
-               sam->num_entries   = entries_added;
-               sam->ptr_entries   = 1;
-               sam->num_entries2  = entries_added;
+               make_sam_entry2(&(sam->sam[i]), start_idx + i + 1,
+                               len_sam_name, len_sam_desc,
+                               pass[i].user_rid, pass[i].acb_info);
+
+               copy_unistr2(&(sam->str[i].uni_srv_name), &(pass[i].uni_user_name));
+               copy_unistr2(&(sam->str[i].uni_srv_desc), &(pass[i].uni_acct_desc));
+
+               dsize += sizeof(SAM_ENTRY2);
+               dsize += len_sam_name + len_sam_desc;
        }
+
+       *num_entries = i;
+        *data_size = dsize;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static void sam_io_sam_info_2(char *desc,  SAM_INFO_2 *sam, prs_struct *ps, int depth)
+static void sam_io_sam_dispinfo_2(char *desc, SAM_DISPINFO_2 *sam, uint32 num_entries, prs_struct *ps, int depth)
 {
        int i;
 
        if (sam == NULL) return;
 
-       prs_debug(ps, depth, desc, "sam_io_sam_info_2");
+       prs_debug(ps, depth, desc, "sam_io_sam_dispinfo_2");
        depth++;
 
        prs_align(ps);
 
-       prs_uint32("num_entries  ", ps, depth, &(sam->num_entries  ));
-       prs_uint32("ptr_entries  ", ps, depth, &(sam->ptr_entries  ));
-
-       prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 ));
+       SMB_ASSERT_ARRAY(sam->sam, num_entries);
 
-       SMB_ASSERT_ARRAY(sam->sam, sam->num_entries);
-
-       for (i = 0; i < sam->num_entries; i++)
+       for (i = 0; i < num_entries; i++)
        {
                prs_grow(ps);
                sam_io_sam_entry2("", &(sam->sam[i]), ps, depth);
        }
 
-       for (i = 0; i < sam->num_entries; i++)
+       for (i = 0; i < num_entries; i++)
        {
                prs_grow(ps);
                sam_io_sam_str2 ("", &(sam->str[i]),
-                                                        sam->sam[i].hdr_srv_name.buffer,
-                                                        sam->sam[i].hdr_srv_desc.buffer,
-                                                        ps, depth);
+                                sam->sam[i].hdr_srv_name.buffer,
+                                sam->sam[i].hdr_srv_desc.buffer,
+                                ps, depth);
        }
 }
 
 
 /*******************************************************************
-makes a SAM_INFO_1 structure.
+makes a SAM_DISPINFO_3 structure.
 ********************************************************************/
-void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask,
-               uint32 start_idx, uint32 num_sam_entries,
-               SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+void make_sam_dispinfo_3(SAM_DISPINFO_3 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        DOMAIN_GRP *grp)
 {
+       uint32 len_sam_name, len_sam_desc;
+       uint32 max_entries, max_data_size;
+       uint32 dsize = 0;
        int i;
-       int entries_added;
 
-       if (sam == NULL) return;
+       if (sam == NULL || num_entries == NULL || data_size == NULL) return;
 
-       DEBUG(5,("make_sam_info_1\n"));
+       DEBUG(5,("make_sam_dispinfo_3\n"));
 
-       if (num_sam_entries >= MAX_SAM_ENTRIES)
+       max_entries = *num_entries;
+       max_data_size = *data_size;
+
+       for (i = 0; (i < max_entries) && (dsize < max_data_size); i++)
        {
-               num_sam_entries = MAX_SAM_ENTRIES;
-               DEBUG(5,("limiting number of entries to %d\n", 
-                        num_sam_entries));
+               len_sam_name = strlen(grp[i].name);
+               len_sam_desc = strlen(grp[i].comment);
+
+               make_sam_entry3(&(sam->sam[i]), start_idx + i + 1,
+                               len_sam_name, len_sam_desc,
+                               grp[i].rid);
+
+               make_unistr2(&(sam->str[i].uni_grp_name), grp[i].name   , len_sam_name);
+               make_unistr2(&(sam->str[i].uni_grp_desc), grp[i].comment, len_sam_desc);
+
+               dsize += sizeof(SAM_ENTRY3);
+               dsize += (len_sam_name + len_sam_desc) * 2;
        }
 
-       for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
+       *num_entries = i;
+        *data_size = dsize;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_sam_dispinfo_3(char *desc, SAM_DISPINFO_3 *sam, int num_entries, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_dispinfo_3");
+       depth++;
+
+       prs_align(ps);
+
+       SMB_ASSERT_ARRAY(sam->sam, num_entries);
+
+       for (i = 0; i < num_entries; i++)
        {
-               if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask))
-               {
-                       make_sam_entry1(&(sam->sam[entries_added]),
-                                               start_idx + entries_added + 1,
-                                               pass[i].uni_user_name.uni_str_len,
-                                               pass[i].uni_full_name.uni_str_len, 
-                                               pass[i].uni_acct_desc.uni_str_len,
-                                               pass[i].user_rid,
-                                               pass[i].acb_info);
-
-                       copy_unistr2(&(sam->str[entries_added].uni_acct_name), &(pass[i].uni_user_name));
-                       copy_unistr2(&(sam->str[entries_added].uni_full_name), &(pass[i].uni_full_name));
-                       copy_unistr2(&(sam->str[entries_added].uni_acct_desc), &(pass[i].uni_acct_desc));
-
-                       entries_added++;
-               }
+               prs_grow(ps);
+               sam_io_sam_entry3("", &(sam->sam[i]), ps, depth);
        }
 
-       sam->num_entries   = entries_added;
-       sam->ptr_entries   = 1;
-       sam->num_entries2  = entries_added;
+       for (i = 0; i < num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_str3 ("", &(sam->str[i]),
+                                sam->sam[i].hdr_grp_name.buffer,
+                                sam->sam[i].hdr_grp_desc.buffer,
+                                ps, depth);
+       }
 }
 
 
+/*******************************************************************
+makes a SAM_DISPINFO_4 structure.
+********************************************************************/
+void make_sam_dispinfo_4(SAM_DISPINFO_4 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES])
+{
+       fstring sam_name;
+       uint32 len_sam_name;
+       uint32 max_entries, max_data_size;
+       uint32 dsize = 0;
+       int i;
+
+       if (sam == NULL || num_entries == NULL || data_size == NULL) return;
+
+       DEBUG(5,("make_sam_dispinfo_4\n"));
+
+       max_entries = *num_entries;
+       max_data_size = *data_size;
+
+       for (i = 0; (i < max_entries) && (dsize < max_data_size); i++)
+       {
+               len_sam_name = pass[i].uni_user_name.uni_str_len;
+
+               make_sam_entry4(&(sam->sam[i]), start_idx + i + 1,
+                               len_sam_name);
+
+               unistr2_to_ascii(sam_name, &(pass[i].uni_user_name), sizeof(sam_name));
+               make_string2(&(sam->str[i].acct_name), sam_name, len_sam_name);
+
+               dsize += sizeof(SAM_ENTRY4);
+               dsize += len_sam_name;
+       }
+
+       *num_entries = i;
+        *data_size = dsize;
+}
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static void sam_io_sam_info_1(char *desc,  SAM_INFO_1 *sam, prs_struct *ps, int depth)
+static void sam_io_sam_dispinfo_4(char *desc, SAM_DISPINFO_4 *sam, int num_entries, prs_struct *ps, int depth)
 {
        int i;
 
        if (sam == NULL) return;
 
-       prs_debug(ps, depth, desc, "sam_io_sam_info_1");
+       prs_debug(ps, depth, desc, "sam_io_sam_dispinfo_4");
        depth++;
 
        prs_align(ps);
 
-       prs_uint32("num_entries  ", ps, depth, &(sam->num_entries  ));
-       prs_uint32("ptr_entries  ", ps, depth, &(sam->ptr_entries  ));
+       SMB_ASSERT_ARRAY(sam->sam, num_entries);
+
+       for (i = 0; i < num_entries; i++)
+       {
+               prs_grow(ps);
+               sam_io_sam_entry4("", &(sam->sam[i]), ps, depth);
+       }
 
-       prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 ));
+       for (i = 0; i < num_entries; i++)
+       {
+               prs_grow(ps);
+               smb_io_string2("acct_name", &(sam->str[i].acct_name),
+                              sam->sam[i].hdr_acct_name.buffer, ps, depth);
+       }
+}
 
-       SMB_ASSERT_ARRAY(sam->sam, sam->num_entries);
 
-       for (i = 0; i < sam->num_entries; i++)
+/*******************************************************************
+makes a SAM_DISPINFO_5 structure.
+********************************************************************/
+void make_sam_dispinfo_5(SAM_DISPINFO_5 *sam, uint32 *num_entries,
+                        uint32 *data_size, uint32 start_idx,
+                        DOMAIN_GRP *grp)
+{
+       uint32 len_sam_name;
+       uint32 max_entries, max_data_size;
+       uint32 dsize = 0;
+       int i;
+
+       if (sam == NULL || num_entries == NULL || data_size == NULL) return;
+
+       DEBUG(5,("make_sam_dispinfo_5\n"));
+
+       max_entries = *num_entries;
+       max_data_size = *data_size;
+
+       for (i = 0; (i < max_entries) && (dsize < max_data_size); i++)
+       {
+               len_sam_name = strlen(grp[i].name);
+
+               make_sam_entry5(&(sam->sam[i]), start_idx + i + 1,
+                               len_sam_name);
+
+               make_string2(&(sam->str[i].grp_name), grp[i].name,
+                            len_sam_name);
+
+               dsize += sizeof(SAM_ENTRY5);
+               dsize += len_sam_name;
+       }
+
+       *num_entries = i;
+        *data_size = dsize;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+static void sam_io_sam_dispinfo_5(char *desc, SAM_DISPINFO_5 *sam, int num_entries, prs_struct *ps, int depth)
+{
+       int i;
+
+       if (sam == NULL) return;
+
+       prs_debug(ps, depth, desc, "sam_io_sam_dispinfo_5");
+       depth++;
+
+       prs_align(ps);
+
+       SMB_ASSERT_ARRAY(sam->sam, num_entries);
+
+       for (i = 0; i < num_entries; i++)
        {
                prs_grow(ps);
-               sam_io_sam_entry1("", &(sam->sam[i]), ps, depth);
+               sam_io_sam_entry5("", &(sam->sam[i]), ps, depth);
        }
 
-       for (i = 0; i < sam->num_entries; i++)
+       for (i = 0; i < num_entries; i++)
        {
                prs_grow(ps);
-               sam_io_sam_str1 ("", &(sam->str[i]),
-                                                        sam->sam[i].hdr_acct_name.buffer,
-                                                        sam->sam[i].hdr_user_name.buffer,
-                                                        sam->sam[i].hdr_user_desc.buffer,
-                                                        ps, depth);
+               smb_io_string2("grp_name", &(sam->str[i].grp_name),
+                              sam->sam[i].hdr_grp_name.buffer, ps, depth);
        }
 }
 
@@ -1228,25 +1538,23 @@ static void sam_io_sam_info_1(char *desc,  SAM_INFO_1 *sam, prs_struct *ps, int
 makes a SAMR_R_QUERY_DISPINFO structure.
 ********************************************************************/
 void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
-               uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status)
+                               uint32 num_entries, uint32 data_size,
+                               uint16 switch_level, SAM_DISPINFO_CTR *ctr,
+                               uint32 status)
 {
        if (r_u == NULL) return;
 
        DEBUG(5,("make_samr_r_query_dispinfo: level %d\n", switch_level));
 
-       if (status == 0x0)
-       {
-               r_u->unknown_0 = 0x0000001;
-               r_u->unknown_1 = 0x0000001;
-       }
-       else
-       {
-               r_u->unknown_0 = 0x0;
-               r_u->unknown_1 = 0x0;
-       }
+       r_u->total_size = 0; /* not calculated */
+       r_u->data_size = data_size;
 
        r_u->switch_level = switch_level;
+       r_u->num_entries = num_entries;
+       r_u->ptr_entries = 1;
+       r_u->num_entries2 = num_entries;
        r_u->ctr = ctr;
+
        r_u->status = status;
 }
 
@@ -1254,7 +1562,7 @@ void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_r_query_dispinfo(char *desc,  SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth)
+void samr_io_r_query_dispinfo(char *desc, SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth)
 {
        if (r_u == NULL) return;
 
@@ -1263,22 +1571,40 @@ void samr_io_r_query_dispinfo(char *desc,  SAMR_R_QUERY_DISPINFO *r_u, prs_struc
 
        prs_align(ps);
 
-       prs_uint32("unknown_0    ", ps, depth, &(r_u->unknown_0    ));
-       prs_uint32("unknown_1    ", ps, depth, &(r_u->unknown_1    ));
-       prs_uint16("switch_level ", ps, depth, &(r_u->switch_level ));
-
+       prs_uint32("total_size  ", ps, depth, &(r_u->total_size  ));
+       prs_uint32("data_size   ", ps, depth, &(r_u->data_size   ));
+       prs_uint16("switch_level", ps, depth, &(r_u->switch_level));
        prs_align(ps);
 
+       prs_uint32("num_entries ", ps, depth, &(r_u->num_entries ));
+       prs_uint32("ptr_entries ", ps, depth, &(r_u->ptr_entries ));
+       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+
        switch (r_u->switch_level)
        {
                case 0x1:
                {
-                       sam_io_sam_info_1("users", r_u->ctr->sam.info1, ps, depth);
+                       sam_io_sam_dispinfo_1("users", r_u->ctr->sam.info1, r_u->num_entries, ps, depth);
                        break;
                }
                case 0x2:
                {
-                       sam_io_sam_info_2("servers", r_u->ctr->sam.info2, ps, depth);
+                       sam_io_sam_dispinfo_2("servers", r_u->ctr->sam.info2, r_u->num_entries, ps, depth);
+                       break;
+               }
+               case 0x3:
+               {
+                       sam_io_sam_dispinfo_3("groups", r_u->ctr->sam.info3, r_u->num_entries, ps, depth);
+                       break;
+               }
+               case 0x4:
+               {
+                       sam_io_sam_dispinfo_4("user list", r_u->ctr->sam.info4,r_u->num_entries, ps, depth);
+                       break;
+               }
+               case 0x5:
+               {
+                       sam_io_sam_dispinfo_5("group list", r_u->ctr->sam.info5, r_u->num_entries, ps, depth);
                        break;
                }
                default:
@@ -1979,110 +2305,59 @@ void samr_io_r_query_groupmem(char *desc,  SAMR_R_QUERY_GROUPMEM *r_u, prs_struc
 
 
 /*******************************************************************
-makes a SAMR_Q_ENUM_DOM_GROUPS structure.
+makes a SAMR_Q_QUERY_USERGROUPS structure.
 ********************************************************************/
-void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
-                               uint16 switch_level, uint32 start_idx, uint32 size)
+void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
+                               POLICY_HND *hnd)
 {
-       if (q_e == NULL || pol == NULL) return;
-
-       DEBUG(5,("make_samr_q_enum_dom_groups\n"));
-
-       memcpy(&(q_e->pol), pol, sizeof(*pol));
+       if (q_u == NULL || hnd == NULL) return;
 
-       q_e->switch_level = switch_level;
+       DEBUG(5,("make_samr_q_query_usergroups\n"));
 
-       q_e->unknown_0 = 0;
-       q_e->start_idx = start_idx;
-       q_e->unknown_1 = 0x000007d0;
-       q_e->max_size  = size;
+       memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
 }
 
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_q_enum_dom_groups(char *desc,  SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth)
+void samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth)
 {
-       if (q_e == NULL) return;
+       if (q_u == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_q_enum_dom_groups");
+       prs_debug(ps, depth, desc, "samr_io_q_query_usergroups");
        depth++;
 
        prs_align(ps);
 
-       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
-       prs_align(ps);
-
-       prs_uint16("switch_level", ps, depth, &(q_e->switch_level));
-       prs_uint16("unknown_0   ", ps, depth, &(q_e->unknown_0   ));
-       prs_uint32("start_idx   ", ps, depth, &(q_e->start_idx   ));
-       prs_uint32("unknown_1   ", ps, depth, &(q_e->unknown_1   ));
-       prs_uint32("max_size    ", ps, depth, &(q_e->max_size    ));
-
+       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
        prs_align(ps);
 }
 
-
 /*******************************************************************
-makes a SAMR_R_ENUM_DOM_GROUPS structure.
+makes a SAMR_R_QUERY_USERGROUPS structure.
 ********************************************************************/
-void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
-               uint32 start_idx, uint32 num_sam_entries,
-               DOMAIN_GRP *grp,
-               uint32 status)
+void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
+               uint32 num_gids, DOM_GID *gid, uint32 status)
 {
-       int i;
-       int entries_added;
-
        if (r_u == NULL) return;
 
-       DEBUG(5,("make_samr_r_enum_dom_groups\n"));
-
-       if (num_sam_entries >= MAX_SAM_ENTRIES)
-       {
-               num_sam_entries = MAX_SAM_ENTRIES;
-               DEBUG(5,("limiting number of entries to %d\n", 
-                        num_sam_entries));
-       }
+       DEBUG(5,("make_samr_r_query_usergroups\n"));
 
        if (status == 0x0)
        {
-               for (i = start_idx, entries_added = 0; i < num_sam_entries; i++)
-               {
-                       int acct_name_len = strlen(grp[i].name);
-                       int acct_desc_len = strlen(grp[i].comment);
-
-                       make_sam_entry3(&(r_u->sam[entries_added]),
-                                       start_idx + entries_added + 1,
-                                       acct_name_len,
-                                       acct_desc_len,
-                                       grp[i].rid);
-
-                       make_unistr2(&(r_u->str[entries_added].uni_grp_name), grp[i].name   , acct_name_len);
-                       make_unistr2(&(r_u->str[entries_added].uni_grp_desc), grp[i].comment, acct_desc_len);
-
-                       entries_added++;
-               }
+               r_u->ptr_0        = 1;
+               r_u->num_entries  = num_gids;
+               r_u->ptr_1        = (num_gids != 0) ? 1 : 0;
+               r_u->num_entries2 = num_gids;
 
-               if (entries_added > 0)
-               {
-                       r_u->unknown_0 = 0x0000492;
-                       r_u->unknown_1 = 0x000049a;
-               }
-               else
-               {
-                       r_u->unknown_0 = 0x0;
-                       r_u->unknown_1 = 0x0;
-               }
-               r_u->switch_level  = 3;
-               r_u->num_entries   = entries_added;
-               r_u->ptr_entries   = 1;
-               r_u->num_entries2  = entries_added;
+               r_u->gid = gid;
        }
        else
        {
-               r_u->switch_level = 0;
+               r_u->ptr_0       = 0;
+               r_u->num_entries = 0;
+               r_u->ptr_1       = 0;
        }
 
        r_u->status = status;
@@ -2091,103 +2366,123 @@ void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_r_enum_dom_groups(char *desc,  SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth)
+void samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth)
 {
        int i;
-
        if (r_u == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_r_enum_dom_groups");
+       prs_debug(ps, depth, desc, "samr_io_r_query_usergroups");
        depth++;
 
        prs_align(ps);
 
-       prs_uint32("unknown_0    ", ps, depth, &(r_u->unknown_0    ));
-       prs_uint32("unknown_1    ", ps, depth, &(r_u->unknown_1    ));
-       prs_uint32("switch_level ", ps, depth, &(r_u->switch_level ));
+       prs_uint32("ptr_0       ", ps, depth, &(r_u->ptr_0      ));
 
-       if (r_u->switch_level != 0)
+       if (r_u->ptr_0 != 0)
        {
-               prs_uint32("num_entries  ", ps, depth, &(r_u->num_entries  ));
-               prs_uint32("ptr_entries  ", ps, depth, &(r_u->ptr_entries  ));
-
-               prs_uint32("num_entries2 ", ps, depth, &(r_u->num_entries2 ));
-
-               SMB_ASSERT_ARRAY(r_u->sam, r_u->num_entries);
+               prs_uint32("num_entries ", ps, depth, &(r_u->num_entries));
+               prs_uint32("ptr_1       ", ps, depth, &(r_u->ptr_1      ));
 
-               for (i = 0; i < r_u->num_entries; i++)
+               if (r_u->num_entries != 0)
                {
-                       prs_grow(ps);
-                       sam_io_sam_entry3("", &(r_u->sam[i]), ps, depth);
-               }
+                       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
 
-               for (i = 0; i < r_u->num_entries; i++)
-               {
-                       prs_grow(ps);
-                       sam_io_sam_str3 ("", &(r_u->str[i]),
-                                            r_u->sam[i].hdr_grp_name.buffer,
-                                            r_u->sam[i].hdr_grp_desc.buffer,
-                                            ps, depth);
+                       for (i = 0; i < r_u->num_entries2; i++)
+                       {
+                               prs_grow(ps);
+                               smb_io_gid("", &(r_u->gid[i]), ps, depth);
+                       }
                }
        }
-
        prs_uint32("status", ps, depth, &(r_u->status));
 }
 
+
 /*******************************************************************
-makes a SAMR_Q_QUERY_USERGROUPS structure.
+makes a SAMR_Q_ENUM_DOM_GROUPS structure.
 ********************************************************************/
-void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
-                               POLICY_HND *hnd)
+void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol, uint32 size)
 {
-       if (q_u == NULL || hnd == NULL) return;
+       if (q_e == NULL || pol == NULL) return;
 
-       DEBUG(5,("make_samr_q_query_usergroups\n"));
+       DEBUG(5,("make_samr_q_enum_dom_groups\n"));
 
-       memcpy(&(q_u->pol), hnd, sizeof(q_u->pol));
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->unknown_0 = 0;
+       q_e->max_size = size;
 }
 
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth)
+void samr_io_q_enum_dom_groups(char *desc, SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth)
 {
-       if (q_u == NULL) return;
+       if (q_e == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_q_query_usergroups");
+       prs_debug(ps, depth, desc, "samr_io_q_enum_dom_groups");
        depth++;
 
        prs_align(ps);
 
-       smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); 
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("unknown_0", ps, depth, &(q_e->unknown_0));
+       prs_uint32("max_size ", ps, depth, &(q_e->max_size ));
+
        prs_align(ps);
 }
 
+
 /*******************************************************************
-makes a SAMR_R_QUERY_USERGROUPS structure.
+makes a SAMR_R_ENUM_DOM_GROUPS structure.
 ********************************************************************/
-void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
-               uint32 num_gids, DOM_GID *gid, uint32 status)
+void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u,
+               uint32 num_sam_entries, DOMAIN_GRP *grps,
+               uint32 status)
 {
+       int i;
+
        if (r_u == NULL) return;
 
-       DEBUG(5,("make_samr_r_query_usergroups\n"));
+       DEBUG(5,("make_samr_r_enum_dom_groups\n"));
 
-       if (status == 0x0)
+       if (num_sam_entries >= MAX_SAM_ENTRIES)
        {
-               r_u->ptr_0        = 1;
-               r_u->num_entries  = num_gids;
-               r_u->ptr_1        = (num_gids != 0) ? 1 : 0;
-               r_u->num_entries2 = num_gids;
+               num_sam_entries = MAX_SAM_ENTRIES;
+               DEBUG(5,("limiting number of entries to %d\n", 
+                        num_sam_entries));
+       }
 
-               r_u->gid = gid;
+       r_u->num_entries  = num_sam_entries;
+
+       if (num_sam_entries > 0)
+       {
+               r_u->ptr_entries  = 1;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->ptr_entries2 = 1;
+               r_u->num_entries3 = num_sam_entries;
+
+               SMB_ASSERT_ARRAY(r_u->sam, num_sam_entries);
+
+               for (i = 0; i < num_sam_entries; i++)
+               {
+                       int acct_name_len = strlen(grps[i].name);
+
+                       make_sam_entry(&(r_u->sam[i]),
+                                       acct_name_len,
+                                       grps[i].rid);
+
+                       make_unistr2(&(r_u->uni_grp_name[i]), grps[i].name, acct_name_len);
+               }
+
+               r_u->num_entries4 = num_sam_entries;
        }
        else
        {
-               r_u->ptr_0       = 0;
-               r_u->num_entries = 0;
-               r_u->ptr_1       = 0;
+               r_u->ptr_entries = 0;
        }
 
        r_u->status = status;
@@ -2196,34 +2491,43 @@ void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-void samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth)
+void samr_io_r_enum_dom_groups(char *desc, SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth)
 {
        int i;
+
        if (r_u == NULL) return;
 
-       prs_debug(ps, depth, desc, "samr_io_r_query_usergroups");
+       prs_debug(ps, depth, desc, "samr_io_r_enum_dom_groups");
        depth++;
 
        prs_align(ps);
 
-       prs_uint32("ptr_0       ", ps, depth, &(r_u->ptr_0      ));
-
-       if (r_u->ptr_0 != 0)
+       prs_uint32("num_entries", ps, depth, &(r_u->num_entries));
+       prs_uint32("ptr_entries", ps, depth, &(r_u->ptr_entries));
+       
+       if (r_u->num_entries != 0 && r_u->ptr_entries != 0)
        {
-               prs_uint32("num_entries ", ps, depth, &(r_u->num_entries));
-               prs_uint32("ptr_1       ", ps, depth, &(r_u->ptr_1      ));
+               prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+               prs_uint32("ptr_entries2", ps, depth, &(r_u->ptr_entries2));
+               prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3));
 
-               if (r_u->num_entries != 0)
+               SMB_ASSERT_ARRAY(r_u->sam, r_u->num_entries);
+
+               for (i = 0; i < r_u->num_entries; i++)
                {
-                       prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2));
+                       sam_io_sam_entry("", &(r_u->sam[i]), ps, depth);
+               }
 
-                       for (i = 0; i < r_u->num_entries2; i++)
-                       {
-                               prs_grow(ps);
-                               smb_io_gid("", &(r_u->gid[i]), ps, depth);
-                       }
+               for (i = 0; i < r_u->num_entries; i++)
+               {
+                       smb_io_unistr2("", &(r_u->uni_grp_name[i]), r_u->sam[i].hdr_name.buffer, ps, depth);
                }
+
+               prs_align(ps);
+
+               prs_uint32("num_entries4", ps, depth, &(r_u->num_entries4));
        }
+
        prs_uint32("status", ps, depth, &(r_u->status));
 }
 
@@ -3385,10 +3689,10 @@ void samr_io_r_lookup_names(char *desc,  SAMR_R_LOOKUP_NAMES *r_u, prs_struct *p
 
        prs_uint32("num_rids1", ps, depth, &(r_u->num_rids1));
        prs_uint32("ptr_rids ", ps, depth, &(r_u->ptr_rids ));
+       prs_uint32("num_rids2", ps, depth, &(r_u->num_rids2));
 
        if (r_u->ptr_rids != 0 && r_u->num_rids1 != 0)
        {
-               prs_uint32("num_rids2", ps, depth, &(r_u->num_rids2));
                for (i = 0; i < r_u->num_rids2; i++)
                {
                        prs_grow(ps);
@@ -3399,10 +3703,10 @@ void samr_io_r_lookup_names(char *desc,  SAMR_R_LOOKUP_NAMES *r_u, prs_struct *p
 
        prs_uint32("num_types1", ps, depth, &(r_u->num_types1));
        prs_uint32("ptr_types ", ps, depth, &(r_u->ptr_types ));
+       prs_uint32("num_types2", ps, depth, &(r_u->num_types2));
 
        if (r_u->ptr_types != 0 && r_u->num_types1 != 0)
        {
-               prs_uint32("num_types2", ps, depth, &(r_u->num_types2));
                for (i = 0; i < r_u->num_types2; i++)
                {
                        prs_grow(ps);
index 449a47e4c9413ca31f83fe20f1d351b1ae2983c8..4f190270dda8c044d72a4f42638d6091c2c0f520 100644 (file)
@@ -618,7 +618,7 @@ static void api_samr_del_aliasmem( uint16 vuid, prs_struct *data, prs_struct *rd
 }
 
 /*******************************************************************
- samr_reply_add_groupmem
+ samr_reply_enum_dom_groups
  ********************************************************************/
 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
                                prs_struct *rdata)
@@ -626,7 +626,6 @@ static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
        SAMR_R_ENUM_DOM_GROUPS r_e;
        DOMAIN_GRP *grps = NULL;
        int num_entries = 0;
-       BOOL got_grps = False;
        DOM_SID sid;
        fstring sid_str;
 
@@ -646,21 +645,19 @@ static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
        if (sid_equal(&sid, &global_sam_sid))
        {
                BOOL ret;
-               got_grps = True;
 
                become_root(True);
                ret = enumdomgroups(&grps, &num_entries);
                unbecome_root(True);
-
                if (!ret)
                {
                        r_e.status = 0xC0000000 | NT_STATUS_NO_MEMORY;
                }
        }
 
-       if (r_e.status == 0 && got_grps)
+       if (r_e.status == 0x0)
        {
-               make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, grps, r_e.status);
+               make_samr_r_enum_dom_groups(&r_e, num_entries, grps, r_e.status);
        }
 
        /* store the response in the SMB stream */
@@ -675,12 +672,16 @@ static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
 }
 
 /*******************************************************************
- api_samr_enum_dom_groups
+ api_samr_enum_dom_aliases
  ********************************************************************/
 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
 {
        SAMR_Q_ENUM_DOM_GROUPS q_e;
+
+       /* grab the samr open */
        samr_io_q_enum_dom_groups("", &q_e, data, 0);
+
+       /* construct reply. */
        samr_reply_enum_dom_groups(&q_e, rdata);
 }
 
@@ -777,72 +778,154 @@ static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
                                prs_struct *rdata)
 {
        SAMR_R_QUERY_DISPINFO r_e;
-       SAM_INFO_CTR ctr;
-       SAM_INFO_1 info1;
-       SAM_INFO_2 info2;
+       SAM_DISPINFO_CTR ctr;
        SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
+       DOMAIN_GRP *grps = NULL;
+       DOMAIN_GRP *sam_grps = NULL;
+       uint32 data_size = 0;
+       uint32 status = 0x0;
+       uint16 acb_mask = ACB_NORMAL;
+       int num_sam_entries = 0;
        int num_entries = 0;
-       int total_entries = 0;
-       BOOL got_pwds;
-       uint16 switch_level = 0x0;
-
-       ZERO_STRUCT(r_e);
-
-       r_e.status = 0x0;
+       int total_entries;
 
        DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
 
        /* find the policy handle.  open a policy on it. */
-       if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
+       if (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1)
        {
-               r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+               status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
                DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
        }
 
-       if (r_e.status == 0x0)
+       if (status == 0x0)
        {
                become_root(True);
-               got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
-               unbecome_root(True);
 
+               /* Get what we need from the password database */
                switch (q_u->switch_level)
                {
+                       case 0x2:
+                       {
+                               acb_mask = ACB_WSTRUST;
+                               /* Fall through */
+                       }
                        case 0x1:
+                       case 0x4:
+                       {
+                               get_sampwd_entries(pass, q_u->start_idx,
+                                             &total_entries, &num_sam_entries,
+                                             MAX_SAM_ENTRIES, acb_mask);
+                               break;
+                       }
+                       case 0x3:
+                       case 0x5:
                        {
-                       
-                               /* query disp info is for users */
-                               switch_level = 0x1;
-                               make_sam_info_1(&info1, ACB_NORMAL,
-                                       q_u->start_idx, num_entries, pass);
+                               enumdomgroups(&sam_grps, &num_sam_entries);
+
+                               if (q_u->start_idx < num_sam_entries) {
+                                       grps = sam_grps + q_u->start_idx;
+                                       num_sam_entries -= q_u->start_idx;
+                               } else {
+                                       num_sam_entries = 0;
+                               }
+                               break;
+                       }
+               }
+
+               unbecome_root(True);
+
+               num_entries = num_sam_entries;
+
+               if (num_entries > q_u->max_entries)
+               {
+                       num_entries = q_u->max_entries;
+               }
+
+               if (num_entries > MAX_SAM_ENTRIES)
+               {
+                       num_entries = MAX_SAM_ENTRIES;
+                       DEBUG(5,("limiting number of entries to %d\n", 
+                                num_entries));
+               }
 
-                               ctr.sam.info1 = &info1;
+               data_size = q_u->max_size;
 
+               /* Now create reply structure */
+               switch (q_u->switch_level)
+               {
+                       case 0x1:
+                       {
+                               ctr.sam.info1 = malloc(sizeof(SAM_DISPINFO_1));
+                               make_sam_dispinfo_1(ctr.sam.info1,
+                                                   &num_entries, &data_size,
+                                                   q_u->start_idx, pass);
                                break;
                        }
                        case 0x2:
                        {
-                               /* query disp info is for servers */
-                               switch_level = 0x2;
-                               make_sam_info_2(&info2, ACB_WSTRUST,
-                                       q_u->start_idx, num_entries, pass);
-
-                               ctr.sam.info2 = &info2;
-
+                               ctr.sam.info2 = malloc(sizeof(SAM_DISPINFO_2));
+                               make_sam_dispinfo_2(ctr.sam.info2,
+                                                   &num_entries, &data_size,
+                                                   q_u->start_idx, pass);
+                               break;
+                       }
+                       case 0x3:
+                       {
+                               ctr.sam.info3 = malloc(sizeof(SAM_DISPINFO_3));
+                               make_sam_dispinfo_3(ctr.sam.info3,
+                                                   &num_entries, &data_size,
+                                                   q_u->start_idx, grps);
+                               break;
+                       }
+                       case 0x4:
+                       {
+                               ctr.sam.info4 = malloc(sizeof(SAM_DISPINFO_4));
+                               make_sam_dispinfo_4(ctr.sam.info4,
+                                                   &num_entries, &data_size,
+                                                   q_u->start_idx, pass);
+                               break;
+                       }
+                       case 0x5:
+                       {
+                               ctr.sam.info5 = malloc(sizeof(SAM_DISPINFO_5));
+                               make_sam_dispinfo_5(ctr.sam.info5,
+                                                   &num_entries, &data_size,
+                                                   q_u->start_idx, grps);
+                               break;
+                       }
+                       default:
+                       {
+                               ctr.sam.info = NULL;
+                               status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
                                break;
                        }
                }
        }
 
-       if (r_e.status == 0 && got_pwds)
+       if ((status == 0) && (num_entries < num_sam_entries))
        {
-               make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
+               status = 0x105; /* STATUS_MORE_ENTRIES */
        }
 
+       make_samr_r_query_dispinfo(&r_e, num_entries, data_size,
+                                  q_u->switch_level, &ctr, status);
+
        /* store the response in the SMB stream */
        samr_io_r_query_dispinfo("", &r_e, rdata, 0);
 
-       DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
+       /* free malloc'd areas */
+       if (sam_grps != NULL)
+       {
+               free(sam_grps);
+       }
 
+       if (ctr.sam.info != NULL)
+       {
+               free(ctr.sam.info);
+       }
+
+       DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
 }
 
 /*******************************************************************
@@ -852,10 +935,7 @@ static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *
 {
        SAMR_Q_QUERY_DISPINFO q_e;
 
-       /* grab the samr open */
        samr_io_q_query_dispinfo("", &q_e, data, 0);
-
-       /* construct reply. */
        samr_reply_query_dispinfo(&q_e, rdata);
 }
 
@@ -2537,6 +2617,64 @@ static void api_samr_open_group( uint16 vuid, prs_struct *data, prs_struct *rdat
        samr_reply_open_group(&q_u, rdata);
 }
 
+/*******************************************************************
+ samr_reply_lookup_domain
+ ********************************************************************/
+static void samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN *q_u,
+                               prs_struct *rdata)
+{
+       SAMR_R_LOOKUP_DOMAIN r_u;
+       fstring domain;
+
+       DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
+
+       r_u.ptr_sid = 0;
+       r_u.status = 0x0;
+
+       /* find the connection policy handle */
+       if (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1)
+       {
+               r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
+       }
+
+       if (r_u.status == 0x0)
+        {
+               unistr2_to_ascii(domain, &(q_u->uni_domain), sizeof(domain));
+               DEBUG(5, ("Lookup Domain: %s\n", domain));
+
+               /* check it's one of ours */
+               if (strequal(domain, global_sam_name))
+               {
+                       make_dom_sid2(&(r_u.dom_sid), &global_sam_sid);
+                       r_u.ptr_sid = 1;
+               }
+               else if (strequal(domain, "BUILTIN"))
+               {
+                       make_dom_sid2(&(r_u.dom_sid), &global_sid_S_1_5_20);
+                       r_u.ptr_sid = 1;
+               }
+               else
+               {
+                       r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_DOMAIN;
+               }
+       }
+
+       /* store the response in the SMB stream */
+       samr_io_r_lookup_domain("", &r_u, rdata, 0);
+
+       DEBUG(5,("samr_lookup_domain: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ api_samr_lookup_domain
+ ********************************************************************/
+static void api_samr_lookup_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
+{
+       SAMR_Q_LOOKUP_DOMAIN q_u;
+       samr_io_q_lookup_domain("", &q_u, data, 0);
+       samr_reply_lookup_domain(&q_u, rdata);
+}
+
 /*******************************************************************
  array of \PIPE\samr operations
  ********************************************************************/
@@ -2565,6 +2703,8 @@ static struct api_struct api_samr_cmds [] =
        { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info   },
        { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
        { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
+       { "SAMR_QUERY_DISPINFO3"  , SAMR_QUERY_DISPINFO3  , api_samr_query_dispinfo   },
+       { "SAMR_QUERY_DISPINFO4"  , SAMR_QUERY_DISPINFO4  , api_samr_query_dispinfo   },
        { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
        { "SAMR_QUERY_GROUPINFO"  , SAMR_QUERY_GROUPINFO  , api_samr_query_groupinfo  },
        { "SAMR_0x32"             , SAMR_UNKNOWN_32       , api_samr_unknown_32       },
@@ -2574,6 +2714,7 @@ static struct api_struct api_samr_cmds [] =
        { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
        { "SAMR_OPEN_GROUP"       , SAMR_OPEN_GROUP       , api_samr_open_group       },
        { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
+       { "SAMR_LOOKUP_DOMAIN"    , SAMR_LOOKUP_DOMAIN    , api_samr_lookup_domain    },
        { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
        { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
        { NULL                    , 0                     , NULL                      }
index 852521d850e6dc92ffaa9da34bec7dca61bfe794..7204411dd5d249d3a315113d3f623986594dc9bf 100644 (file)
@@ -173,6 +173,62 @@ void cmd_sam_test(struct client_info *info)
        }
 }
 
+/****************************************************************************
+Lookup domain in SAM server.
+****************************************************************************/
+void cmd_sam_lookup_domain(struct client_info *info)
+{
+       uint16 fnum;
+       fstring srv_name;
+       fstring domain;
+       fstring str_sid;
+       DOM_SID dom_sid;
+       BOOL res = True;
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       if (!next_token(NULL, domain, NULL, sizeof(domain)))
+       {
+               fprintf(out_hnd, "lookupdomain: <name>\n");
+               return;
+       }
+
+       fprintf(out_hnd, "Lookup Domain in SAM Server\n");
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_SAMR, &fnum) : False;
+
+       /* establish a connection. */
+       res = res ? samr_connect(smb_cli, fnum, 
+                               srv_name, 0x00000020,
+                               &info->dom.samr_pol_connect) : False;
+
+       /* connect to the domain */
+       res = res ? samr_query_lookup_domain(smb_cli, fnum, 
+                   &info->dom.samr_pol_connect, domain, &dom_sid) : False;
+
+       res = res ? samr_close(smb_cli, fnum, &info->dom.samr_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli, fnum);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_sam_lookup_domain: succeeded\n"));
+
+               sid_to_string(str_sid, &dom_sid);
+               fprintf(out_hnd, "%s SID: %s\n", domain, str_sid);
+               fprintf(out_hnd, "Lookup Domain: OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_sam_lookup_domain: failed\n"));
+               fprintf(out_hnd, "Lookup Domain: FAILED\n");
+       }
+}
+
 /****************************************************************************
 SAM delete alias member.
 ****************************************************************************/
@@ -359,7 +415,6 @@ void cmd_sam_delete_dom_alias(struct client_info *info)
        }
 }
 
-
 /****************************************************************************
 SAM add alias member.
 ****************************************************************************/
@@ -1444,7 +1499,7 @@ void cmd_sam_query_dominfo(struct client_info *info)
 
 
 /****************************************************************************
-experimental SAM aliases query.
+SAM aliases query.
 ****************************************************************************/
 void cmd_sam_enum_aliases(struct client_info *info)
 {
@@ -1606,7 +1661,7 @@ void cmd_sam_enum_aliases(struct client_info *info)
        cli_nt_session_close(smb_cli, fnum);
 
        if (info->dom.sam != NULL)
-                       {
+       {
                free(info->dom.sam);
        }
 
@@ -1615,14 +1670,13 @@ void cmd_sam_enum_aliases(struct client_info *info)
                DEBUG(5,("cmd_sam_enum_aliases: succeeded\n"));
        }
        else
-                               {
+       {
                DEBUG(5,("cmd_sam_enum_aliases: failed\n"));
-                               }
-                       }
-
+       }
+}
 
 /****************************************************************************
-experimental SAM groups query.
+SAM groups query.
 ****************************************************************************/
 void cmd_sam_enum_groups(struct client_info *info)
 {
@@ -1633,22 +1687,20 @@ void cmd_sam_enum_groups(struct client_info *info)
        DOM_SID sid1;
        BOOL res = True;
        BOOL request_member_info = False;
-       uint32 flags = 0x304; /* absolutely no idea. */
+       uint32 flags = 0x200003f3; /* absolutely no idea. */
        fstring tmp;
        uint32 group_idx;
 
-       sid_to_string(sid, &info->dom.level3_sid);
-       fstrcpy(domain, info->dom.level3_dom);
-#if 0
-       fstrcpy(sid   , "S-1-5-20");
-#endif
-       if (strlen(sid) == 0)
+       sid_copy(&sid1, &info->dom.level3_sid);
+
+       if (sid1.num_auths == 0)
        {
                fprintf(out_hnd, "please use 'lsaquery' first, to ascertain the SID\n");
                return;
-               }
+       }
 
-       string_to_sid(&sid1, sid);
+       sid_to_string(sid, &sid1);
+       fstrcpy(domain, info->dom.level3_dom);
 
        fstrcpy(srv_name, "\\\\");
        fstrcat(srv_name, info->dest_host);
@@ -1670,7 +1722,7 @@ void cmd_sam_enum_groups(struct client_info *info)
        /* establish a connection. */
        res = res ? samr_connect(smb_cli, fnum,
                                srv_name, 0x00000020,
-                   &info->dom.samr_pol_connect) : False;
+                               &info->dom.samr_pol_connect) : False;
 
        /* connect to the domain */
        res = res ? samr_open_domain(smb_cli, fnum,
@@ -1695,39 +1747,45 @@ void cmd_sam_enum_groups(struct client_info *info)
        {
                uint32 group_rid = info->dom.sam[group_idx].rid;
 
-               fprintf(out_hnd, "Group RID: %8x  Group Name: %s Description: %s\n",
+               fprintf(out_hnd, "Group RID: %8x  Group Name: %s\n",
                                  group_rid,
-                                 info->dom.sam[group_idx].acct_name,
-                                 info->dom.sam[group_idx].acct_desc);
+                                 info->dom.sam[group_idx].acct_name);
 
                if (request_member_info)
                {
-                       uint32 num_groups;
-                       uint32 num_names;
+                       uint32 num_mem;
+                       uint32 rid_mem[MAX_LOOKUP_SIDS];
                        uint32 attr_mem[MAX_LOOKUP_SIDS];
-                       uint32 rid_mem [MAX_LOOKUP_SIDS];
-                       fstring name[MAX_LOOKUP_SIDS];
-                       uint32  type[MAX_LOOKUP_SIDS];
 
-                       /* send user groups query */
+                       /* get group members */
                        if (get_samr_query_groupmem(smb_cli, fnum, 
-                                               &info->dom.samr_pol_open_domain,
-                                               group_rid, &num_groups,
-                                               rid_mem, attr_mem) &&
-                           samr_query_lookup_rids(smb_cli, fnum, 
-                                               &info->dom.samr_pol_open_domain, 0x3e8,
-                                               num_groups, rid_mem, 
-                                               &num_names, name, type))
+                               &info->dom.samr_pol_open_domain,
+                               group_rid, &num_mem, rid_mem, attr_mem))
                        {
-                               display_group_members(out_hnd, ACTION_HEADER   , num_names, name, type);
-                               display_group_members(out_hnd, ACTION_ENUMERATE, num_names, name, type);
-                               display_group_members(out_hnd, ACTION_FOOTER   , num_names, name, type);
+                               BOOL res3 = True;
+                               int num_names = 0;
+                               fstring names[MAX_LOOKUP_SIDS];
+                               uint32 types[MAX_LOOKUP_SIDS];
+
+                               res3 = samr_query_lookup_rids(smb_cli, fnum,
+                                      &info->dom.samr_pol_open_domain, 1000,
+                                      num_mem, rid_mem, &num_names, names, types);
+
+                               if (res3)
+                               {
+                                       display_group_members(out_hnd, ACTION_HEADER   , num_names, names, types);
+                                       display_group_members(out_hnd, ACTION_ENUMERATE, num_names, names, types);
+                                       display_group_members(out_hnd, ACTION_FOOTER   , num_names, names, types);
+                               }
                        }
                }
        }
 
-       res = res ? samr_close(smb_cli, fnum, &info->dom.samr_pol_connect) : False;
-       res = res ? samr_close(smb_cli, fnum, &info->dom.samr_pol_open_domain) : False;
+       res = res ? samr_close(smb_cli, fnum,
+                   &info->dom.samr_pol_open_domain) : False;
+
+       res = res ? samr_close(smb_cli, fnum, 
+                   &info->dom.samr_pol_connect) : False;
 
        /* close the session */
        cli_nt_session_close(smb_cli, fnum);
@@ -1746,5 +1804,3 @@ void cmd_sam_enum_groups(struct client_info *info)
                DEBUG(5,("cmd_sam_enum_groups: failed\n"));
        }
 }
-
-
index 31ae8e6fc02a84db7ac29dbc3b07c238ec71f47a..c8c3b521944d66e06b0c02fe2a44fe48ca0a63f9 100644 (file)
@@ -187,9 +187,13 @@ static void send_trans_reply(char *outbuf,
 
        if (buffer_too_large)
        {
+#if 0
                /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
                SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
                SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
+#endif
+               SCVAL(outbuf, smb_rcls, ERRDOS);
+               SSVAL(outbuf, smb_err, ERRmoredata);
        }
 
        copy_trans_params_and_data(outbuf, align,