added rpcclient "enumdomains" command. enumerates names of domains
authorLuke Leighton <lkcl@samba.org>
Mon, 15 Nov 1999 22:43:08 +0000 (22:43 +0000)
committerLuke Leighton <lkcl@samba.org>
Mon, 15 Nov 1999 22:43:08 +0000 (22:43 +0000)
for which a PDC is responsible.  typical answers are:
<Name of Domain> plus <Builtin>.

against a hierarchical, down-level-compatible NT5 PDC, there's likely to
be more than these two entries!!!!!
(This used to be commit 3146aa6b6049a0d996e9abbe7dbee8526550e7e0)

source3/include/ntdomain.h
source3/include/proto.h
source3/include/rpc_samr.h
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_samr.c
source3/rpcclient/cmd_samr.c
source3/rpcclient/rpcclient.c

index 7f5887447524d8bb4c105e6e23ffcb38c1930894..4f6cc85905eff8631064dd21af0bde0903dbf3ff 100644 (file)
@@ -170,6 +170,9 @@ struct acct_info
                  uint32, const uint32*, char *const *const,\
                  uint32*const)
 
+#define DOMAIN_FN(fn)\
+       void (*fn)(const char*)
+
 #define USER_FN(fn)\
        void (*fn)(const char*, const DOM_SID*, uint32, const char*)
 #define USER_INFO_FN(fn)\
index df05f2d7be135d1ee720a48587fa329f4048f064..ff553314007041f80e40ff031d2bf70071256391 100644 (file)
@@ -1952,6 +1952,11 @@ BOOL samr_unknown_38(struct cli_state *cli, uint16 fnum, char *srv_name);
 BOOL samr_query_dom_info(struct cli_state *cli, uint16 fnum, 
                                POLICY_HND *domain_pol, uint16 switch_value,
                                SAM_UNK_CTR *ctr);
+uint32 samr_enum_domains(struct cli_state *cli, uint16 fnum, 
+                               POLICY_HND *pol,
+                               uint32 *start_idx, uint32 size,
+                               struct acct_info **sam,
+                               uint32 *num_sam_domains);
 uint32 samr_enum_dom_groups(struct cli_state *cli, uint16 fnum, 
                                POLICY_HND *pol,
                                uint32 *start_idx, uint32 size,
@@ -2703,6 +2708,13 @@ BOOL samr_io_q_query_usergroups(char *desc,  SAMR_Q_QUERY_USERGROUPS *q_u, prs_s
 BOOL make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u,
                uint32 num_gids, DOM_GID *gid, uint32 status);
 BOOL samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth);
+BOOL make_samr_q_enum_domains(SAMR_Q_ENUM_DOMAINS *q_e, POLICY_HND *pol,
+                               uint32 start_idx, uint32 size);
+BOOL samr_io_q_enum_domains(char *desc, SAMR_Q_ENUM_DOMAINS *q_e, prs_struct *ps, int depth);
+BOOL make_samr_r_enum_domains(SAMR_R_ENUM_DOMAINS *r_u,
+               uint32 next_idx,
+               uint32 num_sam_entries, char **doms, uint32 status);
+BOOL samr_io_r_enum_domains(char *desc, SAMR_R_ENUM_DOMAINS *r_u, prs_struct *ps, int depth);
 BOOL make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
                                uint32 start_idx, uint32 size);
 BOOL samr_io_q_enum_dom_groups(char *desc, SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth);
@@ -3428,6 +3440,11 @@ BOOL sam_query_groupmem(struct cli_state *cli, uint16 fnum,
                                uint32 **rid_mem,
                                char ***name,
                                uint32 **type);
