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

added rpcclient spoolenum command. enumerates printers.

spoolss_r_io_enumprinters doesn't decode strings correctly
as printer_info_1/2 code has only been written to write
structures, not read them.
This commit is contained in:
Luke Leighton 0001-01-01 00:00:00 +00:00
parent ef7fa58fd3
commit 135eaa9773
9 changed files with 365 additions and 69 deletions

View File

@ -482,14 +482,20 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name);
BOOL become_user_permanently(uid_t uid, gid_t gid);
void free_void_array(uint32 num_entries, void **entries,
void(free_item)(void*));
BOOL add_item_to_array(uint32 *len, void ***array, const void *item,
void*(item_dup)(const void*));
void* add_item_to_array(uint32 *len, void ***array, const void *item,
void*(item_dup)(const void*), BOOL alloc_anyway);
void free_char_array(uint32 num_entries, char **entries);
BOOL add_chars_to_array(uint32 *len, char ***array, const char *name);
char* add_chars_to_array(uint32 *len, char ***array, const char *name);
void free_unistr_array(uint32 num_entries, UNISTR2 **entries);
BOOL add_unistr_to_array(uint32 *len, UNISTR2 ***array, UNISTR2 *name);
UNISTR2* add_unistr_to_array(uint32 *len, UNISTR2 ***array, UNISTR2 *name);
void free_sid_array(uint32 num_entries, DOM_SID **entries);
BOOL add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid);
DOM_SID* add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid);
void free_print2_array(uint32 num_entries, PRINTER_INFO_2 **entries);
PRINTER_INFO_2 *add_print2_to_array(uint32 *len, PRINTER_INFO_2 ***array,
const PRINTER_INFO_2 *prt);
void free_print1_array(uint32 num_entries, PRINTER_INFO_1 **entries);
PRINTER_INFO_1 *add_print1_to_array(uint32 *len, PRINTER_INFO_1 ***array,
const PRINTER_INFO_1 *prt);
/*The following definitions come from lib/util_file.c */
@ -2037,6 +2043,11 @@ BOOL samr_query_dispinfo(struct cli_state *cli, uint16 fnum,
/*The following definitions come from rpc_client/cli_spoolss.c */
BOOL spoolss_enum_printers(struct cli_state *cli, uint16 fnum,
uint32 flags, char *servername,
uint32 level,
uint32 *count,
void ***printers);
BOOL spoolss_open_printer_ex(struct cli_state *cli, uint16 fnum,
char *printername,
uint32 cbbuf, uint32 devmod, uint32 des_access,
@ -2968,6 +2979,11 @@ BOOL spoolss_io_q_getprinterdriver2(char *desc,
prs_struct *ps, int depth);
BOOL spoolss_io_r_getprinterdriver2(char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u,
prs_struct *ps, int depth);
BOOL make_spoolss_q_enumprinters(SPOOL_Q_ENUMPRINTERS *q_u,
uint32 flags,
const char* servername,
uint32 level,
uint32 size);
BOOL spoolss_io_q_enumprinters(char *desc, SPOOL_Q_ENUMPRINTERS *q_u,
prs_struct *ps, int depth);
BOOL spoolss_io_r_enumprinters(char *desc,
@ -3415,6 +3431,7 @@ void cmd_sam_enum_groups(struct client_info *info);
/*The following definitions come from rpcclient/cmd_spoolss.c */
void cmd_spoolss_enum_printers(struct client_info *info);
void cmd_spoolss_open_printer_ex(struct client_info *info);
/*The following definitions come from rpcclient/cmd_srvsvc.c */

View File

@ -811,7 +811,7 @@ typedef struct spool_q_enumprinters
UNISTR2 servername;
uint32 level;
BUFFER buffer;
/* uint32 buf_size;*/
uint32 buf_size;
} SPOOL_Q_ENUMPRINTERS;
typedef struct spool_r_enumprinters
@ -825,6 +825,7 @@ typedef struct spool_r_enumprinters
union {
PRINTER_INFO_1 **printers_1;
PRINTER_INFO_2 **printers_2;
void *info;
} printer;
} SPOOL_R_ENUMPRINTERS;

View File

@ -3245,23 +3245,28 @@ void free_void_array(uint32 num_entries, void **entries,
}
}
BOOL add_item_to_array(uint32 *len, void ***array, const void *item,
void*(item_dup)(const void*))
void* add_item_to_array(uint32 *len, void ***array, const void *item,
void*(item_dup)(const void*), BOOL alloc_anyway)
{
if (len == NULL || array == NULL || item_dup == NULL)
{
return False;
return NULL;
}
(*array) = (void**)Realloc((*array), ((*len)+1)*sizeof((*array)[0]));
if ((*array) != NULL)
{
(*array)[(*len)] = item_dup(item);
void* copy = NULL;
if (item != NULL || alloc_anyway)
{
copy = item_dup(item);
}
(*array)[(*len)] = copy;
(*len)++;
return True;
return copy;
}
return True;
return NULL;
}
void free_char_array(uint32 num_entries, char **entries)
@ -3270,10 +3275,11 @@ void free_char_array(uint32 num_entries, char **entries)
free_void_array(num_entries, (void**)entries, *fn);
}
BOOL add_chars_to_array(uint32 *len, char ***array, const char *name)
char* add_chars_to_array(uint32 *len, char ***array, const char *name)
{
void*(*fn)(const void*) = (void*(*)(const void*))&strdup;
return add_item_to_array(len, (void***)array, (const void*)name, *fn);
return (char*)add_item_to_array(len,
(void***)array, (const void*)name, *fn, False);
}
@ -3283,10 +3289,11 @@ void free_unistr_array(uint32 num_entries, UNISTR2 **entries)
free_void_array(num_entries, (void**)entries, *fn);
}
BOOL add_unistr_to_array(uint32 *len, UNISTR2 ***array, UNISTR2 *name)
UNISTR2* add_unistr_to_array(uint32 *len, UNISTR2 ***array, UNISTR2 *name)
{
void*(*fn)(const void*) = (void*(*)(const void*))&unistr2_dup;
return add_item_to_array(len, (void***)array, (const void*)name, *fn);
return (UNISTR2*)add_item_to_array(len,
(void***)array, (const void*)name, *fn, False);
}
void free_sid_array(uint32 num_entries, DOM_SID **entries)
@ -3295,9 +3302,72 @@ void free_sid_array(uint32 num_entries, DOM_SID **entries)
free_void_array(num_entries, (void**)entries, *fn);
}
BOOL add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid)
DOM_SID* add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid)
{
void*(*fn)(const void*) = (void*(*)(const void*))&sid_dup;
return add_item_to_array(len, (void***)array, (const void*)sid, *fn);
return (DOM_SID*)add_item_to_array(len,
(void***)array, (const void*)sid, *fn, False);
}
static PRINTER_INFO_2 *prt2_dup(const PRINTER_INFO_2* from)
{
PRINTER_INFO_2 *copy = (PRINTER_INFO_2 *)malloc(sizeof(PRINTER_INFO_2));
if (copy != NULL)
{
if (from != NULL)
{
memcpy(copy, from, sizeof(*copy));
}
else
{
memset(copy, 0, sizeof(*copy));
}
}
return copy;
}
void free_print2_array(uint32 num_entries, PRINTER_INFO_2 **entries)
{
void(*fn)(void*) = (void(*)(void*))&free;
free_void_array(num_entries, (void**)entries, *fn);
}
PRINTER_INFO_2 *add_print2_to_array(uint32 *len, PRINTER_INFO_2 ***array,
const PRINTER_INFO_2 *prt)
{
void*(*fn)(const void*) = (void*(*)(const void*))&prt2_dup;
return (PRINTER_INFO_2*)add_item_to_array(len,
(void***)array, (const void*)prt, *fn, True);
}
static PRINTER_INFO_1 *prt1_dup(const PRINTER_INFO_1* from)
{
PRINTER_INFO_1 *copy = (PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1));
if (copy != NULL)
{
if (from != NULL)
{
memcpy(copy, from, sizeof(*copy));
}
else
{
memset(copy, 0, sizeof(*copy));
}
}
return copy;
}
void free_print1_array(uint32 num_entries, PRINTER_INFO_1 **entries)
{
void(*fn)(void*) = (void(*)(void*))&free;
free_void_array(num_entries, (void**)entries, *fn);
}
PRINTER_INFO_1 *add_print1_to_array(uint32 *len, PRINTER_INFO_1 ***array,
const PRINTER_INFO_1 *prt)
{
void*(*fn)(const void*) = (void*(*)(const void*))&prt1_dup;
return (PRINTER_INFO_1*)add_item_to_array(len,
(void***)array, (const void*)prt, *fn, True);
}

