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 :
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 0 : 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 0 : if (argc == 0) {
59 0 : return NT_STATUS_INVALID_PARAMETER;
60 : }
61 :
62 0 : o = talloc_zero(mem_ctx, struct printing_opts);
63 0 : if (o == NULL) {
64 0 : return NT_STATUS_INVALID_PARAMETER;
65 : }
66 :
67 0 : for (c = 0; c < argc; c++) {
68 0 : if (strnequal(argv[c], ARG_ENCODING, sizeof(ARG_ENCODING) - 1)) {
69 0 : o->encoding = talloc_strdup(o,
70 0 : argv[c] + sizeof(ARG_ENCODING) - 1);
71 0 : if (o->encoding == NULL) {
72 0 : return NT_STATUS_NO_MEMORY;
73 : }
74 : } else {
75 0 : o->tdb = talloc_strdup(o, argv[c]);
76 0 : if (o->tdb == NULL) {
77 0 : return NT_STATUS_NO_MEMORY;
78 : }
79 : }
80 : }
81 :
82 0 : *popts = o;
83 0 : return NT_STATUS_OK;
84 : }
85 :
86 0 : 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 0 : printf("found form: %s\n", key_name);
97 :
98 0 : blob = data_blob_const(data, length);
99 :
100 0 : ZERO_STRUCT(r);
101 :
102 0 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
103 : (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
104 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
105 0 : d_fprintf(stderr, _("form pull failed: %s\n"),
106 : ndr_errstr(ndr_err));
107 0 : return;
108 : }
109 :
110 0 : s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
111 0 : if (s) {
112 0 : printf("%s\n", s);
113 : }
114 : }
115 :
116 0 : 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 0 : printf("found driver: %s\n", key_name);
128 :
129 0 : blob = data_blob_const(data, length);
130 :
131 0 : ZERO_STRUCT(r);
132 :
133 0 : if (do_string_conversion) {
134 0 : r.string_flags = LIBNDR_FLAG_STR_ASCII;
135 : }
136 :
137 0 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
138 : (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
139 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
140 0 : d_fprintf(stderr, _("driver pull failed: %s\n"),
141 : ndr_errstr(ndr_err));
142 0 : return;
143 : }
144 :
145 0 : s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
146 0 : if (s) {
147 0 : printf("%s\n", s);
148 : }
149 : }
150 :
151 0 : 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 0 : printf("found printer: %s\n", key_name);
163 :
164 0 : blob = data_blob_const(data, length);
165 :
166 0 : ZERO_STRUCT(r);
167 :
168 0 : if (do_string_conversion) {
169 0 : r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
170 : }
171 :
172 0 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
173 : (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
174 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
175 0 : d_fprintf(stderr, _("printer pull failed: %s\n"),
176 : ndr_errstr(ndr_err));
177 0 : return;
178 : }
179 :
180 0 : s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
181 0 : if (s) {
182 0 : printf("%s\n", s);
183 : }
184 : }
185 :
186 0 : 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 0 : printf("found security descriptor: %s\n", key_name);
197 :
198 0 : blob = data_blob_const(data, length);
199 :
200 0 : ZERO_STRUCT(r);
201 :
202 0 : ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
203 : (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
204 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
205 0 : d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
206 : ndr_errstr(ndr_err));
207 0 : return;
208 : }
209 :
210 0 : s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
211 0 : if (s) {
212 0 : printf("%s\n", s);
213 : }
214 : }
215 :
216 :
217 0 : static int net_printing_dump(struct net_context *c, int argc,
218 : const char **argv)
219 : {
220 0 : int ret = -1;
221 0 : TALLOC_CTX *ctx = talloc_stackframe();
222 : TDB_CONTEXT *tdb;
223 : TDB_DATA kbuf, newkey, dbuf;
224 : struct printing_opts *o;
225 0 : const char *save_dos_charset = lp_dos_charset();
226 0 : bool do_string_conversion = false;
227 : NTSTATUS status;
228 :
229 0 : if (argc < 1 || c->display_usage) {
230 0 : 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 0 : d_printf(_("Valid options:\n"));
236 0 : 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 0 : goto done;
240 : }
241 :
242 0 : status = printing_parse_args(ctx, &o, argc, argv);
243 0 : if (!NT_STATUS_IS_OK(status)) {
244 0 : d_fprintf(stderr, _("failed to parse arguments\n"));
245 0 : goto done;
246 : }
247 :
248 0 : tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
249 0 : if (!tdb) {
250 0 : d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
251 0 : goto done;
252 : }
253 :
254 0 : if (o->encoding != NULL) {
255 0 : lp_set_cmdline("dos charset", o->encoding);
256 0 : d_fprintf(stderr, _("do string conversion from %s to %s\n"),
257 : lp_dos_charset(), lp_unix_charset());
258 0 : do_string_conversion = true;
259 : }
260 :
261 0 : for (kbuf = tdb_firstkey(tdb);
262 0 : kbuf.dptr;
263 0 : newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
264 : {
265 : int cmp;
266 :
267 0 : dbuf = tdb_fetch(tdb, kbuf);
268 0 : if (!dbuf.dptr) {
269 0 : continue;
270 : }
271 :
272 0 : cmp = strncmp((const char *)kbuf.dptr,
273 : FORMS_PREFIX,
274 : FORMS_PREFIX_LEN);
275 0 : if (cmp == 0) {
276 0 : char *key_name = NULL;
277 0 : size_t converted_size = 0;
278 : bool ok;
279 :
280 0 : ok = pull_ascii_talloc(ctx,
281 : &key_name,
282 0 : (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
283 : &converted_size);
284 0 : if (!ok) {
285 0 : continue;
286 : }
287 :
288 0 : dump_form(ctx, key_name, dbuf.dptr, dbuf.dsize);
289 0 : TALLOC_FREE(key_name);
290 0 : SAFE_FREE(dbuf.dptr);
291 0 : continue;
292 : }
293 :
294 0 : cmp = strncmp((const char *)kbuf.dptr,
295 : DRIVERS_PREFIX,
296 : DRIVERS_PREFIX_LEN);
297 0 : if (cmp == 0) {
298 0 : char *key_name = NULL;
299 0 : size_t converted_size = 0;
300 : bool ok;
301 :
302 0 : ok = pull_ascii_talloc(ctx,
303 : &key_name,
304 0 : (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
305 : &converted_size);
306 0 : if (!ok) {
307 0 : continue;
308 : }
309 :
310 0 : dump_driver(ctx,
311 : key_name,
312 : dbuf.dptr,
313 : dbuf.dsize,
314 : do_string_conversion);
315 0 : TALLOC_FREE(key_name);
316 0 : SAFE_FREE(dbuf.dptr);
317 0 : continue;
318 : }
319 :
320 0 : cmp = strncmp((const char *)kbuf.dptr,
321 : PRINTERS_PREFIX,
322 : PRINTERS_PREFIX_LEN);
323 0 : if (cmp == 0) {
324 0 : char *key_name = NULL;
325 0 : size_t converted_size = 0;
326 : bool ok;
327 :
328 0 : ok = pull_ascii_talloc(ctx,
329 : &key_name,
330 0 : (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
331 : &converted_size);
332 0 : if (!ok) {
333 0 : continue;
334 : }
335 :
336 0 : dump_printer(ctx,
337 : key_name,
338 : dbuf.dptr,
339 : dbuf.dsize,
340 : do_string_conversion);
341 0 : TALLOC_FREE(key_name);
342 0 : SAFE_FREE(dbuf.dptr);
343 0 : continue;
344 : }
345 :
346 0 : cmp = strncmp((const char *)kbuf.dptr,
347 : SECDESC_PREFIX,
348 : SECDESC_PREFIX_LEN);
349 0 : if (cmp == 0) {
350 0 : dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
351 0 : SAFE_FREE(dbuf.dptr);
352 0 : continue;
353 : }
354 :
355 : }
356 :
357 0 : ret = 0;
358 :
359 0 : done:
360 0 : lp_set_cmdline("dos charset", save_dos_charset);
361 0 : talloc_free(ctx);
362 0 : return ret;
363 : }
364 :
365 0 : 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 0 : const char *save_dos_charset = lp_dos_charset();
380 0 : bool do_string_conversion = false;
381 :
382 0 : tmp_ctx = talloc_new(mem_ctx);
383 0 : if (tmp_ctx == NULL) {
384 0 : return NT_STATUS_NO_MEMORY;
385 : }
386 :
387 0 : status = printing_parse_args(tmp_ctx, &o, argc, argv);
388 0 : if (!NT_STATUS_IS_OK(status)) {
389 0 : d_fprintf(stderr, _("failed to parse arguments\n"));
390 0 : goto done;
391 : }
392 :
393 0 : tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
394 0 : if (tdb == NULL) {
395 0 : d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
396 0 : status = NT_STATUS_NO_SUCH_FILE;
397 0 : goto done;
398 : }
399 :
400 0 : if (o->encoding != NULL) {
401 0 : lp_set_cmdline("dos charset", o->encoding);
402 0 : d_fprintf(stderr, _("do string conversion from %s to %s\n"),
403 : lp_dos_charset(), lp_unix_charset());
404 0 : do_string_conversion = true;
405 : }
406 :
407 0 : for (kbuf = tdb_firstkey(tdb);
408 0 : kbuf.dptr;
409 0 : newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
410 : {
411 : int cmp;
412 :
413 0 : dbuf = tdb_fetch(tdb, kbuf);
414 0 : if (!dbuf.dptr) {
415 0 : continue;
416 : }
417 :
418 0 : cmp = strncmp((const char *) kbuf.dptr,
419 : FORMS_PREFIX,
420 : FORMS_PREFIX_LEN);
421 0 : if (cmp == 0) {
422 0 : char *key_name = NULL;
423 0 : size_t converted_size = 0;
424 : bool ok;
425 :
426 0 : ok = pull_ascii_talloc(tmp_ctx,
427 : &key_name,
428 0 : (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
429 : &converted_size);
430 0 : if (!ok) {
431 0 : continue;
432 : }
433 :
434 0 : printing_tdb_migrate_form(tmp_ctx,
435 : winreg_pipe,
436 : key_name,
437 : dbuf.dptr,
438 : dbuf.dsize);
439 0 : TALLOC_FREE(key_name);
440 0 : SAFE_FREE(dbuf.dptr);
441 0 : continue;
442 : }
443 :
444 0 : cmp = strncmp((const char *) kbuf.dptr,
445 : DRIVERS_PREFIX,
446 : DRIVERS_PREFIX_LEN);
447 0 : if (cmp == 0) {
448 0 : char *key_name = NULL;
449 0 : size_t converted_size = 0;
450 : bool ok;
451 :
452 0 : ok = pull_ascii_talloc(tmp_ctx,
453 : &key_name,
454 0 : (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
455 : &converted_size);
456 0 : if (!ok) {
457 0 : continue;
458 : }
459 :
460 0 : printing_tdb_migrate_driver(tmp_ctx,
461 : winreg_pipe,
462 : key_name,
463 : dbuf.dptr,
464 : dbuf.dsize,
465 : do_string_conversion);
466 0 : TALLOC_FREE(key_name);
467 0 : SAFE_FREE(dbuf.dptr);
468 0 : continue;
469 : }
470 :
471 0 : cmp = strncmp((const char *) kbuf.dptr,
472 : PRINTERS_PREFIX,
473 : PRINTERS_PREFIX_LEN);
474 0 : if (cmp == 0) {
475 0 : char *key_name = NULL;
476 0 : size_t converted_size = 0;
477 : bool ok;
478 :
479 0 : ok = pull_ascii_talloc(tmp_ctx,
480 : &key_name,
481 0 : (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
482 : &converted_size);
483 0 : if (!ok) {
484 0 : continue;
485 : }
486 :
487 0 : printing_tdb_migrate_printer(tmp_ctx,
488 : winreg_pipe,
489 : key_name,
490 : dbuf.dptr,
491 : dbuf.dsize,
492 : do_string_conversion);
493 0 : TALLOC_FREE(key_name);
494 0 : SAFE_FREE(dbuf.dptr);
495 0 : continue;
496 : }
497 0 : SAFE_FREE(dbuf.dptr);
498 : }
499 :
500 0 : for (kbuf = tdb_firstkey(tdb);
501 0 : kbuf.dptr;
502 0 : newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
503 : {
504 0 : dbuf = tdb_fetch(tdb, kbuf);
505 0 : if (!dbuf.dptr) {
506 0 : continue;
507 : }
508 :
509 0 : if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
510 0 : printing_tdb_migrate_secdesc(tmp_ctx,
511 : winreg_pipe,
512 0 : (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
513 : dbuf.dptr,
514 : dbuf.dsize);
515 0 : SAFE_FREE(dbuf.dptr);
516 0 : continue;
517 : }
518 0 : SAFE_FREE(dbuf.dptr);
519 :
520 : }
521 :
522 0 : status = NT_STATUS_OK;
523 :
524 0 : done:
525 0 : lp_set_cmdline("dos charset", save_dos_charset);
526 0 : talloc_free(tmp_ctx);
527 0 : return status;
528 : }
529 :
530 0 : static int net_printing_migrate(struct net_context *c,
531 : int argc,
532 : const char **argv)
533 : {
534 0 : if (argc < 1 || c->display_usage) {
535 0 : 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 0 : d_printf(_("Valid options:\n"));
541 0 : 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 0 : return 0;
545 : }
546 :
547 0 : 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 0 : int net_printing(struct net_context *c, int argc, const char **argv)
563 : {
564 0 : int ret = -1;
565 :
566 0 : 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 0 : ret = net_run_function(c, argc, argv, "net printing", func);
589 :
590 0 : return ret;
591 : }
|