libcli/security Provide a common, top level libcli/security/security.h
[ira/wip.git] / source3 / utils / net_printing.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Local printing tdb migration interface
5
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, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "utils/net.h"
24 #include "librpc/gen_ndr/ndr_ntprinting.h"
25 #include "librpc/gen_ndr/cli_spoolss.h"
26 #include "rpc_client/cli_spoolss.h"
27 #include "../libcli/security/security.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define PRINTERS_PREFIX "PRINTERS/"
33 #define SECDESC_PREFIX "SECDESC/"
34
35 static void dump_form(TALLOC_CTX *mem_ctx,
36                       const char *key_name,
37                       unsigned char *data,
38                       size_t length)
39 {
40         enum ndr_err_code ndr_err;
41         DATA_BLOB blob;
42         char *s;
43         struct ntprinting_form r;
44
45         printf("found form: %s\n", key_name);
46
47         blob = data_blob_const(data, length);
48
49         ZERO_STRUCT(r);
50
51         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
52                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
53         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
54                 d_fprintf(stderr, _("form pull failed: %s\n"),
55                           ndr_errstr(ndr_err));
56                 return;
57         }
58
59         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
60         if (s) {
61                 printf("%s\n", s);
62         }
63 }
64
65 static void dump_driver(TALLOC_CTX *mem_ctx,
66                         const char *key_name,
67                         unsigned char *data,
68                         size_t length)
69 {
70         enum ndr_err_code ndr_err;
71         DATA_BLOB blob;
72         char *s;
73         struct ntprinting_driver r;
74
75         printf("found driver: %s\n", key_name);
76
77         blob = data_blob_const(data, length);
78
79         ZERO_STRUCT(r);
80
81         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
82                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
83         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
84                 d_fprintf(stderr, _("driver pull failed: %s\n"),
85                           ndr_errstr(ndr_err));
86                 return;
87         }
88
89         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
90         if (s) {
91                 printf("%s\n", s);
92         }
93 }
94
95 static void dump_printer(TALLOC_CTX *mem_ctx,
96                          const char *key_name,
97                          unsigned char *data,
98                          size_t length)
99 {
100         enum ndr_err_code ndr_err;
101         DATA_BLOB blob;
102         char *s;
103         struct ntprinting_printer r;
104
105         printf("found printer: %s\n", key_name);
106
107         blob = data_blob_const(data, length);
108
109         ZERO_STRUCT(r);
110
111         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
112                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
113         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
114                 d_fprintf(stderr, _("printer pull failed: %s\n"),
115                           ndr_errstr(ndr_err));
116                 return;
117         }
118
119         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
120         if (s) {
121                 printf("%s\n", s);
122         }
123 }
124
125 static void dump_sd(TALLOC_CTX *mem_ctx,
126                     const char *key_name,
127                     unsigned char *data,
128                     size_t length)
129 {
130         enum ndr_err_code ndr_err;
131         DATA_BLOB blob;
132         char *s;
133         struct sec_desc_buf r;
134
135         printf("found security descriptor: %s\n", key_name);
136
137         blob = data_blob_const(data, length);
138
139         ZERO_STRUCT(r);
140
141         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
142                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
143         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
144                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
145                           ndr_errstr(ndr_err));
146                 return;
147         }
148
149         s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
150         if (s) {
151                 printf("%s\n", s);
152         }
153 }
154
155
156 static int net_printing_dump(struct net_context *c, int argc,
157                              const char **argv)
158 {
159         int ret = -1;
160         TALLOC_CTX *ctx = talloc_stackframe();
161         TDB_CONTEXT *tdb;
162         TDB_DATA kbuf, newkey, dbuf;
163
164         if (argc < 1 || c->display_usage) {
165                 d_fprintf(stderr, "%s\nnet printing dump <file.tdb>\n",
166                           _("Usage:"));
167                 goto done;
168         }
169
170         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
171         if (!tdb) {
172                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
173                 goto done;
174         }
175
176         for (kbuf = tdb_firstkey(tdb);
177              kbuf.dptr;
178              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
179         {
180                 dbuf = tdb_fetch(tdb, kbuf);
181                 if (!dbuf.dptr) {
182                         continue;
183                 }
184
185                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
186                         dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
187                         SAFE_FREE(dbuf.dptr);
188                         continue;
189                 }
190
191                 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
192                         dump_driver(ctx, (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX), dbuf.dptr, dbuf.dsize);
193                         SAFE_FREE(dbuf.dptr);
194                         continue;
195                 }
196
197                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
198                         dump_printer(ctx, (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX), dbuf.dptr, dbuf.dsize);
199                         SAFE_FREE(dbuf.dptr);
200                         continue;
201                 }
202
203                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
204                         dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
205                         SAFE_FREE(dbuf.dptr);
206                         continue;
207                 }
208
209         }
210
211         ret = 0;
212
213  done:
214         talloc_free(ctx);
215         return ret;
216 }
217
218 static NTSTATUS migrate_form(TALLOC_CTX *mem_ctx,
219                          struct rpc_pipe_client *pipe_hnd,
220                          const char *key_name,
221                          unsigned char *data,
222                          size_t length)
223 {
224         struct policy_handle hnd;
225         enum ndr_err_code ndr_err;
226         struct ntprinting_form r;
227         union spoolss_AddFormInfo f;
228         struct spoolss_AddFormInfo1 f1;
229         DATA_BLOB blob;
230         NTSTATUS status;
231         WERROR result;
232
233         blob = data_blob_const(data, length);
234
235         ZERO_STRUCT(r);
236
237         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
238                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
239         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
240                 d_fprintf(stderr, _("form pull failed: %s\n"),
241                           ndr_errstr(ndr_err));
242                 return NT_STATUS_NO_MEMORY;
243         }
244
245         /* Don't migrate builtin forms */
246         if (r.flag == SPOOLSS_FORM_BUILTIN) {
247                 return NT_STATUS_OK;
248         }
249
250         d_printf(_("Migrating Form: %s\n"), key_name);
251
252         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
253                                                mem_ctx,
254                                                pipe_hnd->srv_name_slash,
255                                                MAXIMUM_ALLOWED_ACCESS,
256                                                &hnd);
257         if (!W_ERROR_IS_OK(result)) {
258                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
259                                   pipe_hnd->srv_name_slash, win_errstr(result));
260                 return werror_to_ntstatus(result);
261         }
262
263         f1.form_name = key_name;
264         f1.flags = r.flag;
265
266         f1.size.width = r.width;
267         f1.size.height = r.length;
268
269         f1.area.top = r.top;
270         f1.area.right = r.right;
271         f1.area.bottom = r.bottom;
272         f1.area.left = r.left;
273
274         f.info1 = &f1;
275
276         status = rpccli_spoolss_AddForm(pipe_hnd,
277                                         mem_ctx,
278                                         &hnd,
279                                         1,
280                                         f,
281                                         &result);
282         if (!NT_STATUS_IS_OK(status)) {
283                 d_printf(_("\tAddForm(%s) refused -- %s.\n"),
284                         f.info1->form_name, nt_errstr(status));
285         }
286
287         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
288
289         return status;
290 }
291
292 static NTSTATUS migrate_driver(TALLOC_CTX *mem_ctx,
293                                struct rpc_pipe_client *pipe_hnd,
294                                const char *key_name,
295                                unsigned char *data,
296                                size_t length)
297 {
298         enum ndr_err_code ndr_err;
299         struct ntprinting_driver r;
300         struct spoolss_AddDriverInfoCtr d;
301         struct spoolss_AddDriverInfo3 d3;
302         struct spoolss_StringArray a;
303         DATA_BLOB blob;
304         NTSTATUS status;
305         WERROR result;
306
307         blob = data_blob_const(data, length);
308
309         ZERO_STRUCT(r);
310
311         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
312                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
313         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
314                 d_fprintf(stderr, _("driver pull failed: %s\n"),
315                           ndr_errstr(ndr_err));
316                 return NT_STATUS_NO_MEMORY;
317         }
318
319         d_printf(_("Migrating Printer Driver: %s\n"), key_name);
320
321         ZERO_STRUCT(d3);
322         ZERO_STRUCT(a);
323
324         a.string = r.dependent_files;
325
326         d3.architecture = r.environment;
327         d3.config_file = r.configfile;
328         d3.data_file = r.datafile;
329         d3.default_datatype = r.defaultdatatype;
330         d3.dependent_files = &a;
331         d3.driver_path = r.driverpath;
332         d3.help_file = r.helpfile;
333         d3.monitor_name = r.monitorname;
334         d3.driver_name = r.name;
335         d3.version = r.version;
336
337         d.info.info3 = &d3;
338         d.level = 3;
339
340         status = rpccli_spoolss_AddPrinterDriver(pipe_hnd,
341                                                  mem_ctx,
342                                                  NULL,
343                                                  &d,
344                                                  &result);
345         if (!NT_STATUS_IS_OK(status)) {
346                 d_printf(_("\tAddDriver driver: [%s] refused -- %s.\n"),
347                         d3.driver_name, nt_errstr(status));
348         }
349
350         return status;
351 }
352
353 static NTSTATUS migrate_printer(TALLOC_CTX *mem_ctx,
354                                 struct rpc_pipe_client *pipe_hnd,
355                                 const char *key_name,
356                                 unsigned char *data,
357                                 size_t length)
358 {
359         struct policy_handle hnd;
360         enum ndr_err_code ndr_err;
361         struct ntprinting_printer r;
362         struct spoolss_SetPrinterInfo2 info2;
363         struct spoolss_DeviceMode dm;
364         struct spoolss_SetPrinterInfoCtr info_ctr;
365         struct spoolss_DevmodeContainer devmode_ctr;
366         struct sec_desc_buf secdesc_ctr;
367         DATA_BLOB blob;
368         NTSTATUS status;
369         WERROR result;
370         int j;
371
372         if (strequal(key_name, "printers")) {
373                 return NT_STATUS_OK;
374         }
375
376         blob = data_blob_const(data, length);
377
378         ZERO_STRUCT(r);
379
380         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
381                    (ndr_pull_flags_fn_t) ndr_pull_ntprinting_printer);
382         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
383                 d_fprintf(stderr, _("printer pull failed: %s\n"),
384                           ndr_errstr(ndr_err));
385                 return NT_STATUS_NO_MEMORY;
386         }
387
388         d_printf(_("Migrating Printer: %s\n"), key_name);
389
390         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
391                                                mem_ctx,
392                                                key_name,
393                                                MAXIMUM_ALLOWED_ACCESS,
394                                                &hnd);
395         if (!W_ERROR_IS_OK(result)) {
396                 d_fprintf(stderr, _("OpenPrinter(%s) failed: %s\n"),
397                                   key_name, win_errstr(result));
398                 return werror_to_ntstatus(result);
399         }
400
401         /* Create printer info level 2 */
402         ZERO_STRUCT(info2);
403         ZERO_STRUCT(devmode_ctr);
404         ZERO_STRUCT(secdesc_ctr);
405
406         info2.attributes = r.info.attributes;
407         info2.averageppm = r.info.averageppm;
408         info2.cjobs = r.info.cjobs;
409         info2.comment = r.info.comment;
410         info2.datatype = r.info.datatype;
411         info2.defaultpriority = r.info.default_priority;
412         info2.drivername = r.info.drivername;
413         info2.location = r.info.location;
414         info2.parameters = r.info.parameters;
415         info2.portname = r.info.portname;
416         info2.printername = r.info.printername;
417         info2.printprocessor = r.info.printprocessor;
418         info2.priority = r.info.priority;
419         info2.sepfile = r.info.sepfile;
420         info2.sharename = r.info.sharename;
421         info2.starttime = r.info.starttime;
422         info2.status = r.info.status;
423         info2.untiltime = r.info.untiltime;
424
425         /* Create Device Mode */
426         if (r.devmode != NULL) {
427                 ZERO_STRUCT(dm);
428
429                 dm.bitsperpel              = r.devmode->bitsperpel;
430                 dm.collate                 = r.devmode->collate;
431                 dm.color                   = r.devmode->color;
432                 dm.copies                  = r.devmode->copies;
433                 dm.defaultsource           = r.devmode->defaultsource;
434                 dm.devicename              = r.devmode->devicename;
435                 dm.displayflags            = r.devmode->displayflags;
436                 dm.displayfrequency        = r.devmode->displayfrequency;
437                 dm.dithertype              = r.devmode->dithertype;
438                 dm.driverversion           = r.devmode->driverversion;
439                 dm.duplex                  = r.devmode->duplex;
440                 dm.fields                  = r.devmode->fields;
441                 dm.formname                = r.devmode->formname;
442                 dm.icmintent               = r.devmode->icmintent;
443                 dm.icmmethod               = r.devmode->icmmethod;
444                 dm.logpixels               = r.devmode->logpixels;
445                 dm.mediatype               = r.devmode->mediatype;
446                 dm.orientation             = r.devmode->orientation;
447                 dm.panningheight           = r.devmode->pelsheight;
448                 dm.panningwidth            = r.devmode->panningwidth;
449                 dm.paperlength             = r.devmode->paperlength;
450                 dm.papersize               = r.devmode->papersize;
451                 dm.paperwidth              = r.devmode->paperwidth;
452                 dm.pelsheight              = r.devmode->pelsheight;
453                 dm.pelswidth               = r.devmode->pelswidth;
454                 dm.printquality            = r.devmode->printquality;
455                 dm.scale                   = r.devmode->scale;
456                 dm.specversion             = r.devmode->specversion;
457                 dm.ttoption                = r.devmode->ttoption;
458                 dm.yresolution             = r.devmode->yresolution;
459
460                 if (r.devmode->nt_dev_private != NULL) {
461                         dm.driverextra_data.data   = r.devmode->nt_dev_private->data;
462                         dm.driverextra_data.length = r.devmode->nt_dev_private->length;
463                         dm.__driverextra_length    = r.devmode->nt_dev_private->length;
464                 }
465
466                 devmode_ctr.devmode = &dm;
467
468                 info2.devmode_ptr = 1;
469         }
470
471         info_ctr.info.info2 = &info2;
472         info_ctr.level = 2;
473
474         status = rpccli_spoolss_SetPrinter(pipe_hnd,
475                                            mem_ctx,
476                                            &hnd,
477                                            &info_ctr,
478                                            &devmode_ctr,
479                                            &secdesc_ctr,
480                                            0, /* command */
481                                            &result);
482         if (!NT_STATUS_IS_OK(status)) {
483                 d_printf(_("\tSetPrinter(%s) level 2 refused -- %s.\n"),
484                         key_name, nt_errstr(status));
485                 goto done;
486         }
487
488         /* migrate printerdata */
489         for (j = 0; j < r.count; j++) {
490                 char *valuename;
491                 char *keyname;
492
493                 if (r.printer_data[j].type == REG_NONE) {
494                         continue;
495                 }
496
497                 keyname = CONST_DISCARD(char *, r.printer_data[j].name);
498                 valuename = strchr(keyname, '\\');
499                 if (valuename == NULL) {
500                         continue;
501                 } else {
502                         valuename[0] = '\0';
503                         valuename++;
504                 }
505
506                 printf("          data: %s\\%s\n", keyname, valuename);
507
508                 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd,
509                                                          mem_ctx,
510                                                          &hnd,
511                                                          keyname,
512                                                          valuename,
513                                                          r.printer_data[j].type,
514                                                          r.printer_data[j].data.data,
515                                                          r.printer_data[j].data.length,
516                                                          &result);
517                 if (!NT_STATUS_IS_OK(status)) {
518                         d_printf(_("\tSetPrinterDataEx: printer [%s], keyname [%s], valuename [%s] refused -- %s.\n"),
519                                 key_name, keyname, valuename, nt_errstr(status));
520                         break;
521                 }
522         }
523
524  done:
525         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
526
527         return status;
528 }
529
530 static NTSTATUS migrate_secdesc(TALLOC_CTX *mem_ctx,
531                                 struct rpc_pipe_client *pipe_hnd,
532                                 const char *key_name,
533                                 unsigned char *data,
534                                 size_t length)
535 {
536         struct policy_handle hnd;
537         enum ndr_err_code ndr_err;
538         struct sec_desc_buf secdesc_ctr;
539         struct spoolss_SetPrinterInfo3 info3;
540         struct spoolss_SetPrinterInfoCtr info_ctr;
541         struct spoolss_DevmodeContainer devmode_ctr;
542         DATA_BLOB blob;
543         NTSTATUS status;
544         WERROR result;
545
546         if (strequal(key_name, "printers")) {
547                 return NT_STATUS_OK;
548         }
549
550         blob = data_blob_const(data, length);
551
552         ZERO_STRUCT(secdesc_ctr);
553
554         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &secdesc_ctr,
555                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
556         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
557                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
558                           ndr_errstr(ndr_err));
559                 return NT_STATUS_NO_MEMORY;
560         }
561
562         d_printf(_("Migrating Security Descriptor: %s\n"), key_name);
563
564         result = rpccli_spoolss_openprinter_ex(pipe_hnd,
565                                                mem_ctx,
566                                                key_name,
567                                                MAXIMUM_ALLOWED_ACCESS,
568                                                &hnd);
569         if (!W_ERROR_IS_OK(result)) {
570                 d_fprintf(stderr, _("\tOpenPrinter(%s) failed: %s\n"),
571                                   key_name, win_errstr(result));
572                 return werror_to_ntstatus(result);
573         }
574
575         ZERO_STRUCT(devmode_ctr);
576
577         info3.sec_desc_ptr = 1;
578
579         info_ctr.info.info3 = &info3;
580         info_ctr.level = 3;
581
582         status = rpccli_spoolss_SetPrinter(pipe_hnd,
583                                            mem_ctx,
584                                            &hnd,
585                                            &info_ctr,
586                                            &devmode_ctr,
587                                            &secdesc_ctr,
588                                            0, /* command */
589                                            &result);
590         if (!NT_STATUS_IS_OK(status)) {
591                 d_printf(_("\tSetPrinter(%s) level 3 refused -- %s.\n"),
592                         key_name, nt_errstr(status));
593         }
594
595         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
596
597         return status;
598 }
599
600 static NTSTATUS printing_migrate_internal(struct net_context *c,
601                                           const struct dom_sid *domain_sid,
602                                           const char *domain_name,
603                                           struct cli_state *cli,
604                                           struct rpc_pipe_client *pipe_hnd,
605                                           TALLOC_CTX *mem_ctx,
606                                           int argc,
607                                           const char **argv)
608 {
609         TALLOC_CTX *tmp_ctx;
610         TDB_CONTEXT *tdb;
611         TDB_DATA kbuf, newkey, dbuf;
612         NTSTATUS status;
613
614         tmp_ctx = talloc_new(mem_ctx);
615         if (tmp_ctx == NULL) {
616                 return NT_STATUS_NO_MEMORY;
617         }
618
619         tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
620         if (tdb == NULL) {
621                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
622                 status = NT_STATUS_NO_SUCH_FILE;
623                 goto done;
624         }
625
626         for (kbuf = tdb_firstkey(tdb);
627              kbuf.dptr;
628              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
629         {
630                 dbuf = tdb_fetch(tdb, kbuf);
631                 if (!dbuf.dptr) {
632                         continue;
633                 }
634
635                 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
636                         migrate_form(tmp_ctx,
637                                      pipe_hnd,
638                                      (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
639                                      dbuf.dptr,
640                                      dbuf.dsize);
641                         SAFE_FREE(dbuf.dptr);
642                         continue;
643                 }
644
645                 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
646                         migrate_driver(tmp_ctx,
647                                        pipe_hnd,
648                                        (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
649                                        dbuf.dptr,
650                                        dbuf.dsize);
651                         SAFE_FREE(dbuf.dptr);
652                         continue;
653                 }
654
655                 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
656                         migrate_printer(tmp_ctx,
657                                         pipe_hnd,
658                                         (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
659                                         dbuf.dptr,
660                                         dbuf.dsize);
661                         SAFE_FREE(dbuf.dptr);
662                         continue;
663                 }
664
665                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
666                         migrate_secdesc(tmp_ctx,
667                                         pipe_hnd,
668                                         (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
669                                         dbuf.dptr,
670                                         dbuf.dsize);
671                         SAFE_FREE(dbuf.dptr);
672                         continue;
673                 }
674
675         }
676
677         status = NT_STATUS_OK;
678
679  done:
680         talloc_free(tmp_ctx);
681         return status;
682 }
683
684 static int net_printing_migrate(struct net_context *c,
685                                 int argc,
686                                 const char **argv)
687 {
688         if (argc < 1 || c->display_usage) {
689                 d_printf(  "%s\n"
690                            "net printing migrate <file.tdb>\n"
691                            "    %s\n",
692                          _("Usage:"),
693                          _("Migrate tdb printing files to new storage"));
694                 return 0;
695         }
696
697         return run_rpc_command(c,
698                                NULL,
699                                &ndr_table_spoolss.syntax_id,
700                                0,
701                                printing_migrate_internal,
702                                argc,
703                                argv);
704 }
705 /**
706  * 'net printing' entrypoint.
707  * @param argc  Standard main() style argc.
708  * @param argv  Standard main() style argv. Initial components are already
709  *              stripped.
710  **/
711
712 int net_printing(struct net_context *c, int argc, const char **argv)
713 {
714         int ret = -1;
715
716         struct functable func[] = {
717                 {
718                         "dump",
719                         net_printing_dump,
720                         NET_TRANSPORT_LOCAL,
721                         N_("Dump printer databases"),
722                         N_("net printing dump\n"
723                            "    Dump tdb printing file")
724                 },
725
726                 {
727                         "migrate",
728                         net_printing_migrate,
729                         NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
730                         N_("Migrate printer databases"),
731                         N_("net printing migrate\n"
732                            "    Migrate tdb printing files to new storage")
733                 },
734
735         { NULL, NULL, 0, NULL, NULL }
736         };
737
738         ret = net_run_function(c, argc, argv, "net printing", func);
739
740         return ret;
741 }