View File

@ -32,6 +32,70 @@
extern int DEBUGLEVEL;
/****************************************************************************
do a SPOOLSS Enum Printers
****************************************************************************/
BOOL spoolss_enum_printers(struct cli_state *cli, uint16 fnum,
uint32 flags, char *servername,
uint32 level,
uint32 *count,
void ***printers)
{
prs_struct rbuf;
prs_struct buf;
SPOOL_Q_ENUMPRINTERS q_o;
BOOL valid_pol = False;
if (count == NULL || printers == NULL) return False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */
DEBUG(5,("SPOOLSS Enum Printers (Server: %s level: %d)\n",
servername, level));
make_spoolss_q_enumprinters(&q_o, flags, servername, level, 0x200);
/* turn parameters into data stream */
spoolss_io_q_enumprinters("", &q_o, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, fnum, SPOOLSS_ENUMPRINTERS, &buf, &rbuf))
{
SPOOL_R_ENUMPRINTERS r_o;
BOOL p;
ZERO_STRUCT(r_o);
r_o.level = level;
spoolss_io_r_enumprinters("", &r_o, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(5,("SPOOLSS_ENUM_PRINTERS: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
/* ok, at last: we're happy. return the policy handle */
(*count) = r_o.returned;
(*printers) = r_o.printer.info;
valid_pol = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_pol;
}
/****************************************************************************
do a SPOOLSS Open Printer Ex
****************************************************************************/

View File

@ -1690,15 +1690,27 @@ static BOOL spoolss_io_read_buffer(char *desc, prs_struct *ps, int depth, BUFFER
if (buffer->ptr != 0x0000)
{
prs_uint32("size", ps, depth, &(buffer->size));
buffer->data=(uint8 *)malloc( (buffer->size) * sizeof(uint8) );
prs_uint8s(True,"buffer", ps, depth, buffer->data, buffer->size);
if (ps->io)
{
/* reading */
buffer->data=(uint8 *)malloc( buffer->size * sizeof(uint8) );
}
if (buffer->data == NULL)
{
return False;
}
prs_uint8s(True, "buffer", ps, depth, buffer->data, buffer->size);
prs_align(ps);
}
else
{
buffer->data=0x0000;
buffer->size=0x0000;
if (ps->io)
{
/* reading */
buffer->data=0x0000;
buffer->size=0x0000;
}
}
return True;
@ -1885,6 +1897,33 @@ BOOL spoolss_io_r_getprinterdriver2(char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u,
return True;
}
/*******************************************************************
* make a structure.
********************************************************************/
BOOL make_spoolss_q_enumprinters(SPOOL_Q_ENUMPRINTERS *q_u,
uint32 flags,
const char* servername,
uint32 level,
uint32 size)
{
size_t len_name = servername != NULL ? strlen(servername) : 0;
DEBUG(5,("make_spoolss_q_enumprinters. size: %d\n", size));
q_u->flags = flags;
make_unistr2(&(q_u->servername), servername, len_name);
q_u->level = level;
q_u->buffer.ptr = (size != 0) ? 1 : 0;
q_u->buffer.size = size;
q_u->buffer.data = (uint8 *)Realloc( NULL,
(q_u->buffer.size) * sizeof(uint8) );
q_u->buf_size = size;
return True;
}
/*******************************************************************
* read a structure.
* called from spoolss_enumprinters (srv_spoolss.c)
@ -1892,24 +1931,34 @@ BOOL spoolss_io_r_getprinterdriver2(char *desc, SPOOL_R_GETPRINTERDRIVER2 *r_u,
BOOL spoolss_io_q_enumprinters(char *desc, SPOOL_Q_ENUMPRINTERS *q_u,
prs_struct *ps, int depth)
{
uint32 useless_ptr;
uint32 useless_ptr = 0x01;
prs_debug(ps, depth, desc, "spoolss_io_q_enumprinters");
depth++;
prs_align(ps);
prs_uint32("flags", ps, depth, &(q_u->flags));
prs_uint32("useless ptr", ps, depth, &useless_ptr);
smb_io_unistr2("", &(q_u->servername),True,ps,depth);
prs_align(ps);
prs_uint32("level", ps, depth, &(q_u->level));
spoolss_io_read_buffer("buffer", ps, depth, &(q_u->buffer));
if (!ps->io)
{
/* writing */
if (q_u->buffer.data != NULL)
{
free(q_u->buffer.data);
}
q_u->buffer.data = NULL;
}
prs_uint32("buf_size", ps, depth, &q_u->buf_size);
return True;
}
@ -1926,6 +1975,7 @@ BOOL spoolss_io_r_enumprinters(char *desc,
int i;
uint32 start_offset, end_offset, beginning;
uint32 bufsize_required=0;
uint32 tmp_ct = 0;
PRINTER_INFO_1 *info1;
PRINTER_INFO_2 *info2;
@ -1935,76 +1985,120 @@ BOOL spoolss_io_r_enumprinters(char *desc,
prs_align(ps);
prs_uint32("pointer", ps, depth, &useless_ptr);
for(i=0;i<r_u->returned;i++)
if (!ps->io)
{
switch (r_u->level)
/* writing */
for(i=0;i<r_u->returned;i++)
{
case 1:
info1 = r_u->printer.printers_1[i];
bufsize_required += spoolss_size_printer_info_1(info1);
break;
case 2:
info2 = r_u->printer.printers_2[i];
bufsize_required += spoolss_size_printer_info_2(info2);
break;
switch (r_u->level)
{
case 1:
info1 = r_u->printer.printers_1[i];
bufsize_required += spoolss_size_printer_info_1(info1);
break;
case 2:
info2 = r_u->printer.printers_2[i];
bufsize_required += spoolss_size_printer_info_2(info2);
break;
}
}
}
DEBUG(4,("spoolss_io_r_enumprinters, size needed: %d\n",bufsize_required));
DEBUG(4,("spoolss_io_r_enumprinters, size offered: %d\n",r_u->offered));
DEBUG(4,("spoolss_io_r_enumprinters, size needed: %d\n",bufsize_required));
DEBUG(4,("spoolss_io_r_enumprinters, size offered: %d\n",r_u->offered));
if (r_u->offered<bufsize_required)
{
/*
* so the buffer is too small to handle datas
* reply the minimum size required in the status
* make the buffer equal 0
* and reply no printers in buffer
*/
r_u->status=ERROR_INSUFFICIENT_BUFFER;
r_u->offered=0;
/*r_u->returned=0;*/
if (r_u->offered<bufsize_required)
{
/*
* so the buffer is too small to handle datas
* reply the minimum size required in the status
* make the buffer equal 0
* and reply no printers in buffer
*/
r_u->status=ERROR_INSUFFICIENT_BUFFER;
r_u->offered=0;
/*r_u->returned=0;*/
DEBUG(4,("spoolss_io_r_enumprinters, buffer too small\n"));
prs_uint32("size of buffer", ps, depth, &(r_u->offered));
prs_uint32("size of buffer needed", ps, depth, &(bufsize_required));
prs_uint32("count", ps, depth, &(r_u->returned));
prs_uint32("status", ps, depth, &(r_u->status));
return False;
}
DEBUG(4,("spoolss_io_r_enumprinters, buffer too small\n"));
prs_uint32("size of buffer", ps, depth, &(r_u->offered));
prs_uint32("size of buffer needed", ps, depth, &(bufsize_required));
prs_uint32("count", ps, depth, &(r_u->returned));
prs_uint32("status", ps, depth, &(r_u->status));
return False;
}
mem_grow_data(&(ps->data), ps->io, r_u->offered, 0);
DEBUG(4,("spoolss_io_r_enumprinters, buffer large enough\n"));
mem_grow_data(&(ps->data), ps->io, r_u->offered, 0);
DEBUG(4,("spoolss_io_r_enumprinters, buffer large enough\n"));
}
prs_uint32("size of buffer", ps, depth, &(r_u->offered));
beginning=ps->offset;
start_offset=ps->offset;
end_offset=start_offset+r_u->offered;
/* have to skip to end of buffer when reading, and have to record
* size of buffer when writing. *shudder*.
*/
beginning = ps->offset;
start_offset = ps->offset;
end_offset = start_offset + r_u->offered;
if (ps->io)
{
/* reading */
ps->offset = beginning + r_u->offered;
prs_align(ps);
prs_uint32("buffer size", ps, depth, &(bufsize_required));
prs_uint32("count", ps, depth, &(r_u->returned));
ps->offset = beginning;
}
tmp_ct = 0;
for(i=0;i<r_u->returned;i++)
{
switch (r_u->level)
{
case 1:
{
if (ps->io)
{
/* reading */
r_u->printer.printers_1[i] = add_print1_to_array(&tmp_ct, &r_u->printer.printers_1, NULL);
}
info1=r_u->printer.printers_1[i];
if (info1 == NULL)
{
return False;
}
smb_io_printer_info_1(desc, info1, ps, depth,
&start_offset, &end_offset);
break;
}
case 2:
{
if (ps->io)
{
/* reading */
r_u->printer.printers_2[i] = add_print2_to_array(&tmp_ct, &r_u->printer.printers_2, NULL);
}
info2=r_u->printer.printers_2[i];
if (info2 == NULL)
{
return False;
}
smb_io_printer_info_2(desc, info2, ps, depth,
&start_offset, &end_offset);
break;
}
}
}
ps->offset=beginning+r_u->offered;
ps->offset = beginning + r_u->offered;
prs_align(ps);
prs_uint32("size of buffer needed", ps, depth, &(bufsize_required));
prs_uint32("buffer size", ps, depth, &(bufsize_required));
prs_uint32("count", ps, depth, &(r_u->returned));
prs_uint32("status", ps, depth, &(r_u->status));

View File

@ -1435,7 +1435,7 @@ void cmd_sam_add_aliasmem(struct client_info *info)
while (next_token(NULL, tmp, NULL, sizeof(tmp)))
{
if (!add_chars_to_array(&num_names, &names, tmp))
if (add_chars_to_array(&num_names, &names, tmp) == NULL)
{
return;
}
@ -1971,7 +1971,7 @@ void cmd_sam_add_groupmem(struct client_info *info)
while (res && next_token(NULL, tmp, NULL, sizeof(tmp)))
{
if (!add_chars_to_array(&num_names, &names, tmp))
if (add_chars_to_array(&num_names, &names, tmp) == NULL)
{
return;
}

View File

@ -37,6 +37,46 @@ extern FILE* out_hnd;
extern struct cli_state *smb_cli;
extern int smb_tidx;
/****************************************************************************
nt spoolss query
****************************************************************************/
void cmd_spoolss_enum_printers(struct client_info *info)
{
uint16 nt_pipe_fnum;
fstring srv_name;
void **printers = NULL;
uint32 count = 0;
BOOL res = True;
fstrcpy(srv_name, "\\\\");
fstrcat(srv_name, smb_cli->desthost);
strupper(srv_name);
DEBUG(5, ("cmd_spoolss_open_printer_ex: smb_cli->fd:%d\n", smb_cli->fd));
/* open SPOOLSS session. */
res = res ? cli_nt_session_open(smb_cli, PIPE_SPOOLSS, &nt_pipe_fnum) : False;
res = res ? spoolss_enum_printers(smb_cli, nt_pipe_fnum,
0x40, srv_name, 1, &count, &printers) : False;
/* close the session */
cli_nt_session_close(smb_cli, nt_pipe_fnum);
if (res)
{
DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
report(out_hnd, "OK\n");
}
else
{
DEBUG(5,("cmd_spoolss_enum_printer: query failed\n"));
}
free_void_array(count, printers, free);
}
/****************************************************************************
nt spoolss query
****************************************************************************/

View File

@ -235,10 +235,16 @@ commands[] =
* printer testing
*/
{
"spoolenum",
cmd_spoolss_enum_printers,
"Spool Printer Enum Test",
{COMPL_NONE, COMPL_NONE}
},
{
"spoolopen",
cmd_spoolss_open_printer_ex,
"Spool Printer Open Test",
"<printer name> Spool Printer Open Test",
{COMPL_NONE, COMPL_NONE}
},
/*

View File

@ -94,6 +94,10 @@ END {
gotstart = 1;
}
if( $0 ~ /^PRINTER_INFO_1|^PRINTER_INFO_2/ ) {
gotstart = 1;
}
if( $0 ~ /^UNISTR2|^LOCAL_GRP|^DOMAIN_GRP|^DOM_SID|^SEC_DESC/ ) {
gotstart = 1;
}