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