VERSION: Disable git snapshots for the 4.0.24 release.
[Samba.git] / source3 / utils / net_printing.c
blob4b9ed435b0e82ea0c86cf7d684a7e7cf0d4df50e
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 DRIVERS_PREFIX "DRIVERS/"
37 #define PRINTERS_PREFIX "PRINTERS/"
38 #define SECDESC_PREFIX "SECDESC/"
40 #define ARG_ENCODING "encoding="
42 struct printing_opts {
43 const char *encoding;
44 const char *tdb;
47 static NTSTATUS printing_parse_args(TALLOC_CTX *mem_ctx,
48 struct printing_opts **popts,
49 int argc, const char **argv)
51 size_t c;
52 struct printing_opts *o;
54 if (argc == 0) {
55 return NT_STATUS_INVALID_PARAMETER;
58 o = talloc_zero(mem_ctx, struct printing_opts);
59 if (o == NULL) {
60 return NT_STATUS_INVALID_PARAMETER;
63 for (c = 0; c < argc; c++) {
64 if (strnequal(argv[c], ARG_ENCODING, sizeof(ARG_ENCODING) - 1)) {
65 o->encoding = talloc_strdup(o,
66 argv[c] + sizeof(ARG_ENCODING) - 1);
67 if (o->encoding == NULL) {
68 return NT_STATUS_NO_MEMORY;
70 } else {
71 o->tdb = talloc_strdup(o, argv[c]);
72 if (o->tdb == NULL) {
73 return NT_STATUS_NO_MEMORY;
78 *popts = o;
79 return NT_STATUS_OK;
82 static void dump_form(TALLOC_CTX *mem_ctx,
83 const char *key_name,
84 unsigned char *data,
85 size_t length)
87 enum ndr_err_code ndr_err;
88 DATA_BLOB blob;
89 char *s;
90 struct ntprinting_form r;
92 printf("found form: %s\n", key_name);
94 blob = data_blob_const(data, length);
96 ZERO_STRUCT(r);
98 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
99 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
100 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
101 d_fprintf(stderr, _("form pull failed: %s\n"),
102 ndr_errstr(ndr_err));
103 return;
106 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
107 if (s) {
108 printf("%s\n", s);
112 static void dump_driver(TALLOC_CTX *mem_ctx,
113 const char *key_name,
114 unsigned char *data,
115 size_t length,
116 bool do_string_conversion)
118 enum ndr_err_code ndr_err;
119 DATA_BLOB blob;
120 char *s;
121 struct ntprinting_driver r;
123 printf("found driver: %s\n", key_name);
125 blob = data_blob_const(data, length);
127 ZERO_STRUCT(r);
129 if (do_string_conversion) {
130 r.string_flags = LIBNDR_FLAG_STR_ASCII;
133 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
134 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
135 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
136 d_fprintf(stderr, _("driver pull failed: %s\n"),
137 ndr_errstr(ndr_err));
138 return;
141 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
142 if (s) {
143 printf("%s\n", s);
147 static void dump_printer(TALLOC_CTX *mem_ctx,
148 const char *key_name,
149 unsigned char *data,
150 size_t length,
151 bool do_string_conversion)
153 enum ndr_err_code ndr_err;
154 DATA_BLOB blob;
155 char *s;
156 struct ntprinting_printer r;
158 printf("found printer: %s\n", key_name);
160 blob = data_blob_const(data, length);
162 ZERO_STRUCT(r);
164 if (do_string_conversion) {
165 r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
168 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
169 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
170 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
171 d_fprintf(stderr, _("printer pull failed: %s\n"),
172 ndr_errstr(ndr_err));
173 return;
176 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
177 if (s) {
178 printf("%s\n", s);
182 static void dump_sd(TALLOC_CTX *mem_ctx,
183 const char *key_name,
184 unsigned char *data,
185 size_t length)
187 enum ndr_err_code ndr_err;
188 DATA_BLOB blob;
189 char *s;
190 struct sec_desc_buf r;
192 printf("found security descriptor: %s\n", key_name);
194 blob = data_blob_const(data, length);
196 ZERO_STRUCT(r);
198 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
199 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
200 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
201 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
202 ndr_errstr(ndr_err));
203 return;
206 s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
207 if (s) {
208 printf("%s\n", s);
213 static int net_printing_dump(struct net_context *c, int argc,
214 const char **argv)
216 int ret = -1;
217 TALLOC_CTX *ctx = talloc_stackframe();
218 TDB_CONTEXT *tdb;
219 TDB_DATA kbuf, dbuf;
220 struct printing_opts *o;
221 const char *save_dos_charset = lp_dos_charset();
222 bool do_string_conversion = false;
223 NTSTATUS status;
225 if (argc < 1 || c->display_usage) {
226 d_printf( "%s\n"
227 "net printing dump [options] <file.tdb>\n"
228 " %s\n",
229 _("Usage:"),
230 _("Dump formated printer information of the tdb."));
231 d_printf(_("Valid options:\n"));
232 d_printf(_(" encoding=<CP> Set the Code Page of the tdb file.\n"
233 " See iconv -l for the list of CP values\n"
234 " (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
235 goto done;
238 status = printing_parse_args(ctx, &o, argc, argv);
239 if (!NT_STATUS_IS_OK(status)) {
240 d_fprintf(stderr, _("failed to parse arguments\n"));
241 goto done;
244 tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
245 if (!tdb) {
246 d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
247 goto done;
250 if (o->encoding != NULL) {
251 lp_set_cmdline("dos charset", o->encoding);
252 d_fprintf(stderr, _("do string conversion from %s to %s\n"),
253 lp_dos_charset(), lp_unix_charset());
254 do_string_conversion = true;
257 for (kbuf = tdb_firstkey_compat(tdb);
258 kbuf.dptr;
259 kbuf = tdb_nextkey_compat(tdb, kbuf))
261 dbuf = tdb_fetch_compat(tdb, kbuf);
262 if (!dbuf.dptr) {
263 continue;
266 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
267 dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
268 SAFE_FREE(dbuf.dptr);
269 continue;
272 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
273 dump_driver(ctx,
274 (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX),
275 dbuf.dptr,
276 dbuf.dsize,
277 do_string_conversion);
278 SAFE_FREE(dbuf.dptr);
279 continue;
282 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
283 dump_printer(ctx,
284 (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX),
285 dbuf.dptr,
286 dbuf.dsize,
287 do_string_conversion);
288 SAFE_FREE(dbuf.dptr);
289 continue;
292 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
293 dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
294 SAFE_FREE(dbuf.dptr);
295 continue;
300 ret = 0;
302 done:
303 lp_set_cmdline("dos charset", save_dos_charset);
304 talloc_free(ctx);
305 return ret;
308 static NTSTATUS printing_migrate_internal(struct net_context *c,
309 const struct dom_sid *domain_sid,
310 const char *domain_name,
311 struct cli_state *cli,
312 struct rpc_pipe_client *winreg_pipe,
313 TALLOC_CTX *mem_ctx,
314 int argc,
315 const char **argv)
317 struct printing_opts *o;
318 TALLOC_CTX *tmp_ctx;
319 TDB_CONTEXT *tdb;
320 TDB_DATA kbuf, dbuf;
321 NTSTATUS status;
322 const char *save_dos_charset = lp_dos_charset();
323 bool do_string_conversion = false;
325 tmp_ctx = talloc_new(mem_ctx);
326 if (tmp_ctx == NULL) {
327 return NT_STATUS_NO_MEMORY;
330 status = printing_parse_args(tmp_ctx, &o, argc, argv);
331 if (!NT_STATUS_IS_OK(status)) {
332 d_fprintf(stderr, _("failed to parse arguments\n"));
333 goto done;
336 tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
337 if (tdb == NULL) {
338 d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
339 status = NT_STATUS_NO_SUCH_FILE;
340 goto done;
343 if (o->encoding != NULL) {
344 lp_set_cmdline("dos charset", o->encoding);
345 d_fprintf(stderr, _("do string conversion from %s to %s\n"),
346 lp_dos_charset(), lp_unix_charset());
347 do_string_conversion = true;
350 for (kbuf = tdb_firstkey_compat(tdb);
351 kbuf.dptr;
352 kbuf = tdb_nextkey_compat(tdb, kbuf))
354 dbuf = tdb_fetch_compat(tdb, kbuf);
355 if (!dbuf.dptr) {
356 continue;
359 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
360 printing_tdb_migrate_form(tmp_ctx,
361 winreg_pipe,
362 (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
363 dbuf.dptr,
364 dbuf.dsize);
365 SAFE_FREE(dbuf.dptr);
366 continue;
369 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
370 printing_tdb_migrate_driver(tmp_ctx,
371 winreg_pipe,
372 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
373 dbuf.dptr,
374 dbuf.dsize,
375 do_string_conversion);
376 SAFE_FREE(dbuf.dptr);
377 continue;
380 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
381 printing_tdb_migrate_printer(tmp_ctx,
382 winreg_pipe,
383 (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
384 dbuf.dptr,
385 dbuf.dsize,
386 do_string_conversion);
387 SAFE_FREE(dbuf.dptr);
388 continue;
390 SAFE_FREE(dbuf.dptr);
393 for (kbuf = tdb_firstkey_compat(tdb);
394 kbuf.dptr;
395 kbuf = tdb_nextkey_compat(tdb, kbuf))
397 dbuf = tdb_fetch_compat(tdb, kbuf);
398 if (!dbuf.dptr) {
399 continue;
402 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
403 printing_tdb_migrate_secdesc(tmp_ctx,
404 winreg_pipe,
405 (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
406 dbuf.dptr,
407 dbuf.dsize);
408 SAFE_FREE(dbuf.dptr);
409 continue;
411 SAFE_FREE(dbuf.dptr);
415 status = NT_STATUS_OK;
417 done:
418 lp_set_cmdline("dos charset", save_dos_charset);
419 talloc_free(tmp_ctx);
420 return status;
423 static int net_printing_migrate(struct net_context *c,
424 int argc,
425 const char **argv)
427 if (argc < 1 || c->display_usage) {
428 d_printf( "%s\n"
429 "net printing migrate [options] <file.tdb>\n"
430 " %s\n",
431 _("Usage:"),
432 _("Migrate tdb printing files to new storage"));
433 d_printf(_("Valid options:\n"));
434 d_printf(_(" encoding=<CP> Set the Code Page of the tdb file.\n"
435 " See iconv -l for the list of CP values\n"
436 " (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
437 return 0;
440 return run_rpc_command(c,
441 NULL,
442 &ndr_table_winreg,
444 printing_migrate_internal,
445 argc,
446 argv);
449 * 'net printing' entrypoint.
450 * @param argc Standard main() style argc.
451 * @param argv Standard main() style argv. Initial components are already
452 * stripped.
455 int net_printing(struct net_context *c, int argc, const char **argv)
457 int ret = -1;
459 struct functable func[] = {
461 "dump",
462 net_printing_dump,
463 NET_TRANSPORT_LOCAL,
464 N_("Dump printer databases"),
465 N_("net printing dump\n"
466 " Dump tdb printing file")
470 "migrate",
471 net_printing_migrate,
472 NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
473 N_("Migrate printer databases"),
474 N_("net printing migrate\n"
475 " Migrate tdb printing files to new storage")
478 { NULL, NULL, 0, NULL, NULL }
481 ret = net_run_function(c, argc, argv, "net printing", func);
483 return ret;