LCOV - code coverage report
Current view: top level - source4/torture/rpc - spoolss_notify.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 176 251 70.1 %
Date: 2024-04-21 15:09:00 Functions: 19 23 82.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for spoolss rpc notify operations
       4             : 
       5             :    Copyright (C) Jelmer Vernooij 2007
       6             :    Copyright (C) Guenther Deschner 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "system/filesys.h"
      25             : #include "librpc/gen_ndr/ndr_spoolss_c.h"
      26             : #include "librpc/gen_ndr/ndr_spoolss.h"
      27             : #include "torture/rpc/torture_rpc.h"
      28             : #include "rpc_server/dcerpc_server.h"
      29             : #include "rpc_server/dcerpc_server_proto.h"
      30             : #include "rpc_server/service_rpc.h"
      31             : #include "samba/process_model.h"
      32             : #include "smb_server/smb_server.h"
      33             : #include "lib/socket/netif.h"
      34             : #include "ntvfs/ntvfs.h"
      35             : #include "param/param.h"
      36             : 
      37             : static struct dcesrv_context_callbacks srv_cb = {
      38             :         .log.successful_authz = log_successful_dcesrv_authz_event,
      39             :         .auth.gensec_prepare = dcesrv_gensec_prepare,
      40             :         .assoc_group.find = dcesrv_assoc_group_find_s4,
      41             : };
      42             : 
      43           2 : static NTSTATUS spoolss__op_bind(struct dcesrv_connection_context *context,
      44             :                                  const struct dcesrv_interface *iface)
      45             : {
      46           2 :         return NT_STATUS_OK;
      47             : }
      48             : 
      49           2 : static void spoolss__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
      50             : {
      51           2 : }
      52             : 
      53           4 : static NTSTATUS spoolss__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
      54             : {
      55           0 :         enum ndr_err_code ndr_err;
      56           4 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
      57             : 
      58           4 :         dce_call->fault_code = 0;
      59             : 
      60           4 :         if (opnum >= ndr_table_spoolss.num_calls) {
      61           0 :                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
      62           0 :                 return NT_STATUS_NET_WRITE_FAULT;
      63             :         }
      64             : 
      65           4 :         *r = talloc_size(mem_ctx, ndr_table_spoolss.calls[opnum].struct_size);
      66           4 :         NT_STATUS_HAVE_NO_MEMORY(*r);
      67             : 
      68             :         /* unravel the NDR for the packet */
      69           4 :         ndr_err = ndr_table_spoolss.calls[opnum].ndr_pull(pull, NDR_IN, *r);
      70           4 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      71           0 :                 dce_call->fault_code = DCERPC_FAULT_NDR;
      72           0 :                 return NT_STATUS_NET_WRITE_FAULT;
      73             :         }
      74             : 
      75           4 :         return NT_STATUS_OK;
      76             : }
      77             : 
      78             : /* Note that received_packets are allocated on the NULL context
      79             :  * because no other context appears to stay around long enough. */
      80             : static struct received_packet {
      81             :         uint16_t opnum;
      82             :         void *r;
      83             :         struct received_packet *prev, *next;
      84             : } *received_packets = NULL;
      85             : 
      86           4 : static void free_received_packets(void)
      87             : {
      88           0 :         struct received_packet *rp;
      89           0 :         struct received_packet *rp_next;
      90             : 
      91           8 :         for (rp = received_packets; rp; rp = rp_next) {
      92           4 :                 rp_next = rp->next;
      93           4 :                 DLIST_REMOVE(received_packets, rp);
      94           4 :                 talloc_unlink(rp, rp->r);
      95           4 :                 talloc_free(rp);
      96             :         }
      97           4 :         received_packets = NULL;
      98           4 : }
      99             : 
     100           2 : static WERROR _spoolss_ReplyOpenPrinter(struct dcesrv_call_state *dce_call,
     101             :                                         TALLOC_CTX *mem_ctx,
     102             :                                         struct spoolss_ReplyOpenPrinter *r)
     103             : {
     104           2 :         DEBUG(1,("_spoolss_ReplyOpenPrinter\n"));
     105             : 
     106           2 :         NDR_PRINT_IN_DEBUG(spoolss_ReplyOpenPrinter, r);
     107             : 
     108           2 :         r->out.handle = talloc(r, struct policy_handle);
     109           2 :         r->out.handle->handle_type = 42;
     110           2 :         r->out.handle->uuid = GUID_random();
     111           2 :         r->out.result = WERR_OK;
     112             : 
     113           2 :         NDR_PRINT_OUT_DEBUG(spoolss_ReplyOpenPrinter, r);
     114             : 
     115           2 :         return WERR_OK;
     116             : }
     117             : 
     118           2 : static WERROR _spoolss_ReplyClosePrinter(struct dcesrv_call_state *dce_call,
     119             :                                          TALLOC_CTX *mem_ctx,
     120             :                                          struct spoolss_ReplyClosePrinter *r)
     121             : {
     122           2 :         DEBUG(1,("_spoolss_ReplyClosePrinter\n"));
     123             : 
     124           2 :         NDR_PRINT_IN_DEBUG(spoolss_ReplyClosePrinter, r);
     125             : 
     126           2 :         ZERO_STRUCTP(r->out.handle);
     127           2 :         r->out.result = WERR_OK;
     128             : 
     129           2 :         NDR_PRINT_OUT_DEBUG(spoolss_ReplyClosePrinter, r);
     130             : 
     131           2 :         return WERR_OK;
     132             : }
     133             : 
     134           0 : static WERROR _spoolss_RouterReplyPrinterEx(struct dcesrv_call_state *dce_call,
     135             :                                             TALLOC_CTX *mem_ctx,
     136             :                                             struct spoolss_RouterReplyPrinterEx *r)
     137             : {
     138           0 :         DEBUG(1,("_spoolss_RouterReplyPrinterEx\n"));
     139             : 
     140           0 :         NDR_PRINT_IN_DEBUG(spoolss_RouterReplyPrinterEx, r);
     141             : 
     142           0 :         r->out.reply_result = talloc(r, uint32_t);
     143           0 :         *r->out.reply_result = 0;
     144           0 :         r->out.result = WERR_OK;
     145             : 
     146           0 :         NDR_PRINT_OUT_DEBUG(spoolss_RouterReplyPrinterEx, r);
     147             : 
     148           0 :         return WERR_OK;
     149             : }
     150             : 
     151           4 : static NTSTATUS spoolss__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
     152             : {
     153           4 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     154           0 :         struct received_packet *rp;
     155             : 
     156           4 :         rp = talloc_zero(NULL, struct received_packet);
     157           4 :         rp->opnum = opnum;
     158           4 :         rp->r = talloc_reference(rp, r);
     159             : 
     160           4 :         DLIST_ADD_END(received_packets, rp);
     161             : 
     162           4 :         switch (opnum) {
     163           2 :         case 58: {
     164           2 :                 struct spoolss_ReplyOpenPrinter *r2 = (struct spoolss_ReplyOpenPrinter *)r;
     165           2 :                 r2->out.result = _spoolss_ReplyOpenPrinter(dce_call, mem_ctx, r2);
     166           2 :                 break;
     167             :         }
     168           2 :         case 60: {
     169           2 :                 struct spoolss_ReplyClosePrinter *r2 = (struct spoolss_ReplyClosePrinter *)r;
     170           2 :                 r2->out.result = _spoolss_ReplyClosePrinter(dce_call, mem_ctx, r2);
     171           2 :                 break;
     172             :         }
     173           0 :         case 66: {
     174           0 :                 struct spoolss_RouterReplyPrinterEx *r2 = (struct spoolss_RouterReplyPrinterEx *)r;
     175           0 :                 r2->out.result = _spoolss_RouterReplyPrinterEx(dce_call, mem_ctx, r2);
     176           0 :                 break;
     177             :         }
     178             : 
     179           0 :         default:
     180           0 :                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
     181           0 :                 break;
     182             :         }
     183             : 
     184           4 :         if (dce_call->fault_code != 0) {
     185           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     186             :         }
     187           4 :         return NT_STATUS_OK;
     188             : }
     189             : 
     190             : 
     191           4 : static NTSTATUS spoolss__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
     192             : {
     193           4 :         return NT_STATUS_OK;
     194             : }
     195             : 
     196             : 
     197           4 : static NTSTATUS spoolss__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
     198             : {
     199           0 :         enum ndr_err_code ndr_err;
     200           4 :         uint16_t opnum = dce_call->pkt.u.request.opnum;
     201             : 
     202           4 :         ndr_err = ndr_table_spoolss.calls[opnum].ndr_push(push, NDR_OUT, r);
     203           4 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     204           0 :                 dce_call->fault_code = DCERPC_FAULT_NDR;
     205           0 :                 return NT_STATUS_NET_WRITE_FAULT;
     206             :         }
     207             : 
     208           4 :         return NT_STATUS_OK;
     209             : }
     210             : 
     211             : static const struct dcesrv_interface notify_test_spoolss_interface = {
     212             :         .name           = "spoolss",
     213             :         .syntax_id  = {{0x12345678,0x1234,0xabcd,{0xef,0x00},{0x01,0x23,0x45,0x67,0x89,0xab}},1.0},
     214             :         .bind           = spoolss__op_bind,
     215             :         .unbind         = spoolss__op_unbind,
     216             :         .ndr_pull       = spoolss__op_ndr_pull,
     217             :         .dispatch       = spoolss__op_dispatch,
     218             :         .reply          = spoolss__op_reply,
     219             :         .ndr_push       = spoolss__op_ndr_push
     220             : };
     221             : 
     222           0 : static bool spoolss__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
     223             : {
     224           0 :         if (notify_test_spoolss_interface.syntax_id.if_version == if_version &&
     225           0 :                 GUID_equal(&notify_test_spoolss_interface.syntax_id.uuid, uuid)) {
     226           0 :                 memcpy(iface,&notify_test_spoolss_interface, sizeof(*iface));
     227           0 :                 return true;
     228             :         }
     229             : 
     230           0 :         return false;
     231             : }
     232             : 
     233           0 : static bool spoolss__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
     234             : {
     235           0 :         if (strcmp(notify_test_spoolss_interface.name, name)==0) {
     236           0 :                 memcpy(iface, &notify_test_spoolss_interface, sizeof(*iface));
     237           0 :                 return true;
     238             :         }
     239             : 
     240           0 :         return false;
     241             : }
     242             : 
     243           2 : static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
     244             : {
     245           0 :         uint32_t i;
     246             : 
     247           6 :         for (i=0;i<ndr_table_spoolss.endpoints->count;i++) {
     248           0 :                 NTSTATUS ret;
     249           4 :                 const char *name = ndr_table_spoolss.endpoints->names[i];
     250             : 
     251           4 :                 ret = dcesrv_interface_register(dce_ctx,
     252             :                                                 name,
     253             :                                                 NULL,
     254             :                                                 &notify_test_spoolss_interface,
     255             :                                                 NULL);
     256           4 :                 if (!NT_STATUS_IS_OK(ret)) {
     257           0 :                         DEBUG(1,("spoolss_op_init_server: failed to register endpoint '%s'\n",name));
     258           0 :                         return ret;
     259             :                 }
     260             :         }
     261             : 
     262           2 :         return NT_STATUS_OK;
     263             : }
     264             : 
     265           0 : static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
     266             :                                 const struct dcesrv_endpoint_server *ep_server)
     267             : {
     268           0 :         return NT_STATUS_OK;
     269             : }
     270             : 
     271           2 : static bool test_OpenPrinter(struct torture_context *tctx,
     272             :                              struct dcerpc_pipe *p,
     273             :                              struct policy_handle *handle,
     274             :                              const char *printername)
     275             : {
     276           0 :         struct spoolss_OpenPrinter r;
     277           2 :         struct dcerpc_binding_handle *b = p->binding_handle;
     278             : 
     279           2 :         ZERO_STRUCT(r);
     280             : 
     281           2 :         r.in.printername        = printername;
     282           2 :         r.in.datatype           = NULL;
     283           2 :         r.in.devmode_ctr.devmode= NULL;
     284           2 :         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
     285           2 :         r.out.handle            = handle;
     286             : 
     287           2 :         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
     288             : 
     289           2 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinter_r(b, tctx, &r),
     290             :                 "OpenPrinter failed");
     291           2 :         torture_assert_werr_ok(tctx, r.out.result,
     292             :                 "OpenPrinter failed");
     293             : 
     294           2 :         return true;
     295             : }
     296             : 
     297           2 : static struct spoolss_NotifyOption *setup_printserver_NotifyOption(struct torture_context *tctx)
     298             : {
     299           0 :         struct spoolss_NotifyOption *o;
     300             : 
     301           2 :         o = talloc_zero(tctx, struct spoolss_NotifyOption);
     302             : 
     303           2 :         o->version = 2;
     304           2 :         o->flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
     305             : 
     306           2 :         o->count = 2;
     307           2 :         o->types = talloc_zero_array(o, struct spoolss_NotifyOptionType, o->count);
     308             : 
     309           2 :         o->types[0].type = PRINTER_NOTIFY_TYPE;
     310           2 :         o->types[0].count = 1;
     311           2 :         o->types[0].fields = talloc_array(o->types, union spoolss_Field, o->types[0].count);
     312           2 :         o->types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
     313             : 
     314           2 :         o->types[1].type = JOB_NOTIFY_TYPE;
     315           2 :         o->types[1].count = 1;
     316           2 :         o->types[1].fields = talloc_array(o->types, union spoolss_Field, o->types[1].count);
     317           2 :         o->types[1].fields[0].field = JOB_NOTIFY_FIELD_MACHINE_NAME;
     318             : 
     319           2 :         return o;
     320             : }
     321             : 
     322             : #if 0
     323             : static struct spoolss_NotifyOption *setup_printer_NotifyOption(struct torture_context *tctx)
     324             : {
     325             :         struct spoolss_NotifyOption *o;
     326             : 
     327             :         o = talloc_zero(tctx, struct spoolss_NotifyOption);
     328             : 
     329             :         o->version = 2;
     330             :         o->flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
     331             : 
     332             :         o->count = 1;
     333             :         o->types = talloc_zero_array(o, struct spoolss_NotifyOptionType, o->count);
     334             : 
     335             :         o->types[0].type = PRINTER_NOTIFY_TYPE;
     336             :         o->types[0].count = 1;
     337             :         o->types[0].fields = talloc_array(o->types, union spoolss_Field, o->types[0].count);
     338             :         o->types[0].fields[0].field = PRINTER_NOTIFY_FIELD_COMMENT;
     339             : 
     340             :         return o;
     341             : }
     342             : #endif
     343             : 
     344           2 : static bool test_RemoteFindFirstPrinterChangeNotifyEx(struct torture_context *tctx,
     345             :                                                       struct dcerpc_binding_handle *b,
     346             :                                                       struct policy_handle *handle,
     347             :                                                       const char *address,
     348             :                                                       struct spoolss_NotifyOption *option)
     349             : {
     350           0 :         struct spoolss_RemoteFindFirstPrinterChangeNotifyEx r;
     351           2 :         const char *local_machine = talloc_asprintf(tctx, "\\\\%s", address);
     352             : 
     353           2 :         torture_comment(tctx, "Testing RemoteFindFirstPrinterChangeNotifyEx(%s)\n", local_machine);
     354             : 
     355           2 :         r.in.flags = 0;
     356           2 :         r.in.local_machine = local_machine;
     357           2 :         r.in.options = 0;
     358           2 :         r.in.printer_local = 0;
     359           2 :         r.in.notify_options = option;
     360           2 :         r.in.handle = handle;
     361             : 
     362           2 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx_r(b, tctx, &r),
     363             :                 "RemoteFindFirstPrinterChangeNotifyEx failed");
     364           2 :         torture_assert_werr_ok(tctx, r.out.result,
     365             :                 "error return code for RemoteFindFirstPrinterChangeNotifyEx");
     366             : 
     367           2 :         return true;
     368             : }
     369             : 
     370           4 : static bool test_RouterRefreshPrinterChangeNotify(struct torture_context *tctx,
     371             :                                                   struct dcerpc_binding_handle *b,
     372             :                                                   struct policy_handle *handle,
     373             :                                                   struct spoolss_NotifyOption *options,
     374             :                                                   struct spoolss_NotifyInfo **info)
     375             : {
     376           0 :         struct spoolss_RouterRefreshPrinterChangeNotify r;
     377             : 
     378           4 :         torture_comment(tctx, "Testing RouterRefreshPrinterChangeNotify\n");
     379             : 
     380           4 :         r.in.handle = handle;
     381           4 :         r.in.change_low = 0;
     382           4 :         r.in.options = options;
     383           4 :         r.out.info = info;
     384             : 
     385           4 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_RouterRefreshPrinterChangeNotify_r(b, tctx, &r),
     386             :                 "RouterRefreshPrinterChangeNotify failed");
     387           4 :         torture_assert_werr_ok(tctx, r.out.result,
     388             :                 "error return code for RouterRefreshPrinterChangeNotify");
     389             : 
     390           4 :         return true;
     391             : }
     392             : 
     393             : #if 0
     394             : static bool test_SetPrinter(struct torture_context *tctx,
     395             :                             struct dcerpc_pipe *p,
     396             :                             struct policy_handle *handle)
     397             : {
     398             :         union spoolss_PrinterInfo info;
     399             :         struct spoolss_SetPrinter r;
     400             :         struct spoolss_SetPrinterInfo2 info2;
     401             :         struct spoolss_SetPrinterInfoCtr info_ctr;
     402             :         struct spoolss_DevmodeContainer devmode_ctr;
     403             :         struct sec_desc_buf secdesc_ctr;
     404             :         struct dcerpc_binding_handle *b = p->binding_handle;
     405             : 
     406             :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
     407             : 
     408             :         ZERO_STRUCT(devmode_ctr);
     409             :         ZERO_STRUCT(secdesc_ctr);
     410             : 
     411             :         info2.servername        = info.info2.servername;
     412             :         info2.printername       = info.info2.printername;
     413             :         info2.sharename         = info.info2.sharename;
     414             :         info2.portname          = info.info2.portname;
     415             :         info2.drivername        = info.info2.drivername;
     416             :         info2.comment           = talloc_asprintf(tctx, "torture_comment %d\n", (int)time(NULL));
     417             :         info2.location          = info.info2.location;
     418             :         info2.devmode_ptr       = 0;
     419             :         info2.sepfile           = info.info2.sepfile;
     420             :         info2.printprocessor    = info.info2.printprocessor;
     421             :         info2.datatype          = info.info2.datatype;
     422             :         info2.parameters        = info.info2.parameters;
     423             :         info2.secdesc_ptr       = 0;
     424             :         info2.attributes        = info.info2.attributes;
     425             :         info2.priority          = info.info2.priority;
     426             :         info2.defaultpriority   = info.info2.defaultpriority;
     427             :         info2.starttime         = info.info2.starttime;
     428             :         info2.untiltime         = info.info2.untiltime;
     429             :         info2.status            = info.info2.status;
     430             :         info2.cjobs             = info.info2.cjobs;
     431             :         info2.averageppm        = info.info2.averageppm;
     432             : 
     433             :         info_ctr.level = 2;
     434             :         info_ctr.info.info2 = &info2;
     435             : 
     436             :         r.in.handle = handle;
     437             :         r.in.info_ctr = &info_ctr;
     438             :         r.in.devmode_ctr = &devmode_ctr;
     439             :         r.in.secdesc_ctr = &secdesc_ctr;
     440             :         r.in.command = 0;
     441             : 
     442             :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r), "SetPrinter failed");
     443             :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
     444             : 
     445             :         return true;
     446             : }
     447             : #endif
     448             : 
     449           2 : static bool test_start_dcerpc_server(struct torture_context *tctx,
     450             :                                      struct tevent_context *event_ctx,
     451             :                                      struct dcesrv_context **dce_ctx_p,
     452             :                                      const char **address_p)
     453             : {
     454           0 :         struct dcesrv_endpoint_server ep_server;
     455           0 :         NTSTATUS status;
     456           0 :         struct dcesrv_context *dce_ctx;
     457           2 :         const char *endpoints[] = { "spoolss", NULL };
     458           0 :         struct dcesrv_endpoint *e;
     459           0 :         const char *address;
     460           0 :         struct interface *ifaces;
     461             : 
     462           2 :         ntvfs_init(tctx->lp_ctx);
     463             : 
     464             :         /* fill in our name */
     465           2 :         ep_server.name = "spoolss";
     466             : 
     467           2 :         ep_server.initialized = false;
     468             : 
     469             :         /* fill in all the operations */
     470           2 :         ep_server.init_server = spoolss__op_init_server;
     471           2 :         ep_server.shutdown_server = spoolss__op_shutdown_server;
     472             : 
     473           2 :         ep_server.interface_by_uuid = spoolss__op_interface_by_uuid;
     474           2 :         ep_server.interface_by_name = spoolss__op_interface_by_name;
     475             : 
     476           2 :         torture_assert_ntstatus_ok(tctx, dcerpc_register_ep_server(&ep_server),
     477             :                                   "unable to register spoolss server");
     478             : 
     479           2 :         lpcfg_set_cmdline(tctx->lp_ctx, "dcerpc endpoint servers", "spoolss");
     480             : 
     481           2 :         load_interface_list(tctx, tctx->lp_ctx, &ifaces);
     482           2 :         address = iface_list_first_v4(ifaces);
     483             : 
     484           2 :         torture_comment(tctx, "Listening for callbacks on %s\n", address);
     485             : 
     486           2 :         status = process_model_init(tctx->lp_ctx);
     487           2 :         torture_assert_ntstatus_ok(tctx, status,
     488             :                                    "unable to initialize process models");
     489             : 
     490           2 :         status = smbsrv_add_socket(tctx, event_ctx, tctx->lp_ctx,
     491             :                                    process_model_startup("single"),
     492             :                                    address, NULL);
     493           2 :         torture_assert_ntstatus_ok(tctx, status, "starting smb server");
     494             : 
     495           2 :         status = dcesrv_init_context(tctx, tctx->lp_ctx, &srv_cb, &dce_ctx);
     496           2 :         torture_assert_ntstatus_ok(tctx, status,
     497             :                                    "unable to initialize DCE/RPC server");
     498             : 
     499           2 :         status = dcesrv_init_ep_servers(dce_ctx, endpoints);
     500           2 :         torture_assert_ntstatus_ok(tctx,
     501             :                                    status,
     502             :                                    "unable to initialize DCE/RPC ep servers");
     503             : 
     504           6 :         for (e=dce_ctx->endpoint_list;e;e=e->next) {
     505           4 :                 status = dcesrv_add_ep(dce_ctx, tctx->lp_ctx,
     506             :                                        e, tctx->ev,
     507             :                                        process_model_startup("single"), NULL);
     508           4 :                 torture_assert_ntstatus_ok(tctx, status,
     509             :                                 "unable listen on dcerpc endpoint server");
     510             :         }
     511             : 
     512           2 :         *dce_ctx_p = dce_ctx;
     513           2 :         *address_p = address;
     514             : 
     515           2 :         return true;
     516             : }
     517             : 
     518           2 : static struct received_packet *last_packet(struct received_packet *p)
     519             : {
     520           0 :         struct received_packet *tmp;
     521           4 :         for (tmp = p; tmp->next; tmp = tmp->next) {
     522             :         }
     523           2 :         return tmp;
     524             : }
     525             : 
     526           2 : static bool test_RFFPCNEx(struct torture_context *tctx,
     527             :                           struct dcerpc_pipe *p)
     528             : {
     529           0 :         struct dcesrv_context *dce_ctx;
     530           0 :         struct policy_handle handle;
     531           0 :         const char *address;
     532           0 :         struct received_packet *tmp;
     533           2 :         struct spoolss_NotifyOption *server_option = setup_printserver_NotifyOption(tctx);
     534             : #if 0
     535             :         struct spoolss_NotifyOption *printer_option = setup_printer_NotifyOption(tctx);
     536             : #endif
     537           2 :         struct dcerpc_binding_handle *b = p->binding_handle;
     538           2 :         const char *printername = NULL;
     539           2 :         struct spoolss_NotifyInfo *info = NULL;
     540             : 
     541           2 :         free_received_packets();
     542             : 
     543             :         /* Start DCE/RPC server */
     544           2 :         torture_assert(tctx, test_start_dcerpc_server(tctx, tctx->ev, &dce_ctx, &address), "");
     545             : 
     546           2 :         printername     = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     547             : 
     548           2 :         torture_assert(tctx, test_OpenPrinter(tctx, p, &handle, printername), "");
     549           2 :         torture_assert(tctx, test_RemoteFindFirstPrinterChangeNotifyEx(tctx, b, &handle, address, server_option), "");
     550           2 :         torture_assert(tctx, received_packets, "no packets received");
     551           2 :         torture_assert_int_equal(tctx, received_packets->opnum, NDR_SPOOLSS_REPLYOPENPRINTER,
     552             :                 "no ReplyOpenPrinter packet after RemoteFindFirstPrinterChangeNotifyEx");
     553           2 :         torture_assert(tctx, test_RouterRefreshPrinterChangeNotify(tctx, b, &handle, NULL, &info), "");
     554           2 :         torture_assert(tctx, test_RouterRefreshPrinterChangeNotify(tctx, b, &handle, server_option, &info), "");
     555           2 :         torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
     556           2 :         tmp = last_packet(received_packets);
     557           2 :         torture_assert_int_equal(tctx, tmp->opnum, NDR_SPOOLSS_REPLYCLOSEPRINTER,
     558             :                 "no ReplyClosePrinter packet after ClosePrinter");
     559             : #if 0
     560             :         printername     = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
     561             : 
     562             :         torture_assert(tctx, test_OpenPrinter(tctx, p, &handle, "Epson AL-2600"), "");
     563             :         torture_assert(tctx, test_RemoteFindFirstPrinterChangeNotifyEx(tctx, p, &handle, address, printer_option), "");
     564             :         tmp = last_packet(received_packets);
     565             :         torture_assert_int_equal(tctx, tmp->opnum, NDR_SPOOLSS_REPLYOPENPRINTER,
     566             :                 "no ReplyOpenPrinter packet after RemoteFindFirstPrinterChangeNotifyEx");
     567             :         torture_assert(tctx, test_RouterRefreshPrinterChangeNotify(tctx, p, &handle, NULL, &info), "");
     568             :         torture_assert(tctx, test_RouterRefreshPrinterChangeNotify(tctx, p, &handle, printer_option, &info), "");
     569             :         torture_assert(tctx, test_SetPrinter(tctx, p, &handle), "");
     570             :         tmp = last_packet(received_packets);
     571             :         torture_assert_int_equal(tctx, tmp->opnum, NDR_SPOOLSS_ROUTERREPLYPRINTEREX,
     572             :                 "no RouterReplyPrinterEx packet after ClosePrinter");
     573             :         torture_assert(tctx, test_ClosePrinter(tctx, p, &handle), "");
     574             :         tmp = last_packet(received_packets);
     575             :         torture_assert_int_equal(tctx, tmp->opnum, NDR_SPOOLSS_REPLYCLOSEPRINTER,
     576             :                 "no ReplyClosePrinter packet after ClosePrinter");
     577             : #endif
     578             :         /* Shut down DCE/RPC server */
     579           2 :         talloc_free(dce_ctx);
     580           2 :         free_received_packets();
     581             : 
     582           2 :         return true;
     583             : }
     584             : 
     585             : /** Test that makes sure that calling ReplyOpenPrinter()
     586             :  * on Samba 4 will cause an irpc broadcast call.
     587             :  */
     588           2 : static bool test_ReplyOpenPrinter(struct torture_context *tctx,
     589             :                                   struct dcerpc_pipe *p)
     590             : {
     591           0 :         struct spoolss_ReplyOpenPrinter r;
     592           0 :         struct spoolss_ReplyClosePrinter s;
     593           0 :         struct policy_handle h;
     594           2 :         struct dcerpc_binding_handle *b = p->binding_handle;
     595             : 
     596           2 :         if (torture_setting_bool(tctx, "samba3", false)) {
     597           2 :                 torture_skip(tctx, "skipping ReplyOpenPrinter server implementation test against s3\n");
     598             :         }
     599             : 
     600           0 :         r.in.server_name = "earth";
     601           0 :         r.in.printer_local = 2;
     602           0 :         r.in.type = REG_DWORD;
     603           0 :         r.in.bufsize = 0;
     604           0 :         r.in.buffer = NULL;
     605           0 :         r.out.handle = &h;
     606             : 
     607           0 :         torture_assert_ntstatus_ok(tctx,
     608             :                         dcerpc_spoolss_ReplyOpenPrinter_r(b, tctx, &r),
     609             :                         "spoolss_ReplyOpenPrinter call failed");
     610             : 
     611           0 :         torture_assert_werr_ok(tctx, r.out.result, "error return code");
     612             : 
     613           0 :         s.in.handle = &h;
     614           0 :         s.out.handle = &h;
     615             : 
     616           0 :         torture_assert_ntstatus_ok(tctx,
     617             :                         dcerpc_spoolss_ReplyClosePrinter_r(b, tctx, &s),
     618             :                         "spoolss_ReplyClosePrinter call failed");
     619             : 
     620           0 :         torture_assert_werr_ok(tctx, r.out.result, "error return code");
     621             : 
     622           0 :         return true;
     623             : }
     624             : 
     625        1515 : struct torture_suite *torture_rpc_spoolss_notify(TALLOC_CTX *mem_ctx)
     626             : {
     627        1515 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.notify");
     628             : 
     629        1515 :         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
     630             :                                                         "notify", &ndr_table_spoolss);
     631             : 
     632        1515 :         torture_rpc_tcase_add_test(tcase, "testRFFPCNEx", test_RFFPCNEx);
     633        1515 :         torture_rpc_tcase_add_test(tcase, "testReplyOpenPrinter", test_ReplyOpenPrinter);
     634             : 
     635        1515 :         return suite;
     636             : }

Generated by: LCOV version 1.14