From the "It's not pretty but it works" category
authorjerry <jerry@0c0555d6-39d7-0310-84fc-f1cc0bd64818>
Sat, 4 Mar 2006 00:05:40 +0000 (00:05 +0000)
committerjerry <jerry@0c0555d6-39d7-0310-84fc-f1cc0bd64818>
Sat, 4 Mar 2006 00:05:40 +0000 (00:05 +0000)
* 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

git-svn-id: svn+ssh://svn.samba.org/data/svn/samba/branches/SAMBA_3_0@13829 0c0555d6-39d7-0310-84fc-f1cc0bd64818

source/include/nt_printing.h
source/include/rpc_spoolss.h
source/param/loadparm.c
source/rpc_parse/parse_spoolss.c
source/rpc_server/srv_spoolss_nt.c

index a2aba3ed26e2e0f84b05b661cd381fb204c37b4e..5bd64ae7be39cc83f8558fd1a4b754db4743a7bd 100644 (file)
@@ -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
index f2f789a49e055d606be0edbcca4ad274ecc04614..4d24ee4f0f85dc7baf8546bf9fb0ee6e2413b555 100755 (executable)
@@ -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;
index ce4bef8d27bff741bddfdbe9bcbcafbd255a1f92..64b3ecd81b38d733ea6543ff4dcc8e3d0be3b931 100644 (file)
@@ -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)
index 2bb8a7bbdd6e93298b0a2932c4d8290653744f02..576d75f88cb9566028acd005178fc42536684a0d 100644 (file)
@@ -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;
+}
+
index 126c2cc140e966ace648036e1779b30b44317a3c..a9d4e14aaefb8afe778df98eb33319ee6e74f4b8 100644 (file)
@@ -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;