2 Unix SMB/CIFS implementation.
3 test suite for iremotewinspool rpc operations
5 Copyright (C) Guenther Deschner 2013
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "torture/torture.h"
23 #include "librpc/gen_ndr/ndr_winspool.h"
24 #include "librpc/gen_ndr/ndr_winspool_c.h"
25 #include "torture/rpc/torture_rpc.h"
26 #include "libcli/registry/util_reg.h"
28 struct test_iremotewinspool_context
{
29 struct GUID object_uuid
;
30 struct dcerpc_pipe
*iremotewinspool_pipe
;
31 struct policy_handle server_handle
;
32 const char *environment
;
35 static bool test_AsyncOpenPrinter_byprinter(struct torture_context
*tctx
,
36 struct test_iremotewinspool_context
*ctx
,
37 struct dcerpc_pipe
*p
,
38 const char *printer_name
,
39 struct policy_handle
*handle
)
41 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
42 struct spoolss_DevmodeContainer devmode_ctr
;
43 struct spoolss_UserLevelCtr client_info_ctr
;
44 struct spoolss_UserLevel1 level1
;
45 uint32_t access_mask
= SERVER_ALL_ACCESS
;
46 struct winspool_AsyncOpenPrinter r
;
48 ZERO_STRUCT(devmode_ctr
);
51 level1
.client
= talloc_asprintf(tctx
, "\\\\%s", "mthelena");
56 level1
.processor
= PROCESSOR_ARCHITECTURE_AMD64
;
58 client_info_ctr
.level
= 1;
59 client_info_ctr
.user_info
.level1
= &level1
;
61 r
.in
.pPrinterName
= printer_name
;
62 r
.in
.pDatatype
= NULL
;
63 r
.in
.pDevModeContainer
= &devmode_ctr
;
64 r
.in
.AccessRequired
= access_mask
;
65 r
.in
.pClientInfo
= &client_info_ctr
;
66 r
.out
.pHandle
= handle
;
68 torture_assert_ntstatus_ok(tctx
,
69 dcerpc_winspool_AsyncOpenPrinter_r(b
, tctx
, &r
),
70 "AsyncOpenPrinter failed");
71 torture_assert_werr_ok(tctx
, r
.out
.result
,
72 "AsyncOpenPrinter failed");
77 static bool test_AsyncClosePrinter_byhandle(struct torture_context
*tctx
,
78 struct test_iremotewinspool_context
*ctx
,
79 struct dcerpc_pipe
*p
,
80 struct policy_handle
*handle
)
82 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
84 struct winspool_AsyncClosePrinter r
;
86 r
.in
.phPrinter
= handle
;
87 r
.out
.phPrinter
= handle
;
89 torture_assert_ntstatus_ok(tctx
,
90 dcerpc_winspool_AsyncClosePrinter_r(b
, tctx
, &r
),
91 "AsyncClosePrinter failed");
92 torture_assert_werr_ok(tctx
, r
.out
.result
,
93 "AsyncClosePrinter failed");
98 static bool test_AsyncGetPrinterData_checktype(struct torture_context
*tctx
,
99 struct dcerpc_binding_handle
*b
,
100 struct policy_handle
*handle
,
101 const char *value_name
,
102 enum winreg_Type
*expected_type
,
103 enum winreg_Type
*type_p
,
107 struct winspool_AsyncGetPrinterData r
;
108 enum winreg_Type type
;
111 r
.in
.hPrinter
= *handle
;
112 r
.in
.pValueName
= value_name
;
115 r
.out
.pData
= talloc_zero_array(tctx
, uint8_t, r
.in
.nSize
);
116 r
.out
.pcbNeeded
= &needed
;
118 torture_comment(tctx
, "Testing AsyncGetPrinterData(%s)\n",
121 torture_assert_ntstatus_ok(tctx
,
122 dcerpc_winspool_AsyncGetPrinterData_r(b
, tctx
, &r
),
123 "AsyncGetPrinterData failed");
125 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
127 torture_assert_int_equal(tctx
, type
, *expected_type
, "unexpected type");
130 r
.out
.pData
= talloc_zero_array(tctx
, uint8_t, r
.in
.nSize
);
132 torture_assert_ntstatus_ok(tctx
,
133 dcerpc_winspool_AsyncGetPrinterData_r(b
, tctx
, &r
),
134 "AsyncGetPrinterData failed");
137 torture_assert_werr_ok(tctx
, r
.out
.result
,
138 "AsyncGetPrinterData failed");
145 *data_p
= r
.out
.pData
;
155 static bool test_AsyncGetPrinterData(struct torture_context
*tctx
,
156 struct dcerpc_binding_handle
*b
,
157 struct policy_handle
*handle
,
158 const char *value_name
,
159 enum winreg_Type
*type_p
,
163 return test_AsyncGetPrinterData_checktype(tctx
, b
, handle
,
166 type_p
, data_p
, needed_p
);
169 static bool test_get_environment(struct torture_context
*tctx
,
170 struct dcerpc_binding_handle
*b
,
171 struct policy_handle
*handle
,
172 const char **architecture
)
175 enum winreg_Type type
;
180 test_AsyncGetPrinterData(tctx
, b
, handle
, "Architecture", &type
, &data
, &needed
),
181 "failed to get Architecture");
183 torture_assert_int_equal(tctx
, type
, REG_SZ
, "unexpected type");
185 blob
= data_blob_const(data
, needed
);
188 pull_reg_sz(tctx
, &blob
, architecture
),
189 "failed to pull environment");
194 static bool torture_rpc_iremotewinspool_setup_common(struct torture_context
*tctx
,
195 struct test_iremotewinspool_context
*t
)
197 const char *printer_name
;
198 struct dcerpc_binding
*binding
;
200 torture_assert_ntstatus_ok(tctx
,
201 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID
, &t
->object_uuid
),
202 "failed to parse GUID");
204 torture_assert_ntstatus_ok(tctx
,
205 torture_rpc_binding(tctx
, &binding
),
206 "failed to retrieve torture binding");
208 torture_assert_ntstatus_ok(tctx
,
209 dcerpc_binding_set_object(binding
, t
->object_uuid
),
210 "failed to set object_uuid");
212 torture_assert_ntstatus_ok(tctx
,
213 torture_rpc_connection_with_binding(tctx
, binding
, &t
->iremotewinspool_pipe
, &ndr_table_iremotewinspool
),
214 "Error connecting to server");
216 printer_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(t
->iremotewinspool_pipe
));
219 test_AsyncOpenPrinter_byprinter(tctx
, t
,
220 t
->iremotewinspool_pipe
, printer_name
,
222 "failed to open printserver");
224 test_get_environment(tctx
,
225 t
->iremotewinspool_pipe
->binding_handle
,
226 &t
->server_handle
, &t
->environment
),
227 "failed to get environment");
232 static bool torture_rpc_iremotewinspool_setup(struct torture_context
*tctx
,
235 struct test_iremotewinspool_context
*t
;
237 *data
= t
= talloc_zero(tctx
, struct test_iremotewinspool_context
);
239 return torture_rpc_iremotewinspool_setup_common(tctx
, t
);
242 static bool torture_rpc_iremotewinspool_teardown_common(struct torture_context
*tctx
,
243 struct test_iremotewinspool_context
*t
)
246 test_AsyncClosePrinter_byhandle(tctx
, t
, t
->iremotewinspool_pipe
, &t
->server_handle
);
251 static bool torture_rpc_iremotewinspool_teardown(struct torture_context
*tctx
,
254 struct test_iremotewinspool_context
*t
= talloc_get_type(data
, struct test_iremotewinspool_context
);
257 ret
= torture_rpc_iremotewinspool_teardown_common(tctx
, t
);
263 static bool test_AsyncClosePrinter(struct torture_context
*tctx
,
266 struct test_iremotewinspool_context
*ctx
=
267 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
269 struct dcerpc_pipe
*p
= ctx
->iremotewinspool_pipe
;
270 const char *printer_name
;
271 struct policy_handle handle
;
273 printer_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
276 test_AsyncOpenPrinter_byprinter(tctx
, ctx
, p
, printer_name
, &handle
),
277 "failed to test AsyncOpenPrinter");
280 test_AsyncClosePrinter_byhandle(tctx
, ctx
, p
, &handle
),
281 "failed to test AsyncClosePrinter");
286 static bool test_AsyncOpenPrinter(struct torture_context
*tctx
,
289 struct test_iremotewinspool_context
*ctx
=
290 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
292 struct dcerpc_pipe
*p
= ctx
->iremotewinspool_pipe
;
293 const char *printer_name
;
294 struct policy_handle handle
;
296 printer_name
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
299 test_AsyncOpenPrinter_byprinter(tctx
, ctx
, p
, printer_name
, &handle
),
300 "failed to test AsyncOpenPrinter");
302 test_AsyncClosePrinter_byhandle(tctx
, ctx
, p
, &handle
);
307 static struct spoolss_NotifyOption
*setup_printserver_NotifyOption(struct torture_context
*tctx
)
309 struct spoolss_NotifyOption
*o
;
311 o
= talloc_zero(tctx
, struct spoolss_NotifyOption
);
317 o
->flags
= PRINTER_NOTIFY_OPTIONS_REFRESH
;
320 o
->types
= talloc_zero_array(o
, struct spoolss_NotifyOptionType
, o
->count
);
321 if (o
->types
== NULL
) {
326 o
->types
[0].type
= PRINTER_NOTIFY_TYPE
;
327 o
->types
[0].count
= 1;
328 o
->types
[0].fields
= talloc_array(o
->types
, union spoolss_Field
, o
->types
[0].count
);
329 if (o
->types
[0].fields
== NULL
) {
333 o
->types
[0].fields
[0].field
= PRINTER_NOTIFY_FIELD_SERVER_NAME
;
335 o
->types
[1].type
= JOB_NOTIFY_TYPE
;
336 o
->types
[1].count
= 1;
337 o
->types
[1].fields
= talloc_array(o
->types
, union spoolss_Field
, o
->types
[1].count
);
338 if (o
->types
[1].fields
== NULL
) {
342 o
->types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_MACHINE_NAME
;
347 static bool test_SyncUnRegisterForRemoteNotifications_args(struct torture_context
*tctx
,
348 struct dcerpc_pipe
*p
,
349 struct policy_handle
*notify_handle
)
351 struct winspool_SyncUnRegisterForRemoteNotifications r
;
352 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
354 r
.in
.phRpcHandle
= notify_handle
;
355 r
.out
.phRpcHandle
= notify_handle
;
357 torture_assert_ntstatus_ok(tctx
,
358 dcerpc_winspool_SyncUnRegisterForRemoteNotifications_r(b
, tctx
, &r
),
359 "SyncUnRegisterForRemoteNotifications failed");
360 torture_assert_hresult_ok(tctx
, r
.out
.result
,
361 "SyncUnRegisterForRemoteNotifications failed");
366 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context
*tctx
,
367 struct dcerpc_pipe
*p
,
368 struct policy_handle
*server_handle
,
369 struct policy_handle
*notify_handle
);
371 static bool test_SyncUnRegisterForRemoteNotifications(struct torture_context
*tctx
,
374 struct test_iremotewinspool_context
*ctx
=
375 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
376 struct policy_handle notify_handle
;
379 test_SyncRegisterForRemoteNotifications_args(tctx
,
380 ctx
->iremotewinspool_pipe
,
383 "failed to test SyncRegisterForRemoteNotifications");
386 test_SyncUnRegisterForRemoteNotifications_args(tctx
,
387 ctx
->iremotewinspool_pipe
,
389 "failed to test UnSyncRegisterForRemoteNotifications");
394 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context
*tctx
,
395 struct dcerpc_pipe
*p
,
396 struct policy_handle
*server_handle
,
397 struct policy_handle
*notify_handle
)
399 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
401 struct winspool_SyncRegisterForRemoteNotifications r
;
402 struct winspool_PrintPropertiesCollection NotifyFilter
;
403 struct winspool_PrintNamedProperty
*c
;
404 struct spoolss_NotifyOption
*options
;
406 ZERO_STRUCT(NotifyFilter
);
408 options
= setup_printserver_NotifyOption(tctx
);
409 torture_assert(tctx
, options
, "out of memory");
411 c
= talloc_zero_array(tctx
, struct winspool_PrintNamedProperty
, 4);
412 torture_assert(tctx
, c
, "out of memory");
414 c
[0].propertyName
= "RemoteNotifyFilter Flags";
415 c
[0].propertyValue
.PropertyType
= winspool_PropertyTypeInt32
;
416 c
[0].propertyValue
.value
.propertyInt32
= 0xff;
418 c
[1].propertyName
= "RemoteNotifyFilter Options";
419 c
[1].propertyValue
.PropertyType
= winspool_PropertyTypeInt32
;
420 c
[1].propertyValue
.value
.propertyInt32
= 0;
422 c
[2].propertyName
= "RemoteNotifyFilter Color";
423 c
[2].propertyValue
.PropertyType
= winspool_PropertyTypeInt32
;
424 c
[2].propertyValue
.value
.propertyInt32
= 0;
426 c
[3].propertyName
= "RemoteNotifyFilter NotifyOptions";
427 c
[3].propertyValue
.PropertyType
= winspool_PropertyTypeNotificationOptions
;
428 c
[3].propertyValue
.value
.propertyOptionsContainer
.pOptions
= options
;
430 NotifyFilter
.numberOfProperties
= 4;
431 NotifyFilter
.propertiesCollection
= c
;
433 r
.in
.hPrinter
= *server_handle
;
434 r
.in
.pNotifyFilter
= &NotifyFilter
;
435 r
.out
.phRpcHandle
= notify_handle
;
437 torture_assert_ntstatus_ok(tctx
,
438 dcerpc_winspool_SyncRegisterForRemoteNotifications_r(b
, tctx
, &r
),
439 "SyncRegisterForRemoteNotifications failed");
440 torture_assert_hresult_ok(tctx
, r
.out
.result
,
441 "SyncRegisterForRemoteNotifications failed");
446 static bool test_SyncRegisterForRemoteNotifications(struct torture_context
*tctx
,
449 struct test_iremotewinspool_context
*ctx
=
450 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
451 struct policy_handle notify_handle
;
454 test_SyncRegisterForRemoteNotifications_args(tctx
,
455 ctx
->iremotewinspool_pipe
,
458 "failed to test SyncRegisterForRemoteNotifications");
460 test_SyncUnRegisterForRemoteNotifications_args(tctx
, ctx
->iremotewinspool_pipe
, ¬ify_handle
);
465 static bool test_AsyncUploadPrinterDriverPackage(struct torture_context
*tctx
,
468 struct test_iremotewinspool_context
*ctx
=
469 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
471 struct dcerpc_pipe
*p
= ctx
->iremotewinspool_pipe
;
472 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
474 struct winspool_AsyncUploadPrinterDriverPackage r
;
475 uint32_t pcchDestInfPath
= 0;
477 r
.in
.pszServer
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
478 r
.in
.pszInfPath
= "";
479 r
.in
.pszEnvironment
= "";
481 r
.in
.pszDestInfPath
= NULL
;
482 r
.in
.pcchDestInfPath
= &pcchDestInfPath
;
483 r
.out
.pszDestInfPath
= NULL
;
484 r
.out
.pcchDestInfPath
= &pcchDestInfPath
;
486 torture_assert_ntstatus_ok(tctx
,
487 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b
, tctx
, &r
),
488 "AsyncUploadPrinterDriverPackage failed");
489 torture_assert_hresult_equal(tctx
, r
.out
.result
, HRES_E_INVALIDARG
,
490 "AsyncUploadPrinterDriverPackage failed");
492 pcchDestInfPath
= 260;
493 r
.in
.pszDestInfPath
= talloc_zero_array(tctx
, uint16_t, pcchDestInfPath
);
494 r
.out
.pszDestInfPath
= talloc_zero_array(tctx
, uint16_t, pcchDestInfPath
);
496 torture_assert_ntstatus_ok(tctx
,
497 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b
, tctx
, &r
),
498 "AsyncUploadPrinterDriverPackage failed");
499 torture_assert_werr_equal(tctx
,
500 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_INVALID_ENVIRONMENT
,
501 "AsyncUploadPrinterDriverPackage failed");
503 r
.in
.pszEnvironment
= SPOOLSS_ARCHITECTURE_x64
;
505 torture_assert_ntstatus_ok(tctx
,
506 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b
, tctx
, &r
),
507 "AsyncUploadPrinterDriverPackage failed");
508 torture_assert_werr_equal(tctx
,
509 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_FILE_NOT_FOUND
,
510 "AsyncUploadPrinterDriverPackage failed");
512 r
.in
.pszInfPath
= "\\\\mthelena\\print$\\x64\\{BD443844-ED00-4D96-8CAE-95E49492312A}\\prnbrcl1.inf";
514 torture_assert_ntstatus_ok(tctx
,
515 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b
, tctx
, &r
),
516 "AsyncUploadPrinterDriverPackage failed");
517 torture_assert_werr_equal(tctx
,
518 W_ERROR(WIN32_FROM_HRESULT(r
.out
.result
)), WERR_FILE_NOT_FOUND
,
519 "AsyncUploadPrinterDriverPackage failed");
524 struct torture_suite
*torture_rpc_iremotewinspool(TALLOC_CTX
*mem_ctx
)
526 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "iremotewinspool");
527 struct torture_tcase
*tcase
= torture_suite_add_tcase(suite
, "printserver");
529 torture_tcase_set_fixture(tcase
,
530 torture_rpc_iremotewinspool_setup
,
531 torture_rpc_iremotewinspool_teardown
);
533 torture_tcase_add_simple_test(tcase
, "AsyncOpenPrinter", test_AsyncOpenPrinter
);
534 torture_tcase_add_simple_test(tcase
, "SyncRegisterForRemoteNotifications", test_SyncRegisterForRemoteNotifications
);
535 torture_tcase_add_simple_test(tcase
, "SyncUnRegisterForRemoteNotifications", test_SyncUnRegisterForRemoteNotifications
);
536 torture_tcase_add_simple_test(tcase
, "AsyncClosePrinter", test_AsyncClosePrinter
);
537 torture_tcase_add_simple_test(tcase
, "AsyncUploadPrinterDriverPackage", test_AsyncUploadPrinterDriverPackage
);