2010-01-19 16:10:47 +03:00
/*
2007-09-03 17:13:25 +04:00
Unix SMB / CIFS implementation .
test suite for spoolss rpc notify operations
Copyright ( C ) Jelmer Vernooij 2007
2010-01-20 00:18:24 +03:00
Copyright ( C ) Guenther Deschner 2010
2010-01-19 16:10:47 +03:00
2007-09-03 17:13:25 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2008-03-28 09:08:49 +03:00
the Free Software Foundation ; either version 3 of the License , or
2007-09-03 17:13:25 +04:00
( at your option ) any later version .
2010-01-19 16:10:47 +03:00
2007-09-03 17:13:25 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2010-01-19 16:10:47 +03:00
2007-09-03 17:13:25 +04:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2009-05-01 20:19:34 +04:00
# include "system/filesys.h"
2007-09-03 17:13:25 +04:00
# include "librpc/gen_ndr/ndr_spoolss_c.h"
2010-01-19 02:22:57 +03:00
# include "librpc/gen_ndr/ndr_spoolss.h"
2010-02-10 02:43:51 +03:00
# include "torture/rpc/rpc.h"
2007-09-03 17:13:25 +04:00
# include "rpc_server/dcerpc_server.h"
2009-05-01 20:19:34 +04:00
# include "rpc_server/service_rpc.h"
2007-09-03 17:13:25 +04:00
# include "smbd/process_model.h"
# include "smb_server/smb_server.h"
# include "lib/socket/netif.h"
# include "ntvfs/ntvfs.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2007-09-03 17:13:25 +04:00
static NTSTATUS spoolss__op_bind ( struct dcesrv_call_state * dce_call , const struct dcesrv_interface * iface )
{
return NT_STATUS_OK ;
}
static void spoolss__op_unbind ( struct dcesrv_connection_context * context , const struct dcesrv_interface * iface )
{
}
static NTSTATUS spoolss__op_ndr_pull ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx , struct ndr_pull * pull , void * * r )
{
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2007-09-03 17:13:25 +04:00
uint16_t opnum = dce_call - > pkt . u . request . opnum ;
dce_call - > fault_code = 0 ;
if ( opnum > = ndr_table_spoolss . num_calls ) {
dce_call - > fault_code = DCERPC_FAULT_OP_RNG_ERROR ;
return NT_STATUS_NET_WRITE_FAULT ;
}
* r = talloc_size ( mem_ctx , ndr_table_spoolss . calls [ opnum ] . struct_size ) ;
NT_STATUS_HAVE_NO_MEMORY ( * r ) ;
/* unravel the NDR for the packet */
2007-11-09 21:24:51 +03:00
ndr_err = ndr_table_spoolss . calls [ opnum ] . ndr_pull ( pull , NDR_IN , * r ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2008-11-02 07:49:36 +03:00
dcerpc_log_packet ( dce_call - > conn - > packet_log_dir ,
2008-11-02 02:26:04 +03:00
& ndr_table_spoolss , opnum , NDR_IN ,
2007-09-03 17:13:25 +04:00
& dce_call - > pkt . u . request . stub_and_verifier ) ;
dce_call - > fault_code = DCERPC_FAULT_NDR ;
return NT_STATUS_NET_WRITE_FAULT ;
}
return NT_STATUS_OK ;
}
2010-01-19 16:10:47 +03:00
/* Note that received_packets are allocated in talloc_autofree_context(),
2008-01-28 04:49:44 +03:00
* because no other context appears to stay around long enough . */
2007-09-03 17:13:25 +04:00
static struct received_packet {
uint16_t opnum ;
void * r ;
struct received_packet * prev , * next ;
} * received_packets = NULL ;
2010-01-19 02:22:57 +03:00
static WERROR _spoolss_ReplyOpenPrinter ( struct dcesrv_call_state * dce_call ,
TALLOC_CTX * mem_ctx ,
struct spoolss_ReplyOpenPrinter * r )
{
DEBUG ( 1 , ( " _spoolss_ReplyOpenPrinter \n " ) ) ;
NDR_PRINT_IN_DEBUG ( spoolss_ReplyOpenPrinter , r ) ;
r - > out . handle = talloc ( r , struct policy_handle ) ;
r - > out . handle - > handle_type = 42 ;
r - > out . handle - > uuid = GUID_random ( ) ;
r - > out . result = WERR_OK ;
NDR_PRINT_OUT_DEBUG ( spoolss_ReplyOpenPrinter , r ) ;
return WERR_OK ;
}
2007-09-03 17:13:25 +04:00
2010-01-19 02:27:50 +03:00
static WERROR _spoolss_ReplyClosePrinter ( struct dcesrv_call_state * dce_call ,
TALLOC_CTX * mem_ctx ,
struct spoolss_ReplyClosePrinter * r )
{
DEBUG ( 1 , ( " _spoolss_ReplyClosePrinter \n " ) ) ;
NDR_PRINT_IN_DEBUG ( spoolss_ReplyClosePrinter , r ) ;
ZERO_STRUCTP ( r - > out . handle ) ;
r - > out . result = WERR_OK ;
NDR_PRINT_OUT_DEBUG ( spoolss_ReplyClosePrinter , r ) ;
return WERR_OK ;
}
2010-01-31 22:39:36 +03:00
static WERROR _spoolss_RouterReplyPrinterEx ( struct dcesrv_call_state * dce_call ,
TALLOC_CTX * mem_ctx ,
struct spoolss_RouterReplyPrinterEx * r )
{
DEBUG ( 1 , ( " _spoolss_RouterReplyPrinterEx \n " ) ) ;
NDR_PRINT_IN_DEBUG ( spoolss_RouterReplyPrinterEx , r ) ;
r - > out . reply_result = talloc ( r , uint32_t ) ;
* r - > out . reply_result = 0 ;
r - > out . result = WERR_OK ;
NDR_PRINT_OUT_DEBUG ( spoolss_RouterReplyPrinterEx , r ) ;
return WERR_OK ;
}
2007-09-03 17:13:25 +04:00
static NTSTATUS spoolss__op_dispatch ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx , void * r )
{
uint16_t opnum = dce_call - > pkt . u . request . opnum ;
struct received_packet * rp ;
2008-01-28 04:49:44 +03:00
rp = talloc_zero ( talloc_autofree_context ( ) , struct received_packet ) ;
2007-09-03 17:13:25 +04:00
rp - > opnum = opnum ;
2008-01-28 04:49:44 +03:00
rp - > r = talloc_reference ( rp , r ) ;
2007-09-03 17:13:25 +04:00
DLIST_ADD_END ( received_packets , rp , struct received_packet * ) ;
switch ( opnum ) {
case 58 : {
struct spoolss_ReplyOpenPrinter * r2 = ( struct spoolss_ReplyOpenPrinter * ) r ;
2010-01-19 02:22:57 +03:00
r2 - > out . result = _spoolss_ReplyOpenPrinter ( dce_call , mem_ctx , r2 ) ;
2007-09-03 17:13:25 +04:00
break ;
}
2010-01-19 02:27:50 +03:00
case 60 : {
struct spoolss_ReplyClosePrinter * r2 = ( struct spoolss_ReplyClosePrinter * ) r ;
r2 - > out . result = _spoolss_ReplyClosePrinter ( dce_call , mem_ctx , r2 ) ;
break ;
}
2010-01-31 22:39:36 +03:00
case 66 : {
struct spoolss_RouterReplyPrinterEx * r2 = ( struct spoolss_RouterReplyPrinterEx * ) r ;
r2 - > out . result = _spoolss_RouterReplyPrinterEx ( dce_call , mem_ctx , r2 ) ;
break ;
}
2007-09-03 17:13:25 +04:00
default :
dce_call - > fault_code = DCERPC_FAULT_OP_RNG_ERROR ;
break ;
}
if ( dce_call - > fault_code ! = 0 ) {
2008-11-02 07:49:36 +03:00
dcerpc_log_packet ( dce_call - > conn - > packet_log_dir ,
2008-11-02 02:26:04 +03:00
& ndr_table_spoolss , opnum , NDR_IN ,
2007-09-03 17:13:25 +04:00
& dce_call - > pkt . u . request . stub_and_verifier ) ;
return NT_STATUS_NET_WRITE_FAULT ;
}
return NT_STATUS_OK ;
}
static NTSTATUS spoolss__op_reply ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx , void * r )
{
return NT_STATUS_OK ;
}
static NTSTATUS spoolss__op_ndr_push ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx , struct ndr_push * push , const void * r )
{
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2007-09-03 17:13:25 +04:00
uint16_t opnum = dce_call - > pkt . u . request . opnum ;
2007-11-09 21:24:51 +03:00
ndr_err = ndr_table_spoolss . calls [ opnum ] . ndr_push ( push , NDR_OUT , r ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2007-09-03 17:13:25 +04:00
dce_call - > fault_code = DCERPC_FAULT_NDR ;
return NT_STATUS_NET_WRITE_FAULT ;
}
return NT_STATUS_OK ;
}
const static struct dcesrv_interface notify_test_spoolss_interface = {
. name = " spoolss " ,
. syntax_id = { { 0x12345678 , 0x1234 , 0xabcd , { 0xef , 0x00 } , { 0x01 , 0x23 , 0x45 , 0x67 , 0x89 , 0xab } } , 1.0 } ,
. bind = spoolss__op_bind ,
. unbind = spoolss__op_unbind ,
. ndr_pull = spoolss__op_ndr_pull ,
. dispatch = spoolss__op_dispatch ,
. reply = spoolss__op_reply ,
. ndr_push = spoolss__op_ndr_push
} ;
static bool spoolss__op_interface_by_uuid ( struct dcesrv_interface * iface , const struct GUID * uuid , uint32_t if_version )
{
if ( notify_test_spoolss_interface . syntax_id . if_version = = if_version & &
GUID_equal ( & notify_test_spoolss_interface . syntax_id . uuid , uuid ) ) {
memcpy ( iface , & notify_test_spoolss_interface , sizeof ( * iface ) ) ;
return true ;
}
return false ;
}
static bool spoolss__op_interface_by_name ( struct dcesrv_interface * iface , const char * name )
{
if ( strcmp ( notify_test_spoolss_interface . name , name ) = = 0 ) {
memcpy ( iface , & notify_test_spoolss_interface , sizeof ( * iface ) ) ;
return true ;
}
2010-01-19 16:10:47 +03:00
return false ;
2007-09-03 17:13:25 +04:00
}
static NTSTATUS spoolss__op_init_server ( struct dcesrv_context * dce_ctx , const struct dcesrv_endpoint_server * ep_server )
{
int i ;
for ( i = 0 ; i < ndr_table_spoolss . endpoints - > count ; i + + ) {
NTSTATUS ret ;
const char * name = ndr_table_spoolss . endpoints - > names [ i ] ;
ret = dcesrv_interface_register ( dce_ctx , name , & notify_test_spoolss_interface , NULL ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 1 , ( " spoolss_op_init_server: failed to register endpoint '%s' \n " , name ) ) ;
return ret ;
}
}
return NT_STATUS_OK ;
}
2010-01-20 00:18:24 +03:00
static bool test_OpenPrinter ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
2010-01-31 22:39:36 +03:00
struct policy_handle * handle ,
const char * name )
2010-01-20 00:18:24 +03:00
{
struct spoolss_OpenPrinter r ;
2010-01-31 22:39:36 +03:00
const char * printername ;
2010-01-20 00:18:24 +03:00
ZERO_STRUCT ( r ) ;
2010-01-31 22:39:36 +03:00
if ( name ) {
printername = talloc_asprintf ( tctx , " \\ \\ %s \\ %s " , dcerpc_server_name ( p ) , name ) ;
} else {
printername = talloc_asprintf ( tctx , " \\ \\ %s " , dcerpc_server_name ( p ) ) ;
}
r . in . printername = printername ;
2010-01-20 00:18:24 +03:00
r . in . datatype = NULL ;
r . in . devmode_ctr . devmode = NULL ;
r . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
r . out . handle = handle ;
torture_comment ( tctx , " Testing OpenPrinter(%s) \n " , r . in . printername ) ;
2010-01-31 22:39:36 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_spoolss_OpenPrinter ( p , tctx , & r ) ,
" OpenPrinter failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result ,
" OpenPrinter failed " ) ;
2010-01-20 00:18:24 +03:00
return true ;
}
2010-01-31 22:30:09 +03:00
static struct spoolss_NotifyOption * setup_printserver_NotifyOption ( struct torture_context * tctx )
{
struct spoolss_NotifyOption * o ;
o = talloc_zero ( tctx , struct spoolss_NotifyOption ) ;
o - > version = 2 ;
o - > flags = PRINTER_NOTIFY_OPTIONS_REFRESH ;
o - > count = 2 ;
o - > types = talloc_zero_array ( o , struct spoolss_NotifyOptionType , o - > count ) ;
o - > types [ 0 ] . type = PRINTER_NOTIFY_TYPE ;
o - > types [ 0 ] . count = 1 ;
o - > types [ 0 ] . fields = talloc_array ( o - > types , union spoolss_Field , o - > types [ 0 ] . count ) ;
o - > types [ 0 ] . fields [ 0 ] . field = PRINTER_NOTIFY_FIELD_SERVER_NAME ;
o - > types [ 1 ] . type = JOB_NOTIFY_TYPE ;
o - > types [ 1 ] . count = 1 ;
o - > types [ 1 ] . fields = talloc_array ( o - > types , union spoolss_Field , o - > types [ 1 ] . count ) ;
o - > types [ 1 ] . fields [ 0 ] . field = JOB_NOTIFY_FIELD_MACHINE_NAME ;
return o ;
}
2010-01-31 22:39:36 +03:00
static struct spoolss_NotifyOption * setup_printer_NotifyOption ( struct torture_context * tctx )
{
struct spoolss_NotifyOption * o ;
o = talloc_zero ( tctx , struct spoolss_NotifyOption ) ;
o - > version = 2 ;
o - > flags = PRINTER_NOTIFY_OPTIONS_REFRESH ;
o - > count = 1 ;
o - > types = talloc_zero_array ( o , struct spoolss_NotifyOptionType , o - > count ) ;
o - > types [ 0 ] . type = PRINTER_NOTIFY_TYPE ;
o - > types [ 0 ] . count = 1 ;
o - > types [ 0 ] . fields = talloc_array ( o - > types , union spoolss_Field , o - > types [ 0 ] . count ) ;
o - > types [ 0 ] . fields [ 0 ] . field = PRINTER_NOTIFY_FIELD_COMMENT ;
return o ;
}
2010-01-20 00:18:24 +03:00
static bool test_RemoteFindFirstPrinterChangeNotifyEx ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct policy_handle * handle ,
2010-01-31 22:30:09 +03:00
const char * address ,
struct spoolss_NotifyOption * option )
2007-09-03 17:13:25 +04:00
{
struct spoolss_RemoteFindFirstPrinterChangeNotifyEx r ;
2010-01-20 00:18:24 +03:00
torture_comment ( tctx , " Testing RemoteFindFirstPrinterChangeNotifyEx \n " ) ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
r . in . flags = 0 ;
r . in . local_machine = talloc_asprintf ( tctx , " \\ \\ %s " , address ) ;
r . in . options = 0 ;
2010-01-31 22:30:09 +03:00
r . in . printer_local = 0 ;
r . in . notify_options = option ;
2010-01-20 00:18:24 +03:00
r . in . handle = handle ;
2007-12-13 13:41:47 +03:00
2010-01-20 00:18:24 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx ( p , tctx , & r ) ,
" RemoteFindFirstPrinterChangeNotifyEx failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result ,
" error return code for RemoteFindFirstPrinterChangeNotifyEx " ) ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
return true ;
}
2007-09-03 17:13:25 +04:00
2010-01-31 22:31:00 +03:00
static bool test_RouterRefreshPrinterChangeNotify ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct policy_handle * handle ,
struct spoolss_NotifyOption * options )
{
struct spoolss_RouterRefreshPrinterChangeNotify r ;
struct spoolss_NotifyInfo * info ;
torture_comment ( tctx , " Testing RouterRefreshPrinterChangeNotify \n " ) ;
r . in . handle = handle ;
r . in . change_low = 0 ;
r . in . options = options ;
r . out . info = & info ;
torture_assert_ntstatus_ok ( tctx , dcerpc_spoolss_RouterRefreshPrinterChangeNotify ( p , tctx , & r ) ,
" RouterRefreshPrinterChangeNotify failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result ,
" error return code for RouterRefreshPrinterChangeNotify " ) ;
return true ;
}
2010-01-20 00:18:24 +03:00
static bool test_ClosePrinter ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct policy_handle * handle )
{
struct spoolss_ClosePrinter r ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
r . in . handle = handle ;
r . out . handle = handle ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
torture_comment ( tctx , " Testing ClosePrinter \n " ) ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
torture_assert_ntstatus_ok ( tctx , dcerpc_spoolss_ClosePrinter ( p , tctx , & r ) ,
" ClosePrinter failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result ,
" ClosePrinter failed " ) ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
return true ;
}
2010-01-31 22:39:36 +03:00
static bool test_SetPrinter ( struct torture_context * tctx ,
struct dcerpc_pipe * p ,
struct policy_handle * handle )
{
2010-02-10 02:43:51 +03:00
union spoolss_PrinterInfo info ;
2010-01-31 22:39:36 +03:00
struct spoolss_SetPrinter r ;
struct spoolss_SetPrinterInfo2 info2 ;
struct spoolss_SetPrinterInfoCtr info_ctr ;
struct spoolss_DevmodeContainer devmode_ctr ;
struct sec_desc_buf secdesc_ctr ;
2010-02-10 02:43:51 +03:00
torture_assert ( tctx , test_GetPrinter_level ( tctx , p , handle , 2 , & info ) , " " ) ;
2010-01-31 22:39:36 +03:00
ZERO_STRUCT ( devmode_ctr ) ;
ZERO_STRUCT ( secdesc_ctr ) ;
2010-02-10 02:43:51 +03:00
info2 . servername = info . info2 . servername ;
info2 . printername = info . info2 . printername ;
info2 . sharename = info . info2 . sharename ;
info2 . portname = info . info2 . portname ;
info2 . drivername = info . info2 . drivername ;
2010-01-31 22:39:36 +03:00
info2 . comment = talloc_asprintf ( tctx , " torture_comment %d \n " , ( int ) time ( NULL ) ) ;
2010-02-10 02:43:51 +03:00
info2 . location = info . info2 . location ;
2010-01-31 22:39:36 +03:00
info2 . devmode_ptr = 0 ;
2010-02-10 02:43:51 +03:00
info2 . sepfile = info . info2 . sepfile ;
info2 . printprocessor = info . info2 . printprocessor ;
info2 . datatype = info . info2 . datatype ;
info2 . parameters = info . info2 . parameters ;
2010-01-31 22:39:36 +03:00
info2 . secdesc_ptr = 0 ;
2010-02-10 02:43:51 +03:00
info2 . attributes = info . info2 . attributes ;
info2 . priority = info . info2 . priority ;
info2 . defaultpriority = info . info2 . defaultpriority ;
info2 . starttime = info . info2 . starttime ;
info2 . untiltime = info . info2 . untiltime ;
info2 . status = info . info2 . status ;
info2 . cjobs = info . info2 . cjobs ;
info2 . averageppm = info . info2 . averageppm ;
2010-01-31 22:39:36 +03:00
info_ctr . level = 2 ;
info_ctr . info . info2 = & info2 ;
r . in . handle = handle ;
r . in . info_ctr = & info_ctr ;
r . in . devmode_ctr = & devmode_ctr ;
r . in . secdesc_ctr = & secdesc_ctr ;
r . in . command = 0 ;
torture_assert_ntstatus_ok ( tctx , dcerpc_spoolss_SetPrinter ( p , tctx , & r ) , " SetPrinter failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result , " SetPrinter failed " ) ;
return true ;
}
2010-01-20 00:18:24 +03:00
static bool test_start_dcerpc_server ( struct torture_context * tctx ,
struct tevent_context * event_ctx ,
struct dcesrv_context * * dce_ctx_p ,
const char * * address_p )
{
struct dcesrv_endpoint_server ep_server ;
NTSTATUS status ;
struct dcesrv_context * dce_ctx ;
const char * endpoints [ ] = { " spoolss " , NULL } ;
struct dcesrv_endpoint * e ;
const char * address ;
struct interface * ifaces ;
ntvfs_init ( tctx - > lp_ctx ) ;
2007-09-03 17:13:25 +04:00
/* fill in our name */
ep_server . name = " spoolss " ;
/* fill in all the operations */
ep_server . init_server = spoolss__op_init_server ;
ep_server . interface_by_uuid = spoolss__op_interface_by_uuid ;
ep_server . interface_by_name = spoolss__op_interface_by_name ;
torture_assert_ntstatus_ok ( tctx , dcerpc_register_ep_server ( & ep_server ) ,
" unable to register spoolss server " ) ;
2007-12-03 02:28:22 +03:00
lp_set_cmdline ( tctx - > lp_ctx , " dcerpc endpoint servers " , " spoolss " ) ;
2007-09-03 17:13:25 +04:00
2007-12-12 00:23:20 +03:00
load_interfaces ( tctx , lp_interfaces ( tctx - > lp_ctx ) , & ifaces ) ;
2007-12-12 00:23:14 +03:00
address = iface_n_ip ( ifaces , 0 ) ;
2010-01-20 00:18:24 +03:00
2007-09-03 17:13:25 +04:00
torture_comment ( tctx , " Listening for callbacks on %s \n " , address ) ;
2010-01-20 00:18:24 +03:00
status = smbsrv_add_socket ( event_ctx , tctx - > lp_ctx , & single_ops , address ) ;
2007-09-03 17:13:25 +04:00
torture_assert_ntstatus_ok ( tctx , status , " starting smb server " ) ;
2007-12-04 22:05:00 +03:00
status = dcesrv_init_context ( tctx , tctx - > lp_ctx , endpoints , & dce_ctx ) ;
2010-01-19 16:10:47 +03:00
torture_assert_ntstatus_ok ( tctx , status ,
2007-09-03 17:13:25 +04:00
" unable to initialize DCE/RPC server " ) ;
2009-05-01 20:19:34 +04:00
for ( e = dce_ctx - > endpoint_list ; e ; e = e - > next ) {
status = dcesrv_add_ep ( dce_ctx , tctx - > lp_ctx ,
e , tctx - > ev , & single_ops ) ;
torture_assert_ntstatus_ok ( tctx , status ,
" unable listen on dcerpc endpoint server " ) ;
}
2010-01-20 00:18:24 +03:00
* dce_ctx_p = dce_ctx ;
* address_p = address ;
2007-09-03 17:13:25 +04:00
2010-01-20 00:18:24 +03:00
return true ;
}
2007-09-03 17:13:25 +04:00
2010-01-27 17:04:00 +03:00
static struct received_packet * last_packet ( struct received_packet * p )
{
struct received_packet * tmp ;
for ( tmp = p ; tmp - > next ; tmp = tmp - > next ) ; ;
return tmp ;
}
2010-01-20 00:18:24 +03:00
static bool test_RFFPCNEx ( struct torture_context * tctx ,
struct dcerpc_pipe * p )
{
struct dcesrv_context * dce_ctx ;
struct policy_handle handle ;
const char * address ;
2010-01-27 17:04:00 +03:00
struct received_packet * tmp ;
2010-01-31 22:30:09 +03:00
struct spoolss_NotifyOption * server_option = setup_printserver_NotifyOption ( tctx ) ;
2010-01-31 22:39:36 +03:00
struct spoolss_NotifyOption * printer_option = setup_printer_NotifyOption ( tctx ) ;
2010-01-19 02:27:50 +03:00
2010-01-20 00:18:24 +03:00
received_packets = NULL ;
2010-01-19 02:27:50 +03:00
2010-01-20 00:18:24 +03:00
/* Start DCE/RPC server */
torture_assert ( tctx , test_start_dcerpc_server ( tctx , p - > conn - > event_ctx , & dce_ctx , & address ) , " " ) ;
2010-01-31 22:39:36 +03:00
torture_assert ( tctx , test_OpenPrinter ( tctx , p , & handle , NULL ) , " " ) ;
2010-01-31 22:30:09 +03:00
torture_assert ( tctx , test_RemoteFindFirstPrinterChangeNotifyEx ( tctx , p , & handle , address , server_option ) , " " ) ;
2010-01-20 00:18:24 +03:00
torture_assert ( tctx , received_packets , " no packets received " ) ;
torture_assert_int_equal ( tctx , received_packets - > opnum , NDR_SPOOLSS_REPLYOPENPRINTER ,
" no ReplyOpenPrinter packet after RemoteFindFirstPrinterChangeNotifyEx " ) ;
2010-01-31 22:31:00 +03:00
torture_assert ( tctx , test_RouterRefreshPrinterChangeNotify ( tctx , p , & handle , NULL ) , " " ) ;
torture_assert ( tctx , test_RouterRefreshPrinterChangeNotify ( tctx , p , & handle , server_option ) , " " ) ;
2010-01-20 00:18:24 +03:00
torture_assert ( tctx , test_ClosePrinter ( tctx , p , & handle ) , " " ) ;
2010-01-27 17:04:00 +03:00
tmp = last_packet ( received_packets ) ;
torture_assert_int_equal ( tctx , tmp - > opnum , NDR_SPOOLSS_REPLYCLOSEPRINTER ,
2010-01-20 00:18:24 +03:00
" no ReplyClosePrinter packet after ClosePrinter " ) ;
2010-01-31 22:39:36 +03:00
#if 0
torture_assert ( tctx , test_OpenPrinter ( tctx , p , & handle , " Epson AL-2600 " ) , " " ) ;
torture_assert ( tctx , test_RemoteFindFirstPrinterChangeNotifyEx ( tctx , p , & handle , address , printer_option ) , " " ) ;
tmp = last_packet ( received_packets ) ;
torture_assert_int_equal ( tctx , tmp - > opnum , NDR_SPOOLSS_REPLYOPENPRINTER ,
" no ReplyOpenPrinter packet after RemoteFindFirstPrinterChangeNotifyEx " ) ;
torture_assert ( tctx , test_RouterRefreshPrinterChangeNotify ( tctx , p , & handle , NULL ) , " " ) ;
torture_assert ( tctx , test_RouterRefreshPrinterChangeNotify ( tctx , p , & handle , printer_option ) , " " ) ;
torture_assert ( tctx , test_SetPrinter ( tctx , p , & handle ) , " " ) ;
tmp = last_packet ( received_packets ) ;
torture_assert_int_equal ( tctx , tmp - > opnum , NDR_SPOOLSS_ROUTERREPLYPRINTEREX ,
" no RouterReplyPrinterEx packet after ClosePrinter " ) ;
torture_assert ( tctx , test_ClosePrinter ( tctx , p , & handle ) , " " ) ;
tmp = last_packet ( received_packets ) ;
torture_assert_int_equal ( tctx , tmp - > opnum , NDR_SPOOLSS_REPLYCLOSEPRINTER ,
" no ReplyClosePrinter packet after ClosePrinter " ) ;
# endif
2007-09-03 17:13:25 +04:00
/* Shut down DCE/RPC server */
talloc_free ( dce_ctx ) ;
return true ;
}
2009-04-13 19:05:12 +04:00
/** Test that makes sure that calling ReplyOpenPrinter()
* on Samba 4 will cause an irpc broadcast call .
*/
static bool test_ReplyOpenPrinter ( struct torture_context * tctx ,
2009-05-01 20:20:53 +04:00
struct dcerpc_pipe * p )
2009-04-13 19:05:12 +04:00
{
struct spoolss_ReplyOpenPrinter r ;
struct spoolss_ReplyClosePrinter s ;
struct policy_handle h ;
2010-01-19 02:19:47 +03:00
if ( torture_setting_bool ( tctx , " samba3 " , false ) ) {
torture_skip ( tctx , " skipping ReplyOpenPrinter server implementation test against s3 \n " ) ;
}
2009-04-13 19:05:12 +04:00
r . in . server_name = " earth " ;
r . in . printer_local = 2 ;
r . in . type = REG_DWORD ;
r . in . bufsize = 0 ;
r . in . buffer = NULL ;
r . out . handle = & h ;
torture_assert_ntstatus_ok ( tctx ,
2009-05-01 20:20:53 +04:00
dcerpc_spoolss_ReplyOpenPrinter ( p , tctx , & r ) ,
2009-04-13 19:05:12 +04:00
" spoolss_ReplyOpenPrinter call failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result , " error return code " ) ;
s . in . handle = & h ;
s . out . handle = & h ;
torture_assert_ntstatus_ok ( tctx ,
2009-05-01 20:20:53 +04:00
dcerpc_spoolss_ReplyClosePrinter ( p , tctx , & s ) ,
2009-04-13 19:05:12 +04:00
" spoolss_ReplyClosePrinter call failed " ) ;
torture_assert_werr_ok ( tctx , r . out . result , " error return code " ) ;
return true ;
}
2007-09-03 17:13:25 +04:00
struct torture_suite * torture_rpc_spoolss_notify ( TALLOC_CTX * mem_ctx )
{
struct torture_suite * suite = torture_suite_create ( mem_ctx , " SPOOLSS-NOTIFY " ) ;
2010-01-19 16:10:47 +03:00
struct torture_rpc_tcase * tcase = torture_suite_add_rpc_iface_tcase ( suite ,
2007-09-03 17:13:25 +04:00
" notify " , & ndr_table_spoolss ) ;
torture_rpc_tcase_add_test ( tcase , " testRFFPCNEx " , test_RFFPCNEx ) ;
2009-04-13 19:05:12 +04:00
torture_rpc_tcase_add_test ( tcase , " testReplyOpenPrinter " , test_ReplyOpenPrinter ) ;
2010-01-19 16:10:47 +03:00
2007-09-03 17:13:25 +04:00
return suite ;
}