468484e471fca309ddda7bf652c2d8c266c86e72
[bbaumbach/samba-autobuild/.git] / source4 / torture / rpc / spoolss.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for spoolss rpc operations
4
5    Copyright (C) Tim Potter 2003
6    
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 2 of the License, or
10    (at your option) any later version.
11    
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.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
25                      struct policy_handle *handle)
26 {
27         NTSTATUS status;
28         struct spoolss_GetPrinter r;
29         uint16 levels[] = {1, 2, 3, 4, 5, 6, 7};
30         int i;
31         BOOL ret = True;
32         
33         for (i=0;i<ARRAY_SIZE(levels);i++) {
34                 uint32 buf_size = 0;
35                 r.in.handle = handle;
36                 r.in.level = levels[i];
37                 r.in.buffer = NULL;
38                 r.in.buf_size = &buf_size;
39                 r.out.buf_size = &buf_size;
40
41                 printf("Testing GetPrinter level %u\n", r.in.level);
42
43                 status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
44                 if (!NT_STATUS_IS_OK(status)) {
45                         printf("GetPrinter failed - %s\n", nt_errstr(status));
46                         ret = False;
47                         continue;
48                 }
49                 
50                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
51                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
52                         data_blob_clear(&blob);
53                         r.in.buffer = &blob;
54                         status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
55                 }
56                 
57                 if (!NT_STATUS_IS_OK(status) ||
58                     !W_ERROR_IS_OK(r.out.result)) {
59                         printf("GetPrinter failed - %s/%s\n", 
60                                nt_errstr(status), win_errstr(r.out.result));
61                         ret = False;
62                         continue;
63                 }
64         }
65
66         return ret;
67 }
68
69
70 BOOL test_ClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
71                        struct policy_handle *handle)
72 {
73         NTSTATUS status;
74         struct spoolss_ClosePrinter r;
75
76         r.in.handle = handle;
77         r.out.handle = handle;
78
79         printf("Testing ClosePrinter\n");
80
81         status = dcerpc_spoolss_ClosePrinter(p, mem_ctx, &r);
82         if (!NT_STATUS_IS_OK(status)) {
83                 printf("ClosePrinter failed - %s\n", nt_errstr(status));
84                 return False;
85         }
86
87         return True;
88 }
89
90 BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91                   struct policy_handle *handle, char *formname)
92 {
93         NTSTATUS status;
94         struct spoolss_GetForm r;
95         uint32 buf_size;
96
97         r.in.handle = handle;
98         r.in.formname = formname;
99         r.in.level = 1;
100         r.in.buffer = NULL;
101         buf_size = 0;
102         r.in.buf_size = r.out.buf_size = &buf_size;
103
104         printf("Testing GetForm\n");
105
106         status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
107
108         if (!NT_STATUS_IS_OK(status)) {
109                 printf("GetForm failed - %s\n", nt_errstr(status));
110                 return False;
111         }
112
113         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
114                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
115
116                 data_blob_clear(&blob);
117                 r.in.buffer = &blob;
118
119                 status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
120
121                 if (!r.out.info) {
122                         printf("No form info returned");
123                         return False;
124                 }
125         }
126
127         return True;
128 }
129
130 BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
131                     struct policy_handle *handle)
132 {
133         NTSTATUS status;
134         struct spoolss_EnumForms r;
135         uint32 buf_size;
136
137         r.in.handle = handle;
138         r.in.level = 1;
139         r.in.buffer = NULL;
140         buf_size = 0;
141         r.in.buf_size = &buf_size;
142         r.out.buf_size = &buf_size;
143
144         printf("Testing EnumForms\n");
145
146         status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
147
148         if (!NT_STATUS_IS_OK(status)) {
149                 printf("EnumForms failed - %s\n", nt_errstr(status));
150                 return False;
151         }
152
153         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
154                 DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
155                 union spoolss_FormInfo *info;
156                 int j;
157
158                 data_blob_clear(&blob);
159                 r.in.buffer = &blob;
160
161                 status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
162
163                 if (!r.out.buffer) {
164                         printf("No forms returned");
165                         return False;
166                 }
167
168                 status = pull_spoolss_FormInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
169                 if (!NT_STATUS_IS_OK(status)) {
170                         printf("EnumFormsArray parse failed - %s\n", nt_errstr(status));
171                         return False;
172                 }
173
174                 for (j=0;j<r.out.count;j++) {
175                         printf("Form %d\n", j);
176                         NDR_PRINT_UNION_DEBUG(spoolss_FormInfo, r.in.level, &info[j]);
177                 }
178
179                 for (j = 0; j < r.out.count; j++)
180                         test_GetForm(p, mem_ctx, handle, info[j].info1.name);
181         }
182
183         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
184                 printf("EnumForms failed - %s/%s\n", 
185                        nt_errstr(status), win_errstr(r.out.result));
186                 return False;
187         }
188
189         return True;
190 }
191
192 BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
193                      struct policy_handle *handle, char *formname)
194 {
195         NTSTATUS status;
196         struct spoolss_DeleteForm r;
197
198         r.in.handle = handle;
199         r.in.formname = formname;
200
201         status = dcerpc_spoolss_DeleteForm(p, mem_ctx, &r);
202
203         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
204                 printf("DeleteForm failed - %s/%s\n", 
205                        nt_errstr(status), win_errstr(r.out.result));
206                 return False;
207         }
208
209         return True;
210 }
211
212 BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
213                   struct policy_handle *handle)
214 {
215         struct spoolss_AddForm r;
216         struct spoolss_AddFormInfo1 form;
217         NTSTATUS status;
218         char *formname = "testform3";
219
220         r.in.handle = handle;
221         r.in.level = 1;
222         form.flags = 2;         /* User form */
223         form.name = formname;
224         form.width = 1;
225         form.length = 2;
226         form.left = 3;
227         form.top = 4;
228         form.right = 5;
229         form.bottom = 6;
230         r.in.info.info1 = &form;
231         
232         status = dcerpc_spoolss_AddForm(p, mem_ctx, &r);
233
234         if (!NT_STATUS_IS_OK(status)) {
235                 printf("AddForm failed - %s\n", nt_errstr(status));
236                 return False;
237         }
238
239         if (!W_ERROR_IS_OK(r.out.result)) {
240                 printf("AddForm failed - %s\n", nt_errstr(status));
241                 /* Fall through to delete form */
242         }
243
244         if (!test_DeleteForm(p, mem_ctx, handle, formname)) {
245                 printf("DeleteForm failed\n");
246                 return False;
247         }
248
249         return True;
250 }
251
252 BOOL test_EnumPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
253                           struct policy_handle *handle)
254 {
255         NTSTATUS status;
256         struct spoolss_EnumPrinterData r;
257
258         r.in.handle = handle;
259         r.in.enum_index = 0;
260
261         do {
262                 uint32 data_size;
263                 
264                 r.in.value_offered = 0;
265                 data_size = 0;
266                 r.in.data_size = &data_size;
267                 r.out.data_size = &data_size;
268
269                 printf("Testing EnumPrinterData\n");
270
271                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
272
273                 if (!NT_STATUS_IS_OK(status)) {
274                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
275                         return False;
276                 }
277
278                 r.in.value_offered = r.out.value_needed;
279
280                 status = dcerpc_spoolss_EnumPrinterData(p, mem_ctx, &r);
281
282                 if (!NT_STATUS_IS_OK(status)) {
283                         printf("EnumPrinterData failed - %s\n", nt_errstr(status));
284                         return False;
285                 }
286                 
287                 r.in.enum_index++;
288         } while (!W_ERROR_IS_OK(r.out.result));
289
290         return True;
291 }
292
293 static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
294                              const char *name)
295 {
296         NTSTATUS status;
297         struct spoolss_OpenPrinter r;
298         struct policy_handle handle;
299         DATA_BLOB blob;
300         BOOL ret = True;
301
302         blob = data_blob(NULL, 0);
303
304         r.in.server = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
305         r.in.printer = NULL;
306         r.in.buffer = &blob;
307         r.in.access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED;  
308         r.out.handle = &handle;
309
310         printf("\nTesting OpenPrinter(\\\\%s)\n", r.in.server);
311
312         status = dcerpc_spoolss_OpenPrinter(p, mem_ctx, &r);
313         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(r.out.result)) {
314                 printf("OpenPrinter failed - %s/%s\n", 
315                        nt_errstr(status), win_errstr(r.out.result));
316                 /* don't consider failing this an error until we understand it */
317                 return True;
318         }
319
320
321         if (!test_GetPrinter(p, mem_ctx, &handle)) {
322                 ret = False;
323         }
324
325         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
326                 ret = False;
327         }
328         
329         return ret;
330 }
331
332 static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
333                                const char *name)
334 {
335         struct policy_handle handle;
336         struct spoolss_OpenPrinterEx r;
337         struct spoolss_UserLevel1 userlevel1;
338         NTSTATUS status;
339         BOOL ret = True;
340
341         r.in.printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s", 
342                                            dcerpc_server_name(p), name);
343         r.in.datatype = NULL;
344         r.in.devmode_ctr.size = 0;
345         r.in.devmode_ctr.devmode = NULL;
346         r.in.access_required = 0x02000000;
347         r.in.level = 1;
348         r.out.handle = &handle;
349
350         userlevel1.size = 1234;
351         userlevel1.client = "hello";
352         userlevel1.user = "spottyfoot!";
353         userlevel1.build = 1;
354         userlevel1.major = 2;
355         userlevel1.minor = 3;
356         userlevel1.processor = 4;
357         r.in.userlevel.level1 = &userlevel1;
358
359         printf("Testing OpenPrinterEx(%s)\n", r.in.printername);
360
361         status = dcerpc_spoolss_OpenPrinterEx(p, mem_ctx, &r);
362
363         if (!NT_STATUS_IS_OK(status)) {
364                 printf("OpenPrinterEx failed - %s\n", nt_errstr(status));
365                 return False;
366         }
367
368         if (!W_ERROR_IS_OK(r.out.result)) {
369                 printf("OpenPrinterEx failed - %s\n", win_errstr(r.out.result));
370                 return False;
371         }
372
373         if (!test_GetPrinter(p, mem_ctx, &handle)) {
374                 ret = False;
375         }
376
377         if (!test_EnumForms(p, mem_ctx, &handle)) {
378                 ret = False;
379         }
380
381         if (!test_AddForm(p, mem_ctx, &handle)) {
382                 ret = False;
383         }
384
385         if (!test_EnumPrinterData(p, mem_ctx, &handle)) {
386                 ret = False;
387         }
388
389         if (!test_ClosePrinter(p, mem_ctx, &handle)) {
390                 ret = False;
391         }
392
393         return ret;
394 }
395
396
397 static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
398 {
399         struct spoolss_EnumPrinters r;
400         NTSTATUS status;
401         uint16 levels[] = {1, 2, 4, 5};
402         int i;
403         BOOL ret = True;
404
405         for (i=0;i<ARRAY_SIZE(levels);i++) {
406                 uint32 buf_size = 0;
407                 union spoolss_PrinterInfo *info;
408                 int j;
409
410                 r.in.flags = 0x02;
411                 r.in.server = "";
412                 r.in.level = levels[i];
413                 r.in.buffer = NULL;
414                 r.in.buf_size = &buf_size;
415                 r.out.buf_size = &buf_size;
416
417                 printf("\nTesting EnumPrinters level %u\n", r.in.level);
418
419                 status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
420                 if (!NT_STATUS_IS_OK(status)) {
421                         printf("EnumPrinters failed - %s\n", nt_errstr(status));
422                         ret = False;
423                         continue;
424                 }
425                 
426                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
427                         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
428                         data_blob_clear(&blob);
429                         r.in.buffer = &blob;
430                         status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
431                 }
432                 
433                 if (!NT_STATUS_IS_OK(status) ||
434                     !W_ERROR_IS_OK(r.out.result)) {
435                         printf("EnumPrinters failed - %s/%s\n", 
436                                nt_errstr(status), win_errstr(r.out.result));
437                         continue;
438                 }
439
440                 if (!r.out.buffer) {
441                         printf("No printers returned");
442                         continue;
443                 }
444
445                 status = pull_spoolss_PrinterInfoArray(r.out.buffer, mem_ctx, r.in.level, r.out.count, &info);
446                 if (!NT_STATUS_IS_OK(status)) {
447                         printf("EnumPrintersArray parse failed - %s\n", nt_errstr(status));
448                         continue;
449                 }
450
451                 for (j=0;j<r.out.count;j++) {
452                         printf("Printer %d\n", j);
453                         NDR_PRINT_UNION_DEBUG(spoolss_PrinterInfo, r.in.level, &info[j]);
454                 }
455
456                 for (j=0;j<r.out.count;j++) {
457                         if (r.in.level == 1) {
458                                 /* the names appear to be comma-separated name lists? */
459                                 char *name = talloc_strdup(mem_ctx, info[j].info1.name);
460                                 char *comma = strchr(name, ',');
461                                 if (comma) *comma = 0;
462                                 if (!test_OpenPrinter(p, mem_ctx, name)) {
463                                         ret = False;
464                                 }
465                                 if (!test_OpenPrinterEx(p, mem_ctx, name)) {
466                                         ret = False;
467                                 }
468                         }
469                 }
470         }
471         
472         return ret;
473 }
474
475 BOOL torture_rpc_spoolss(int dummy)
476 {
477         NTSTATUS status;
478         struct dcerpc_pipe *p;
479         TALLOC_CTX *mem_ctx;
480         BOOL ret = True;
481
482         mem_ctx = talloc_init("torture_rpc_spoolss");
483
484         status = torture_rpc_connection(&p, 
485                                         DCERPC_SPOOLSS_NAME,
486                                         DCERPC_SPOOLSS_UUID,
487                                         DCERPC_SPOOLSS_VERSION);
488         if (!NT_STATUS_IS_OK(status)) {
489                 return False;
490         }
491
492         p->flags |= DCERPC_DEBUG_PRINT_BOTH;
493         
494         if (!test_EnumPrinters(p, mem_ctx)) {
495                 ret = False;
496         }
497
498         talloc_destroy(mem_ctx);
499
500         torture_rpc_close(p);
501
502         return ret;
503 }