From 5df58c38f3c29d87c5918d1611c17e016c6f7545 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Sat, 4 Mar 2006 00:05:40 +0000 Subject: r13829: From the "It's not pretty but it works" category * Finish prototype of the "add port command" implementation Format is "addportcommand portname deviceURI" * DeviceURI is either - socket://hostname:port/ - lpr://hostname/queue depending on what the client sent in the request (This used to be commit 6d74de7a676b71e83a3c3714743e6380c04e4425) --- source3/include/nt_printing.h | 22 +++++++ source3/include/rpc_spoolss.h | 20 ++++++- source3/param/loadparm.c | 3 + source3/rpc_parse/parse_spoolss.c | 100 ++++++++++++++++++++++++++++++++ source3/rpc_server/srv_spoolss_nt.c | 112 ++++++++++++++++++++++++++++++++---- 5 files changed, 244 insertions(+), 13 deletions(-) diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h index a2aba3ed26..5bd64ae7be 100644 --- a/source3/include/nt_printing.h +++ b/source3/include/nt_printing.h @@ -348,6 +348,28 @@ typedef struct #define SAMBA_PRINTER_PORT_NAME "Samba Printer Port" #endif + +/* + * Structures for the XcvDataPort() calls + */ + +#define PORT_PROTOCOL_DIRECT 1 +#define PORT_PROTOCOL_LPR 2 + +typedef struct { + fstring name; + uint32 version; + uint32 protocol; + fstring hostaddr; + fstring snmpcommunity; + fstring queue; + uint32 dblspool; + fstring ipaddr; + uint32 port; + BOOL enable_snmp; + uint32 snmp_index; +} NT_PORT_DATA_1; + /* DOS header format */ #define DOS_HEADER_SIZE 64 #define DOS_HEADER_MAGIC_OFFSET 0 diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index f2f789a49e..4d24ee4f0f 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -2174,7 +2174,23 @@ SPOOL_R_GETPRINTPROCESSORDIRECTORY; /**************************************/ -typedef struct spool_q_xcvdataport { +typedef struct { + UNISTR portname; /* constant 64 wchars */ + uint32 version; + uint32 protocol; + uint32 size; + uint32 reserved; + UNISTR hostaddress; /* constant 49 wchars */ + UNISTR snmpcommunity; /* constant 33 wchars */ + uint32 dblspool; + UNISTR queue; /* constant 33 wchars */ + UNISTR ipaddress; /* constant 17 wchars */ + uint32 port; + uint32 snmpenabled; + uint32 snmpdevindex; +} SPOOL_PORT_DATA_1; + +typedef struct { POLICY_HND handle; UNISTR2 dataname; RPC_BUFFER indata; @@ -2183,7 +2199,7 @@ typedef struct spool_q_xcvdataport { uint32 unknown; } SPOOL_Q_XCVDATAPORT; -typedef struct spool_r_xcvdataport { +typedef struct { RPC_BUFFER outdata; uint32 needed; uint32 unknown; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index ce4bef8d27..64b3ecd81b 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -104,6 +104,7 @@ typedef struct { char *unix_charset; char *display_charset; char *szPrintcapname; + char *szAddPortCommand; char *szEnumPortsCommand; char *szAddPrinterCommand; char *szDeletePrinterCommand; @@ -1050,6 +1051,7 @@ static struct parm_struct parm_table[] = { {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"addport command", P_STRING, P_GLOBAL, &Globals.szAddPortCommand, NULL, NULL, FLAG_ADVANCED}, {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED}, {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED}, {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED}, @@ -1763,6 +1765,7 @@ FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile) FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir) FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString) FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime) +FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand) FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand) FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand) FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand) diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 2bb8a7bbdd..576d75f88c 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -7488,3 +7488,103 @@ BOOL make_monitorui_buf( RPC_BUFFER *buf, const char *dllname ) return True; } + +/******************************************************************* + ********************************************************************/ + +static BOOL smb_io_port_data_1( const char *desc, RPC_BUFFER *buf, int depth, SPOOL_PORT_DATA_1 *p1 ) +{ + prs_struct *ps = &buf->prs; + uint8 *fodder; + + prs_debug(ps, depth, desc, "smb_io_port_data_1"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( UNMARSHALLING(ps) ) { + p1->portname.buffer = PRS_ALLOC_MEM( ps, uint16, 64 ); + p1->hostaddress.buffer = PRS_ALLOC_MEM( ps, uint16, 49 ); + p1->snmpcommunity.buffer = PRS_ALLOC_MEM( ps, uint16, 33 ); + p1->queue.buffer = PRS_ALLOC_MEM( ps, uint16, 33 ); + p1->ipaddress.buffer = PRS_ALLOC_MEM( ps, uint16, 17 ); + fodder = PRS_ALLOC_MEM( ps, uint8, 540 ); + } + + if( !prs_uint16s(True, "portname", ps, depth, p1->portname.buffer, 64)) + return False; + + if (!prs_uint32("version", ps, depth, &p1->version)) + return False; + if (!prs_uint32("protocol", ps, depth, &p1->protocol)) + return False; + if (!prs_uint32("size", ps, depth, &p1->size)) + return False; + if (!prs_uint32("reserved", ps, depth, &p1->reserved)) + return False; + + if( !prs_uint16s(True, "hostaddress", ps, depth, p1->hostaddress.buffer, 49)) + return False; + if( !prs_uint16s(True, "snmpcommunity", ps, depth, p1->snmpcommunity.buffer, 33)) + return False; + + if (!prs_uint32("dblspool", ps, depth, &p1->dblspool)) + return False; + + if( !prs_uint16s(True, "queue", ps, depth, p1->queue.buffer, 33)) + return False; + if( !prs_uint16s(True, "ipaddress", ps, depth, p1->ipaddress.buffer, 17)) + return False; + + /* fodder according to MSDN */ + if( !prs_uint8s(False, "", ps, depth, fodder, 540)) + return False; + + if (!prs_uint32("port", ps, depth, &p1->port)) + return False; + if (!prs_uint32("snmpenabled", ps, depth, &p1->snmpenabled)) + return False; + if (!prs_uint32("snmpdevindex", ps, depth, &p1->snmpdevindex)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +BOOL convert_port_data_1( NT_PORT_DATA_1 *port1, RPC_BUFFER *buf ) +{ + SPOOL_PORT_DATA_1 spdata_1; + + ZERO_STRUCT( spdata_1 ); + + if ( !smb_io_port_data_1( "port_data_1", buf, 0, &spdata_1 ) ) + return False; + + rpcstr_pull(port1->name, spdata_1.portname.buffer, sizeof(port1->name), + -1, 0); + rpcstr_pull(port1->queue, spdata_1.queue.buffer, sizeof(port1->queue), + -1, 0); + rpcstr_pull(port1->hostaddr, spdata_1.hostaddress.buffer, + sizeof(port1->hostaddr), -1, 0); + + port1->port = spdata_1.port; + + switch ( spdata_1.protocol ) { + case 1: + port1->protocol = PORT_PROTOCOL_DIRECT; + break; + case 2: + port1->protocol = PORT_PROTOCOL_LPR; + break; + default: + DEBUG(3,("convert_port_data_1: unknown protocol [%d]!\n", + spdata_1.protocol)); + return False; + } + + return True; +} + diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 126c2cc140..a9d4e14aae 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -91,7 +91,7 @@ extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping; struct xcv_api_table { const char *name; - WERROR(*fn) (RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed); + WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed); }; @@ -5956,6 +5956,52 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum) /**************************************************************************** ****************************************************************************/ +WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri ) +{ + char *cmd = lp_addport_cmd(); + pstring command; + int ret; + int fd; + SE_PRIV se_printop = SE_PRINT_OPERATOR; + BOOL is_print_op = False; + + if ( !*cmd ) { + return WERR_ACCESS_DENIED; + } + + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri ); + + if ( token ) + is_print_op = user_has_privileges( token, &se_printop ); + + DEBUG(10,("Running [%s]\n", command)); + + /********* BEGIN SePrintOperatorPrivilege **********/ + + if ( is_print_op ) + become_root(); + + ret = smbrun(command, &fd); + + if ( is_print_op ) + unbecome_root(); + + /********* END SePrintOperatorPrivilege **********/ + + DEBUGADD(10,("returned [%d]\n", ret)); + + if ( ret != 0 ) { + if (fd != -1) + close(fd); + return WERR_ACCESS_DENIED; + } + + return WERR_OK; +} + +/**************************************************************************** +****************************************************************************/ + BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer) { char *cmd = lp_addprinter_cmd(); @@ -6025,6 +6071,7 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer) return True; } + /******************************************************************** * Called by spoolss_api_setprinter * when updating a printer description. @@ -9400,7 +9447,8 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC Streams the monitor UI DLL name in UNICODE *******************************************************************/ -static WERROR xcvtcp_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed ) +static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, + RPC_BUFFER *out, uint32 *needed ) { const char *dllname = "tcpmonui.dll"; @@ -9417,16 +9465,54 @@ static WERROR xcvtcp_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed return WERR_OK; } +/******************************************************************* + Create a new TCP/IP port +*******************************************************************/ + +static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in, + RPC_BUFFER *out, uint32 *needed ) +{ + NT_PORT_DATA_1 port1; + pstring device_uri; + + ZERO_STRUCT( port1 ); + + /* convert to our internal port data structure */ + + if ( !convert_port_data_1( &port1, in ) ) { + return WERR_NOMEM; + } + + /* create the device URI and call the add_port_hook() */ + + switch ( port1.protocol ) { + case PORT_PROTOCOL_DIRECT: + pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port ); + break; + + case PORT_PROTOCOL_LPR: + pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue ); + break; + + default: + return WERR_UNKNOWN_PORT; + } + + return add_port_hook( token, port1.name, device_uri ); +} + /******************************************************************* *******************************************************************/ struct xcv_api_table xcvtcp_cmds[] = { { "MonitorUI", xcvtcp_monitorui }, + { "AddPort", xcvtcp_addport}, { NULL, NULL } }; -static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf, - RPC_BUFFER *outbuf, uint32 *needed ) +static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command, + RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, + uint32 *needed ) { int i; @@ -9434,7 +9520,7 @@ static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf, for ( i=0; xcvtcp_cmds[i].name; i++ ) { if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 ) - return xcvtcp_cmds[i].fn( inbuf, outbuf, needed ); + return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed ); } return WERR_BADFUNC; @@ -9443,7 +9529,8 @@ static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf, /******************************************************************* *******************************************************************/ -static WERROR xcvlocal_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed ) +static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, + RPC_BUFFER *out, uint32 *needed ) { const char *dllname = "localui.dll"; @@ -9472,8 +9559,9 @@ struct xcv_api_table xcvlocal_cmds[] = { /******************************************************************* *******************************************************************/ -static WERROR process_xcvlocal_command( const char *command, RPC_BUFFER *inbuf, - RPC_BUFFER *outbuf, uint32 *needed ) +static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command, + RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, + uint32 *needed ) { int i; @@ -9482,7 +9570,7 @@ static WERROR process_xcvlocal_command( const char *command, RPC_BUFFER *inbuf, for ( i=0; xcvlocal_cmds[i].name; i++ ) { if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 ) - return xcvlocal_cmds[i].fn( inbuf, outbuf , needed ); + return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed ); } return WERR_BADFUNC; } @@ -9526,9 +9614,11 @@ WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_X switch ( Printer->printer_type ) { case SPLHND_PORTMON_TCP: - return process_xcvtcp_command( command, &q_u->indata, &r_u->outdata, &r_u->needed ); + return process_xcvtcp_command( p->pipe_user.nt_user_token, command, + &q_u->indata, &r_u->outdata, &r_u->needed ); case SPLHND_PORTMON_LOCAL: - return process_xcvlocal_command( command, &q_u->indata, &r_u->outdata, &r_u->needed ); + return process_xcvlocal_command( p->pipe_user.nt_user_token, command, + &q_u->indata, &r_u->outdata, &r_u->needed ); } return WERR_INVALID_PRINT_MONITOR; -- cgit