summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source3/include/ntdomain.h3
-rw-r--r--source3/include/proto.h18
-rw-r--r--source3/include/rpc_samr.h32
-rw-r--r--source3/rpc_client/cli_samr.c102
-rw-r--r--source3/rpc_parse/parse_samr.c160
-rw-r--r--source3/rpcclient/cmd_samr.c137
-rw-r--r--source3/rpcclient/rpcclient.c6
7 files changed, 457 insertions, 1 deletions
diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h
index 7f588744752..4f6cc85905e 100644
--- a/source3/include/ntdomain.h
+++ b/source3/include/ntdomain.h
@@ -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)\
diff --git a/source3/include/proto.h b/source3/include/proto.h
index df05f2d7be1..ff553314007 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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 */
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h
index 58246488a1a..850e3a8b948 100644
--- a/source3/include/rpc_samr.h
+++ b/source3/include/rpc_samr.h
@@ -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
{
diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c
index 94865e4d3c9..d16098247f4 100644
--- a/source3/rpc_client/cli_samr.c
+++ b/source3/rpc_client/cli_samr.c
@@ -616,6 +616,108 @@ BOOL samr_query_dom_info(struct cli_state *cli, uint16 fnum,
}
/****************************************************************************
+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
****************************************************************************/
uint32 samr_enum_dom_groups(struct cli_state *cli, uint16 fnum,
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index 2cd796f874b..ab45152db0e 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -2756,6 +2756,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.
********************************************************************/
BOOL make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol,
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index 1327099aac2..e9314bada65 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -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)
@@ -757,6 +762,95 @@ static BOOL req_groupmem_info(struct cli_state *cli, uint16 fnum,
}
/****************************************************************************
+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.
****************************************************************************/
uint32 msrpc_sam_enum_groups(struct cli_state *cli,
@@ -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);
+ }
+}
+
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c
index 06e6d0c089b..f359045baeb 100644
--- a/source3/rpcclient/rpcclient.c
+++ b/source3/rpcclient/rpcclient.c
@@ -484,6 +484,12 @@ commands[] =
{COMPL_NONE, COMPL_NONE}
},
{
+ "enumdomains",
+ cmd_sam_enum_domains,
+ "SAM Domains Database Query (experimental!)",
+ {COMPL_NONE, COMPL_NONE}
+ },
+ {
"enumgroups",
cmd_sam_enum_groups,
"SAM Group Database Query (experimental!)",