1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00

added rpcclient "enumdomains" command. enumerates names of domains

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 commit is contained in:
Luke Leighton 0001-01-01 00:00:00 +00:00
parent 25c70e3c98
commit 3146aa6b60
7 changed files with 457 additions and 1 deletions

View 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)\

View 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 */

View 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
{

View 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
****************************************************************************/

View 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.
********************************************************************/

View 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);
}
}

View 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,