summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source3/include/nt_printing.h22
-rwxr-xr-xsource3/include/rpc_spoolss.h20
-rw-r--r--source3/param/loadparm.c3
-rw-r--r--source3/rpc_parse/parse_spoolss.c100
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c112
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";
@@ -9418,15 +9466,53 @@ static WERROR xcvtcp_monitorui( RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed
}
/*******************************************************************
+ 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;