s3:rpc_client: implement bind time feature negotiation
[metze/samba-autobuild/.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 "system/filesys.h"
24 #include "utils/net.h"
25 #include "rpc_client/rpc_client.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "librpc/gen_ndr/ndr_ntprinting.h"
28 #include "librpc/gen_ndr/ndr_spoolss.h"
29 #include "../libcli/security/security.h"
30 #include "../librpc/gen_ndr/ndr_security.h"
31 #include "../librpc/gen_ndr/ndr_winreg.h"
32 #include "util_tdb.h"
33 #include "printing/nt_printing_migrate.h"
34
35 #define FORMS_PREFIX "FORMS/"
36 #define FORMS_PREFIX_LEN 6
37 #define DRIVERS_PREFIX "DRIVERS/"
38 #define DRIVERS_PREFIX_LEN 8
39 #define PRINTERS_PREFIX "PRINTERS/"
40 #define PRINTERS_PREFIX_LEN 9
41 #define SECDESC_PREFIX "SECDESC/"
42 #define SECDESC_PREFIX_LEN 8
43
44 #define ARG_ENCODING "encoding="
45
46 struct printing_opts {
47         const char *encoding;
48         const char *tdb;
49 };
50
51 static NTSTATUS printing_parse_args(TALLOC_CTX *mem_ctx,
52                                     struct printing_opts **popts,
53                                     int argc, const char **argv)
54 {
55         size_t c;
56         struct printing_opts *o;
57
58         if (argc == 0) {
59                 return NT_STATUS_INVALID_PARAMETER;
60         }
61
62         o = talloc_zero(mem_ctx, struct printing_opts);
63         if (o == NULL) {
64                 return NT_STATUS_INVALID_PARAMETER;
65         }
66
67         for (c = 0; c < argc; c++) {
68                 if (strnequal(argv[c], ARG_ENCODING, sizeof(ARG_ENCODING) - 1)) {
69                         o->encoding = talloc_strdup(o,
70                                         argv[c] + sizeof(ARG_ENCODING) - 1);
71                         if (o->encoding == NULL) {
72                                 return NT_STATUS_NO_MEMORY;
73                         }
74                 } else {
75                         o->tdb = talloc_strdup(o, argv[c]);
76                         if (o->tdb == NULL) {
77                                 return NT_STATUS_NO_MEMORY;
78                         }
79                 }
80         }
81
82         *popts = o;
83         return NT_STATUS_OK;
84 }
85
86 static void dump_form(TALLOC_CTX *mem_ctx,
87                       const char *key_name,
88                       unsigned char *data,
89                       size_t length)
90 {
91         enum ndr_err_code ndr_err;
92         DATA_BLOB blob;
93         char *s;
94         struct ntprinting_form r;
95
96         printf("found form: %s\n", key_name);
97
98         blob = data_blob_const(data, length);
99
100         ZERO_STRUCT(r);
101
102         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
103                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
104         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
105                 d_fprintf(stderr, _("form pull failed: %s\n"),
106                           ndr_errstr(ndr_err));
107                 return;
108         }
109
110         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
111         if (s) {
112                 printf("%s\n", s);
113         }
114 }
115
116 static void dump_driver(TALLOC_CTX *mem_ctx,
117                         const char *key_name,
118                         unsigned char *data,
119                         size_t length,
120                         bool do_string_conversion)
121 {
122         enum ndr_err_code ndr_err;
123         DATA_BLOB blob;
124         char *s;
125         struct ntprinting_driver r;
126
127         printf("found driver: %s\n", key_name);
128
129         blob = data_blob_const(data, length);
130
131         ZERO_STRUCT(r);
132
133         if (do_string_conversion) {
134                 r.string_flags = LIBNDR_FLAG_STR_ASCII;
135         }
136
137         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
138                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
139         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
140                 d_fprintf(stderr, _("driver pull failed: %s\n"),
141                           ndr_errstr(ndr_err));
142                 return;
143         }
144
145         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
146         if (s) {
147                 printf("%s\n", s);
148         }
149 }
150
151 static void dump_printer(TALLOC_CTX *mem_ctx,
152                          const char *key_name,
153                          unsigned char *data,
154                          size_t length,
155                          bool do_string_conversion)
156 {
157         enum ndr_err_code ndr_err;
158         DATA_BLOB blob;
159         char *s;
160         struct ntprinting_printer r;
161
162         printf("found printer: %s\n", key_name);
163
164         blob = data_blob_const(data, length);
165
166         ZERO_STRUCT(r);
167
168         if (do_string_conversion) {
169                 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
170         }
171
172         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
173                    (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
174         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
175                 d_fprintf(stderr, _("printer pull failed: %s\n"),
176                           ndr_errstr(ndr_err));
177                 return;
178         }
179
180         s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
181         if (s) {
182                 printf("%s\n", s);
183         }
184 }
185
186 static void dump_sd(TALLOC_CTX *mem_ctx,
187                     const char *key_name,
188                     unsigned char *data,
189                     size_t length)
190 {
191         enum ndr_err_code ndr_err;
192         DATA_BLOB blob;
193         char *s;
194         struct sec_desc_buf r;
195
196         printf("found security descriptor: %s\n", key_name);
197
198         blob = data_blob_const(data, length);
199
200         ZERO_STRUCT(r);
201
202         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
203                    (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
204         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
205                 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
206                           ndr_errstr(ndr_err));
207                 return;
208         }
209
210         s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
211         if (s) {
212                 printf("%s\n", s);
213         }
214 }
215
216
217 static int net_printing_dump(struct net_context *c, int argc,
218                              const char **argv)
219 {
220         int ret = -1;
221         TALLOC_CTX *ctx = talloc_stackframe();
222         TDB_CONTEXT *tdb;
223         TDB_DATA kbuf, newkey, dbuf;
224         struct printing_opts *o;
225         const char *save_dos_charset = lp_dos_charset();
226         bool do_string_conversion = false;
227         NTSTATUS status;
228
229         if (argc < 1 || c->display_usage) {
230                 d_printf(  "%s\n"
231                            "net printing dump [options] <file.tdb>\n"
232                            "    %s\n",
233                          _("Usage:"),
234                          _("Dump formatted printer information of the tdb."));
235                 d_printf(_("Valid options:\n"));
236                 d_printf(_("    encoding=<CP>   Set the Code Page of the tdb file.\n"
237                            "                    See iconv -l for the list of CP values\n"
238                            "                    (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
239                 goto done;
240         }
241
242         status = printing_parse_args(ctx, &o, argc, argv);
243         if (!NT_STATUS_IS_OK(status)) {
244                 d_fprintf(stderr, _("failed to parse arguments\n"));
245                 goto done;
246         }
247
248         tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
249         if (!tdb) {
250                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
251                 goto done;
252         }
253
254         if (o->encoding != NULL) {
255                 lp_set_cmdline("dos charset", o->encoding);
256                 d_fprintf(stderr, _("do string conversion from %s to %s\n"),
257                                     lp_dos_charset(), lp_unix_charset());
258                 do_string_conversion = true;
259         }
260
261         for (kbuf = tdb_firstkey(tdb);
262              kbuf.dptr;
263              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
264         {
265                 int cmp;
266
267                 dbuf = tdb_fetch(tdb, kbuf);
268                 if (!dbuf.dptr) {
269                         continue;
270                 }
271
272                 cmp = strncmp((const char *)kbuf.dptr,
273                               FORMS_PREFIX,
274                               FORMS_PREFIX_LEN);
275                 if (cmp == 0) {
276                         char *key_name = NULL;
277                         size_t converted_size = 0;
278                         bool ok;
279
280                         ok = pull_ascii_talloc(ctx,
281                                                &key_name,
282                                                (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
283                                                &converted_size);
284                         if (!ok) {
285                                 continue;
286                         }
287
288                         dump_form(ctx, key_name, dbuf.dptr, dbuf.dsize);
289                         TALLOC_FREE(key_name);
290                         SAFE_FREE(dbuf.dptr);
291                         continue;
292                 }
293
294                 cmp = strncmp((const char *)kbuf.dptr,
295                               DRIVERS_PREFIX,
296                               DRIVERS_PREFIX_LEN);
297                 if (cmp == 0) {
298                         char *key_name = NULL;
299                         size_t converted_size = 0;
300                         bool ok;
301
302                         ok = pull_ascii_talloc(ctx,
303                                                &key_name,
304                                                (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
305                                                &converted_size);
306                         if (!ok) {
307                                 continue;
308                         }
309
310                         dump_driver(ctx,
311                                     key_name,
312                                     dbuf.dptr,
313                                     dbuf.dsize,
314                                     do_string_conversion);
315                         TALLOC_FREE(key_name);
316                         SAFE_FREE(dbuf.dptr);
317                         continue;
318                 }
319
320                 cmp = strncmp((const char *)kbuf.dptr,
321                               PRINTERS_PREFIX,
322                               PRINTERS_PREFIX_LEN);
323                 if (cmp == 0) {
324                         char *key_name = NULL;
325                         size_t converted_size = 0;
326                         bool ok;
327
328                         ok = pull_ascii_talloc(ctx,
329                                                &key_name,
330                                                (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
331                                                &converted_size);
332                         if (!ok) {
333                                 continue;
334                         }
335
336                         dump_printer(ctx,
337                                      key_name,
338                                      dbuf.dptr,
339                                      dbuf.dsize,
340                                      do_string_conversion);
341                         TALLOC_FREE(key_name);
342                         SAFE_FREE(dbuf.dptr);
343                         continue;
344                 }
345
346                 cmp = strncmp((const char *)kbuf.dptr,
347                               SECDESC_PREFIX,
348                               SECDESC_PREFIX_LEN);
349                 if (cmp == 0) {
350                         dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
351                         SAFE_FREE(dbuf.dptr);
352                         continue;
353                 }
354
355         }
356
357         ret = 0;
358
359  done:
360         lp_set_cmdline("dos charset", save_dos_charset);
361         talloc_free(ctx);
362         return ret;
363 }
364
365 static NTSTATUS printing_migrate_internal(struct net_context *c,
366                                           const struct dom_sid *domain_sid,
367                                           const char *domain_name,
368                                           struct cli_state *cli,
369                                           struct rpc_pipe_client *winreg_pipe,
370                                           TALLOC_CTX *mem_ctx,
371                                           int argc,
372                                           const char **argv)
373 {
374         struct printing_opts *o;
375         TALLOC_CTX *tmp_ctx;
376         TDB_CONTEXT *tdb;
377         TDB_DATA kbuf, newkey, dbuf;
378         NTSTATUS status;
379         const char *save_dos_charset = lp_dos_charset();
380         bool do_string_conversion = false;
381
382         tmp_ctx = talloc_new(mem_ctx);
383         if (tmp_ctx == NULL) {
384                 return NT_STATUS_NO_MEMORY;
385         }
386
387         status = printing_parse_args(tmp_ctx, &o, argc, argv);
388         if (!NT_STATUS_IS_OK(status)) {
389                 d_fprintf(stderr, _("failed to parse arguments\n"));
390                 goto done;
391         }
392
393         tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
394         if (tdb == NULL) {
395                 d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
396                 status = NT_STATUS_NO_SUCH_FILE;
397                 goto done;
398         }
399
400         if (o->encoding != NULL) {
401                 lp_set_cmdline("dos charset", o->encoding);
402                 d_fprintf(stderr, _("do string conversion from %s to %s\n"),
403                                     lp_dos_charset(), lp_unix_charset());
404                 do_string_conversion = true;
405         }
406
407         for (kbuf = tdb_firstkey(tdb);
408              kbuf.dptr;
409              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
410         {
411                 int cmp;
412
413                 dbuf = tdb_fetch(tdb, kbuf);
414                 if (!dbuf.dptr) {
415                         continue;
416                 }
417
418                 cmp = strncmp((const char *) kbuf.dptr,
419                               FORMS_PREFIX,
420                               FORMS_PREFIX_LEN);
421                 if (cmp == 0) {
422                         char *key_name = NULL;
423                         size_t converted_size = 0;
424                         bool ok;
425
426                         ok = pull_ascii_talloc(tmp_ctx,
427                                                &key_name,
428                                                (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
429                                                &converted_size);
430                         if (!ok) {
431                                 continue;
432                         }
433
434                         printing_tdb_migrate_form(tmp_ctx,
435                                      winreg_pipe,
436                                      key_name,
437                                      dbuf.dptr,
438                                      dbuf.dsize);
439                         TALLOC_FREE(key_name);
440                         SAFE_FREE(dbuf.dptr);
441                         continue;
442                 }
443
444                 cmp = strncmp((const char *) kbuf.dptr,
445                               DRIVERS_PREFIX,
446                               DRIVERS_PREFIX_LEN);
447                 if (cmp == 0) {
448                         char *key_name = NULL;
449                         size_t converted_size = 0;
450                         bool ok;
451
452                         ok = pull_ascii_talloc(tmp_ctx,
453                                                &key_name,
454                                                (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
455                                                &converted_size);
456                         if (!ok) {
457                                 continue;
458                         }
459
460                         printing_tdb_migrate_driver(tmp_ctx,
461                                        winreg_pipe,
462                                        key_name,
463                                        dbuf.dptr,
464                                        dbuf.dsize,
465                                        do_string_conversion);
466                         TALLOC_FREE(key_name);
467                         SAFE_FREE(dbuf.dptr);
468                         continue;
469                 }
470
471                 cmp = strncmp((const char *) kbuf.dptr,
472                               PRINTERS_PREFIX,
473                               PRINTERS_PREFIX_LEN);
474                 if (cmp == 0) {
475                         char *key_name = NULL;
476                         size_t converted_size = 0;
477                         bool ok;
478
479                         ok = pull_ascii_talloc(tmp_ctx,
480                                                &key_name,
481                                                (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
482                                                &converted_size);
483                         if (!ok) {
484                                 continue;
485                         }
486
487                         printing_tdb_migrate_printer(tmp_ctx,
488                                         winreg_pipe,
489                                         key_name,
490                                         dbuf.dptr,
491                                         dbuf.dsize,
492                                         do_string_conversion);
493                         TALLOC_FREE(key_name);
494                         SAFE_FREE(dbuf.dptr);
495                         continue;
496                 }
497                 SAFE_FREE(dbuf.dptr);
498         }
499
500         for (kbuf = tdb_firstkey(tdb);
501              kbuf.dptr;
502              newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
503         {
504                 dbuf = tdb_fetch(tdb, kbuf);
505                 if (!dbuf.dptr) {
506                         continue;
507                 }
508
509                 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
510                         printing_tdb_migrate_secdesc(tmp_ctx,
511                                         winreg_pipe,
512                                         (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
513                                         dbuf.dptr,
514                                         dbuf.dsize);
515                         SAFE_FREE(dbuf.dptr);
516                         continue;
517                 }
518                 SAFE_FREE(dbuf.dptr);
519
520         }
521
522         status = NT_STATUS_OK;
523
524  done:
525         lp_set_cmdline("dos charset", save_dos_charset);
526         talloc_free(tmp_ctx);
527         return status;
528 }
529
530 static int net_printing_migrate(struct net_context *c,
531                                 int argc,
532                                 const char **argv)
533 {
534         if (argc < 1 || c->display_usage) {
535                 d_printf(  "%s\n"
536                            "net printing migrate [options] <file.tdb>\n"
537                            "    %s\n",
538                          _("Usage:"),
539                          _("Migrate tdb printing files to new storage"));
540                 d_printf(_("Valid options:\n"));
541                 d_printf(_("    encoding=<CP>   Set the Code Page of the tdb file.\n"
542                            "                    See iconv -l for the list of CP values\n"
543                            "                    (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
544                 return 0;
545         }
546
547         return run_rpc_command(c,
548                                NULL,
549                                &ndr_table_winreg,
550                                0,
551                                printing_migrate_internal,
552                                argc,
553                                argv);
554 }
555 /**
556  * 'net printing' entrypoint.
557  * @param argc  Standard main() style argc.
558  * @param argv  Standard main() style argv. Initial components are already
559  *              stripped.
560  **/
561
562 int net_printing(struct net_context *c, int argc, const char **argv)
563 {
564         int ret = -1;
565
566         struct functable func[] = {
567                 {
568                         "dump",
569                         net_printing_dump,
570                         NET_TRANSPORT_LOCAL,
571                         N_("Dump printer databases"),
572                         N_("net printing dump\n"
573                            "    Dump tdb printing file")
574                 },
575
576                 {
577                         "migrate",
578                         net_printing_migrate,
579                         NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
580                         N_("Migrate printer databases"),
581                         N_("net printing migrate\n"
582                            "    Migrate tdb printing files to new storage")
583                 },
584
585         { NULL, NULL, 0, NULL, NULL }
586         };
587
588         ret = net_run_function(c, argc, argv, "net printing", func);
589
590         return ret;
591 }