s3: vfs_fruit: Ensure we operate on a copy of the incoming security descriptor.
[Samba.git] / source3 / utils / net_printing.c
blob8287e0ea04ac088b11a64319631d1bafd5dfb589
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Local printing tdb migration interface
6 Copyright (C) Guenther Deschner 2010
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.
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.
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/>.
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"
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
44 #define ARG_ENCODING "encoding="
46 struct printing_opts {
47 const char *encoding;
48 const char *tdb;
51 static NTSTATUS printing_parse_args(TALLOC_CTX *mem_ctx,
52 struct printing_opts **popts,
53 int argc, const char **argv)
55 size_t c;
56 struct printing_opts *o;
58 if (argc == 0) {
59 return NT_STATUS_INVALID_PARAMETER;
62 o = talloc_zero(mem_ctx, struct printing_opts);
63 if (o == NULL) {
64 return NT_STATUS_INVALID_PARAMETER;
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;
74 } else {
75 o->tdb = talloc_strdup(o, argv[c]);
76 if (o->tdb == NULL) {
77 return NT_STATUS_NO_MEMORY;
82 *popts = o;
83 return NT_STATUS_OK;
86 static void dump_form(TALLOC_CTX *mem_ctx,
87 const char *key_name,
88 unsigned char *data,
89 size_t length)
91 enum ndr_err_code ndr_err;
92 DATA_BLOB blob;
93 char *s;
94 struct ntprinting_form r;
96 printf("found form: %s\n", key_name);
98 blob = data_blob_const(data, length);
100 ZERO_STRUCT(r);
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;
110 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
111 if (s) {
112 printf("%s\n", s);
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)
122 enum ndr_err_code ndr_err;
123 DATA_BLOB blob;
124 char *s;
125 struct ntprinting_driver r;
127 printf("found driver: %s\n", key_name);
129 blob = data_blob_const(data, length);
131 ZERO_STRUCT(r);
133 if (do_string_conversion) {
134 r.string_flags = LIBNDR_FLAG_STR_ASCII;
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;
145 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
146 if (s) {
147 printf("%s\n", s);
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)
157 enum ndr_err_code ndr_err;
158 DATA_BLOB blob;
159 char *s;
160 struct ntprinting_printer r;
162 printf("found printer: %s\n", key_name);
164 blob = data_blob_const(data, length);
166 ZERO_STRUCT(r);
168 if (do_string_conversion) {
169 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
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;
180 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
181 if (s) {
182 printf("%s\n", s);
186 static void dump_sd(TALLOC_CTX *mem_ctx,
187 const char *key_name,
188 unsigned char *data,
189 size_t length)
191 enum ndr_err_code ndr_err;
192 DATA_BLOB blob;
193 char *s;
194 struct sec_desc_buf r;
196 printf("found security descriptor: %s\n", key_name);
198 blob = data_blob_const(data, length);
200 ZERO_STRUCT(r);
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;
210 s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
211 if (s) {
212 printf("%s\n", s);
217 static int net_printing_dump(struct net_context *c, int argc,
218 const char **argv)
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;
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 formated 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;
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;
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;
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;
261 for (kbuf = tdb_firstkey(tdb);
262 kbuf.dptr;
263 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
265 int cmp;
267 dbuf = tdb_fetch(tdb, kbuf);
268 if (!dbuf.dptr) {
269 continue;
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;
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;
288 dump_form(ctx, key_name, dbuf.dptr, dbuf.dsize);
289 TALLOC_FREE(key_name);
290 SAFE_FREE(dbuf.dptr);
291 continue;
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;
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;
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;
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;
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;
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;
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;
357 ret = 0;
359 done:
360 lp_set_cmdline("dos charset", save_dos_charset);
361 talloc_free(ctx);
362 return ret;
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)
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;
382 tmp_ctx = talloc_new(mem_ctx);
383 if (tmp_ctx == NULL) {
384 return NT_STATUS_NO_MEMORY;
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;
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;
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;
407 for (kbuf = tdb_firstkey(tdb);
408 kbuf.dptr;
409 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
411 int cmp;
413 dbuf = tdb_fetch(tdb, kbuf);
414 if (!dbuf.dptr) {
415 continue;
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;
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;
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;
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;
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;
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;
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;
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;
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;
497 SAFE_FREE(dbuf.dptr);
500 for (kbuf = tdb_firstkey(tdb);
501 kbuf.dptr;
502 newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
504 dbuf = tdb_fetch(tdb, kbuf);
505 if (!dbuf.dptr) {
506 continue;
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;
518 SAFE_FREE(dbuf.dptr);
522 status = NT_STATUS_OK;
524 done:
525 lp_set_cmdline("dos charset", save_dos_charset);
526 talloc_free(tmp_ctx);
527 return status;
530 static int net_printing_migrate(struct net_context *c,
531 int argc,
532 const char **argv)
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;
547 return run_rpc_command(c,
548 NULL,
549 &ndr_table_winreg,
551 printing_migrate_internal,
552 argc,
553 argv);
556 * 'net printing' entrypoint.
557 * @param argc Standard main() style argc.
558 * @param argv Standard main() style argv. Initial components are already
559 * stripped.
562 int net_printing(struct net_context *c, int argc, const char **argv)
564 int ret = -1;
566 struct functable func[] = {
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")
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")
585 { NULL, NULL, 0, NULL, NULL }
588 ret = net_run_function(c, argc, argv, "net printing", func);
590 return ret;