+uint32 msrpc_sam_enum_domains(struct cli_state *cli,
+                               const char* srv_name,
+                               struct acct_info **sam,
+                               uint32 *num_sam_entries,
+                               DOMAIN_FN(dom_fn));
 uint32 msrpc_sam_enum_groups(struct cli_state *cli,
                                const char* domain,
                                const DOM_SID *sid1,
@@ -3469,6 +3486,7 @@ void cmd_sam_query_aliasmem(struct client_info *info);
 void cmd_sam_query_alias(struct client_info *info);
 void cmd_sam_enum_aliases(struct client_info *info);
 void cmd_sam_enum_groups(struct client_info *info);
+void cmd_sam_enum_domains(struct client_info *info);
 
 /*The following definitions come from  rpcclient/cmd_spoolss.c  */
 
index 58246488a1ae5a6977a2f64d5fc2a56460f1e6f1..850e3a8b948e561637a7f33a77d8e9472cce972c 100644 (file)
@@ -83,6 +83,7 @@ SamrTestPrivateFunctionsUser
 #define SAMR_QUERY_SEC_OBJECT  0x03
 #define SAMR_LOOKUP_DOMAIN     0x05
 #define SAMR_OPEN_DOMAIN       0x07
+#define SAMR_ENUM_DOMAINS      0x06
 
 #define SAMR_QUERY_DOMAIN_INFO 0x08
 
@@ -586,7 +587,6 @@ typedef struct r_samr_open_domain_info
 
 } SAMR_R_OPEN_DOMAIN;
 
-
 #define MAX_SAM_ENTRIES 250
 
 typedef struct samr_entry_info
@@ -597,6 +597,36 @@ typedef struct samr_entry_info
 } SAM_ENTRY;
 
 
