From 0f18ca772da544a93799ca130a8f23529aad98f6 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Sat, 6 Nov 1999 19:52:04 +0000 Subject: 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 used to be commit 135eaa977385cdd5f572a51f654f14d893347d7b) --- source3/include/proto.h | 27 +++++- source3/include/rpc_spoolss.h | 3 +- source3/lib/util.c | 94 ++++++++++++++++--- source3/rpc_client/cli_spoolss.c | 64 +++++++++++++ source3/rpc_parse/parse_spoolss.c | 188 ++++++++++++++++++++++++++++---------- source3/rpcclient/cmd_samr.c | 4 +- source3/rpcclient/cmd_spoolss.c | 40 ++++++++ source3/rpcclient/rpcclient.c | 8 +- source3/script/mkproto.awk | 4 + 9 files changed, 364 insertions(+), 68 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index c382d2d6ed..1bd5d131b5 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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 */ diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index 0afc8d2b5d..626835933b 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -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; diff --git a/source3/lib/util.c b/source3/lib/util.c index 0ed4e6fe50..69f884cc8b 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -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); } diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index adb850673f..9d8d5f5736 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -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 ****************************************************************************/ diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index d58a4868e6..59fbd6ac23 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -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;ireturned;i++) + if (!ps->io) { - switch (r_u->level) + /* writing */ + for(i=0;ireturned;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)); + + if (r_u->offeredstatus=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; + } + + 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)); - 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)); + /* have to skip to end of buffer when reading, and have to record + * size of buffer when writing. *shudder*. + */ - if (r_u->offeredstatus=ERROR_INSUFFICIENT_BUFFER; - r_u->offered=0; - /*r_u->returned=0;*/ + beginning = ps->offset; + start_offset = ps->offset; + end_offset = start_offset + r_u->offered; - DEBUG(4,("spoolss_io_r_enumprinters, buffer too small\n")); + if (ps->io) + { + /* reading */ + ps->offset = beginning + r_u->offered; - prs_uint32("size of buffer", ps, depth, &(r_u->offered)); - prs_uint32("size of buffer needed", ps, depth, &(bufsize_required)); + prs_align(ps); + prs_uint32("buffer size", 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")); + + ps->offset = beginning; + } - prs_uint32("size of buffer", ps, depth, &(r_u->offered)); + tmp_ct = 0; - beginning=ps->offset; - start_offset=ps->offset; - end_offset=start_offset+r_u->offered; - for(i=0;ireturned;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)); diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index c66f79938b..4d6cdf6409 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -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; } diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 0e931d4a39..8966eb45c2 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -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 ****************************************************************************/ diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 681ebb42fa..2231824b95 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -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", + " Spool Printer Open Test", {COMPL_NONE, COMPL_NONE} }, /* diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index bc6f50af99..9e4c7de2d6 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -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; } -- cgit