+/* SAMR_Q_ENUM_DOMAINS - SAM rids and names */
+typedef struct q_samr_enum_domains_info
+{
+       POLICY_HND pol;     /* policy handle */
+
+       uint32 start_idx;   /* enumeration handle */
+       uint32 max_size;    /* 0x0000 ffff */
+
+} SAMR_Q_ENUM_DOMAINS;
+
+/* SAMR_R_ENUM_DOMAINS - SAM rids and Domain names */
+typedef struct r_samr_enum_domains_info
+{
+       uint32 next_idx;     /* next starting index required for enum */
+       uint32 ptr_entries1;  
+
+       uint32 num_entries2;
+       uint32 ptr_entries2;
+
+       uint32 num_entries3;
+
+       SAM_ENTRY *sam;
+       UNISTR2 *uni_dom_name;
+
+       uint32 num_entries4;
+
+       uint32 status;
+
+} SAMR_R_ENUM_DOMAINS;
+
 /* SAMR_Q_ENUM_DOM_USERS - SAM rids and names */
 typedef struct q_samr_enum_dom_users_info
 {
index 94865e4d3c911e1d8396242c64e3c5f35a1ae64e..d16098247f499a46c2fe0d307851a999232851d1 100644 (file)
@@ -615,6 +615,108 @@ BOOL samr_query_dom_info(struct cli_state *cli, uint16 fnum,
        return valid_un8;
 }
 
+/****************************************************************************
+do a SAMR enumerate Domains
+****************************************************************************/
+uint32 samr_enum_domains(struct cli_state *cli, uint16 fnum, 
+                               POLICY_HND *pol,
+                               uint32 *start_idx, uint32 size,
+                               struct acct_info **sam,
+                               uint32 *num_sam_domains)
+{
+       uint32 status = 0x0;
+       prs_struct data;
+       prs_struct rdata;
+
+       SAMR_Q_ENUM_DOMAINS q_e;
+
+       DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
+
+       if (pol == NULL || num_sam_domains == NULL || sam == NULL)
+       {
+               return NT_STATUS_INVALID_PARAMETER | 0xC0000000;
+       }
+
+       /* create and send a MSRPC command with api SAMR_ENUM_DOMAINS */
+
+       prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+       prs_init(&rdata, 0   , 4, SAFETY_MARGIN, True );
+
+       /* store the parameters */
+       make_samr_q_enum_domains(&q_e, pol, *start_idx, size);
+
+       /* turn parameters into data stream */
+       samr_io_q_enum_domains("", &q_e, &data, 0);
+
+       /* send the data on \PIPE\ */
+       if (rpc_api_pipe_req(cli, fnum, SAMR_ENUM_DOMAINS, &data, &rdata))
+       {
+               SAMR_R_ENUM_DOMAINS r_e;
+               BOOL p;
+
+               samr_io_r_enum_domains("", &r_e, &rdata, 0);
+
+               status = r_e.status;
+               p = rdata.offset != 0;
+               if (p && r_e.status != 0)
+               {
+                       /* report error code */
+                       DEBUG(4,("SAMR_R_ENUM_DOMAINS: %s\n", get_nt_error_msg(r_e.status)));
+                       p = (r_e.status == STATUS_MORE_ENTRIES);
+               }
+
+               if (p)
+               {
+                       uint32 i = (*num_sam_domains);
+                       uint32 j = 0;
+                       uint32 name_idx = 0;
+
+                       (*num_sam_domains) += r_e.num_entries2;
+                       (*sam) = (struct acct_info*) Realloc((*sam),
+                              sizeof(struct acct_info) * (*num_sam_domains));
+                                   
+                       if ((*sam) == NULL)
+                       {
+                               (*num_sam_domains) = 0;
+                               i = 0;
+                       }
+
+                       for (j = 0; i < (*num_sam_domains) && j < r_e.num_entries2; j++, i++)
+                       {
+                               (*sam)[i].rid = r_e.sam[j].rid;
+                               (*sam)[i].acct_name[0] = 0;
+                               (*sam)[i].acct_desc[0] = 0;
+                               if (r_e.sam[j].hdr_name.buffer)
+                               {
+                                       unistr2_to_ascii((*sam)[i].acct_name, &r_e.uni_dom_name[name_idx], sizeof((*sam)[i].acct_name)-1);
+                                       name_idx++;
+                               }
+                               DEBUG(5,("samr_enum_domains: idx: %4d rid: %8x acct: %s\n",
+                                         i, (*sam)[i].rid, (*sam)[i].acct_name));
+                       }
+                       (*start_idx) = r_e.next_idx;
+               }
+               else if (status == 0x0)
+               {
+                       status = NT_STATUS_INVALID_PARAMETER | 0xC0000000;
+               }
+
+               if (r_e.sam != NULL)
+               {
+                       free(r_e.sam);
+               }
+               if (r_e.uni_dom_name != NULL)
+               {
+                       free(r_e.uni_dom_name);
+               }
+       }
+
+       prs_mem_free(&data   );
+       prs_mem_free(&rdata  );
+
+       return status;
+}
+
 /****************************************************************************
 do a SAMR enumerate groups
 ****************************************************************************/
index 2cd796f874b2c606a520088b0c2665a2069aeadd..ab45152db0e2ccfeead275ab4f49a9e3a3a82dad 100644 (file)
@@ -2755,6 +2755,166 @@ BOOL samr_io_r_query_usergroups(char *desc,  SAMR_R_QUERY_USERGROUPS *r_u, prs_s
 }
 
 
+/*******************************************************************
+makes a SAMR_Q_ENUM_DOMAINS structure.
+********************************************************************/
+BOOL make_samr_q_enum_domains(SAMR_Q_ENUM_DOMAINS *q_e, POLICY_HND *pol,
+                               uint32 start_idx, uint32 size)
+{
+       if (q_e == NULL || pol == NULL) return False;
+
+       DEBUG(5,("make_samr_q_enum_domains\n"));
+
+       memcpy(&(q_e->pol), pol, sizeof(*pol));
+
+       q_e->start_idx = start_idx;
+       q_e->max_size = size;
+
+       return True;
+}
+
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+BOOL samr_io_q_enum_domains(char *desc, SAMR_Q_ENUM_DOMAINS *q_e, prs_struct *ps, int depth)
+{
+       if (q_e == NULL) return False;
+
+       prs_debug(ps, depth, desc, "samr_io_q_enum_domains");
+       depth++;
+
+       prs_align(ps);
+
+       smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); 
+       prs_align(ps);
+
+       prs_uint32("start_idx", ps, depth, &(q_e->start_idx));
+       prs_uint32("max_size ", ps, depth, &(q_e->max_size ));
+
+       prs_align(ps);
+
+       return True;
+}
+
+
+/*******************************************************************
+makes a SAMR_R_ENUM_DOMAINS structure.
+********************************************************************/
+BOOL make_samr_r_enum_domains(SAMR_R_ENUM_DOMAINS *r_u,
+               uint32 next_idx,
+               uint32 num_sam_entries, char **doms, uint32 status)
+{
+       uint32 i;
+
+       if (r_u == NULL) return False;
+
+       DEBUG(5,("make_samr_r_enum_domains\n"));
+
+       r_u->next_idx = next_idx;
+       r_u->sam = NULL;
+       r_u->uni_dom_name = NULL;
+
+       if (num_sam_entries != 0)
+       {
+               r_u->ptr_entries1 = 1;
+               r_u->ptr_entries2 = 1;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->num_entries3 = num_sam_entries;
+
+               r_u->sam = (SAM_ENTRY*)Realloc(NULL, r_u->num_entries2 * sizeof(r_u->sam[0]));
+               r_u->uni_dom_name = (UNISTR2*)Realloc(NULL, r_u->num_entries2 * sizeof(r_u->uni_dom_name[0]));
+
+               if (r_u->sam == NULL || r_u->uni_dom_name == NULL)
+               {
+                       DEBUG(0,("NULL pointers in SAMR_R_ENUM_DOMAINS\n"));
+                       return False;
+               }
+
+               for (i = 0; i < num_sam_entries; i++)
+               {
+                       int acct_name_len = doms[i] != NULL ? strlen(doms[i]) : 0;
+
+                       make_sam_entry(&(r_u->sam[i]), acct_name_len, 0);
+                       make_unistr2(&(r_u->uni_dom_name[i]), doms[i], acct_name_len);
+               }
+
+               r_u->num_entries4 = num_sam_entries;
+       }
+       else
+       {
+               r_u->ptr_entries1 = 0;
+               r_u->num_entries2 = num_sam_entries;
+               r_u->ptr_entries2 = 1;
+       }
+
+       r_u->status = status;
+
+       return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+BOOL samr_io_r_enum_domains(char *desc, SAMR_R_ENUM_DOMAINS *r_u, prs_struct *ps, int depth)
+{
+       uint32 i;
+
+       if (r_u == NULL) return False;
+
+       prs_debug(ps, depth, desc, "samr_io_r_enum_domains");
+       depth++;
+
+       r_u->sam = NULL;
+       r_u->uni_dom_name = NULL;
+
+       prs_align(ps);
+
+       prs_uint32("next_idx    ", ps, depth, &(r_u->next_idx    ));
+       prs_uint32("ptr_entries1", ps, depth, &(r_u->ptr_entries1));
+
+       if (r_u->ptr_entries1 != 0)
+       {
+               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 (ps->io)
+               {
+                       r_u->sam = (SAM_ENTRY*)Realloc(NULL, r_u->num_entries2 * sizeof(r_u->sam[0]));
+                       r_u->uni_dom_name = (UNISTR2*)Realloc(NULL, r_u->num_entries2 * sizeof(r_u->uni_dom_name[0]));
+               }
+
+               if ((r_u->sam == NULL || r_u->uni_dom_name == NULL) && r_u->num_entries2 != 0)
+               {
+                       DEBUG(0,("NULL pointers in SAMR_R_ENUM_DOMAINS\n"));
+                       r_u->num_entries4 = 0;
+                       r_u->status = 0xC0000000|NT_STATUS_MEMORY_NOT_ALLOCATED;
+                       return False;
+               }
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       prs_grow(ps);
+                       sam_io_sam_entry("", &(r_u->sam[i]), ps, depth);
+               }
+
+               for (i = 0; i < r_u->num_entries2; i++)
+               {
+                       prs_grow(ps);
+                       smb_io_unistr2("", &(r_u->uni_dom_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));
+
+       return True;
+}
+
 /*******************************************************************
 makes a SAMR_Q_ENUM_DOM_GROUPS structure.
 ********************************************************************/
index 1327099aac2937800be02fb04889bc4cbd676d1a..e9314bada6584fb213033013cc91c89f7b574e85 100644 (file)
@@ -37,6 +37,11 @@ extern struct cli_state *smb_cli;
 
 extern FILE* out_hnd;
 
+static void sam_display_domain(const char *domain)
+{
+       report(out_hnd, "Domain Name: %s\n", domain);
+}
+
 static void sam_display_alias_info(const char *domain, const DOM_SID *sid,
                                uint32 alias_rid, 
                                ALIAS_INFO_CTR *const ctr)
@@ -756,6 +761,95 @@ static BOOL req_groupmem_info(struct cli_state *cli, uint16 fnum,
        return False;
 }
 
+/****************************************************************************
+SAM Domains query.
+                               DOMAIN_INFO_FN(dom_inf_fn),
+                               DOMAIN_MEM_FN(dom_mem_fn))
+****************************************************************************/
+uint32 msrpc_sam_enum_domains(struct cli_state *cli,
+                               const char* srv_name,
+                               struct acct_info **sam,
+                               uint32 *num_sam_entries,
+                               DOMAIN_FN(dom_fn))
+{
+       uint16 fnum;
+       BOOL res = True;
+       uint32 ace_perms = 0x02000000; /* access control permissions. */
+       POLICY_HND sam_pol;
+       uint32 status;
+
+       /* open SAMR session.  negotiate credentials */
+       res = res ? cli_nt_session_open(cli, PIPE_SAMR, &fnum) : False;
+
+       /* establish a connection. */
+       res = res ? samr_connect(cli, fnum,
+                               srv_name, ace_perms,
+                               &sam_pol) : False;
+
+       (*sam) = NULL;
+       (*num_sam_entries) = 0;
+
+       if (res)
+       {
+               uint32 domain_idx;
+               uint32 start_idx = 0;
+               /* read some domains */
+               do
+               {
+                       status = samr_enum_domains(cli, fnum, 
+                            &sam_pol,
+                            &start_idx, 0x10000,
+                            sam, num_sam_entries);
+
+               } while (status == STATUS_MORE_ENTRIES);
+
+               if ((*num_sam_entries) == 0)
+               {
+                       report(out_hnd, "No domains\n");
+               }
+
+               for (domain_idx = 0; domain_idx < (*num_sam_entries); domain_idx++)
+               {
+                       char *domain_name = (*sam)[domain_idx].acct_name;
+
+                       if (dom_fn != NULL)
+                       {
+                               dom_fn(domain_name);
+                       }
+
+#if 0
+                       if (dom_inf_fn != NULL)
+                       {
+                               query_domaininfo(cli, fnum, &sam_pol,
+                                                 domain_name,
+                                                 dom_inf_fn);
+                       }
+                       if (dom_mem_fn != NULL)
+                       {
+                               req_domainmem_info(cli, fnum, &sam_pol,
+                                                 domain_name,
+                                                 dom_mem_fn);
+                       }
+#endif
+               }
+       }
+
+       res = res ? samr_close(cli, fnum, &sam_pol) : False;
+
+       /* close the session */
+       cli_nt_session_close(cli, fnum);
+
+       if (res)
+       {
+               DEBUG(5,("msrpc_sam_enum_domains: succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("msrpc_sam_enum_domains: failed\n"));
+       }
+       return (*num_sam_entries);
+}
+
 /****************************************************************************
 SAM groups query.
 ****************************************************************************/
@@ -3133,3 +3227,46 @@ void cmd_sam_enum_groups(struct client_info *info)
                free(sam);
        }
 }
+
+/****************************************************************************
+experimental SAM domains enum.
+****************************************************************************/
+void cmd_sam_enum_domains(struct client_info *info)
+{
+       BOOL request_domain_info = False;
+       fstring tmp;
+       int i;
+       struct acct_info *sam = NULL;
+       uint32 num_sam_entries = 0;
+
+       fstring srv_name;
+
+       fstrcpy(srv_name, "\\\\");
+       fstrcat(srv_name, info->dest_host);
+       strupper(srv_name);
+
+       for (i = 0; i < 3; i++)
+       {
+               /* a bad way to do token parsing... */
+               if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+               {
+                       request_domain_info  |= strequal(tmp, "-i");
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       report(out_hnd, "SAM Enumerate Domains\n");
+
+       msrpc_sam_enum_domains(smb_cli, srv_name,
+                   &sam, &num_sam_entries,
+                   sam_display_domain);
+
+       if (sam != NULL)
+       {
+               free(sam);
+       }
+}
+
index 06e6d0c089b0835d6f9e697cfe126e807b8a3428..f359045baeb53cc32c2163174995469d04b5bbb0 100644 (file)
@@ -483,6 +483,12 @@ commands[] =
                "SAM Aliases Database Query (experimental!)",
                {COMPL_NONE, COMPL_NONE}
        },
+       {
+               "enumdomains",
+               cmd_sam_enum_domains,
+               "SAM Domains Database Query (experimental!)",
+               {COMPL_NONE, COMPL_NONE}
+       },
        {
                "enumgroups",
                cmd_sam_enum_groups,