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/>.
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"
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 {
47 static NTSTATUS printing_parse_args(TALLOC_CTX *mem_ctx,
48 struct printing_opts **popts,
49 int argc, const char **argv)
52 struct printing_opts *o;
55 return NT_STATUS_INVALID_PARAMETER;
58 o = talloc_zero(mem_ctx, struct printing_opts);
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;
71 o->tdb = talloc_strdup(o, argv[c]);
73 return NT_STATUS_NO_MEMORY;
82 static void dump_form(TALLOC_CTX *mem_ctx,
87 enum ndr_err_code ndr_err;
90 struct ntprinting_form r;
92 printf("found form: %s\n", key_name);
94 blob = data_blob_const(data, length);
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));
106 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
112 static void dump_driver(TALLOC_CTX *mem_ctx,
113 const char *key_name,
117 enum ndr_err_code ndr_err;
120 struct ntprinting_driver r;
122 printf("found driver: %s\n", key_name);
124 blob = data_blob_const(data, length);
128 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
129 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
130 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
131 d_fprintf(stderr, _("driver pull failed: %s\n"),
132 ndr_errstr(ndr_err));
136 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
142 static void dump_printer(TALLOC_CTX *mem_ctx,
143 const char *key_name,
147 enum ndr_err_code ndr_err;
150 struct ntprinting_printer r;
152 printf("found printer: %s\n", key_name);
154 blob = data_blob_const(data, length);
158 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
159 (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
160 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
161 d_fprintf(stderr, _("printer pull failed: %s\n"),
162 ndr_errstr(ndr_err));
166 s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
172 static void dump_sd(TALLOC_CTX *mem_ctx,
173 const char *key_name,
177 enum ndr_err_code ndr_err;
180 struct sec_desc_buf r;
182 printf("found security descriptor: %s\n", key_name);
184 blob = data_blob_const(data, length);
188 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
189 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
190 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
191 d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
192 ndr_errstr(ndr_err));
196 s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
203 static int net_printing_dump(struct net_context *c, int argc,
207 TALLOC_CTX *ctx = talloc_stackframe();
211 if (argc < 1 || c->display_usage) {
212 d_fprintf(stderr, "%s\nnet printing dump <file.tdb>\n",
217 tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0600);
219 d_fprintf(stderr, _("failed to open tdb file: %s\n"), argv[0]);
223 for (kbuf = tdb_firstkey_compat(tdb);
225 kbuf = tdb_nextkey_compat(tdb, kbuf))
227 dbuf = tdb_fetch_compat(tdb, kbuf);
232 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
233 dump_form(ctx, (const char *)kbuf.dptr+strlen(FORMS_PREFIX), dbuf.dptr, dbuf.dsize);
234 SAFE_FREE(dbuf.dptr);
238 if (strncmp((const char *)kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
239 dump_driver(ctx, (const char *)kbuf.dptr+strlen(DRIVERS_PREFIX), dbuf.dptr, dbuf.dsize);
240 SAFE_FREE(dbuf.dptr);
244 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
245 dump_printer(ctx, (const char *)kbuf.dptr+strlen(PRINTERS_PREFIX), dbuf.dptr, dbuf.dsize);
246 SAFE_FREE(dbuf.dptr);
250 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
251 dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
252 SAFE_FREE(dbuf.dptr);
265 static NTSTATUS printing_migrate_internal(struct net_context *c,
266 const struct dom_sid *domain_sid,
267 const char *domain_name,
268 struct cli_state *cli,
269 struct rpc_pipe_client *winreg_pipe,
274 struct printing_opts *o;
279 const char *save_dos_charset = lp_dos_charset();
280 bool do_string_conversion = false;
282 tmp_ctx = talloc_new(mem_ctx);
283 if (tmp_ctx == NULL) {
284 return NT_STATUS_NO_MEMORY;
287 status = printing_parse_args(tmp_ctx, &o, argc, argv);
288 if (!NT_STATUS_IS_OK(status)) {
289 d_fprintf(stderr, _("failed to parse arguments\n"));
293 tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
295 d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
296 status = NT_STATUS_NO_SUCH_FILE;
300 if (o->encoding != NULL) {
301 lp_set_cmdline("dos charset", o->encoding);
302 d_fprintf(stderr, _("do string conversion from %s to %s\n"),
303 lp_dos_charset(), lp_unix_charset());
304 do_string_conversion = true;
307 for (kbuf = tdb_firstkey_compat(tdb);
309 kbuf = tdb_nextkey_compat(tdb, kbuf))
311 dbuf = tdb_fetch_compat(tdb, kbuf);
316 if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
317 printing_tdb_migrate_form(tmp_ctx,
319 (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
322 SAFE_FREE(dbuf.dptr);
326 if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
327 printing_tdb_migrate_driver(tmp_ctx,
329 (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
332 do_string_conversion);
333 SAFE_FREE(dbuf.dptr);
337 if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
338 printing_tdb_migrate_printer(tmp_ctx,
340 (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
343 do_string_conversion);
344 SAFE_FREE(dbuf.dptr);
347 SAFE_FREE(dbuf.dptr);
350 for (kbuf = tdb_firstkey_compat(tdb);
352 kbuf = tdb_nextkey_compat(tdb, kbuf))
354 dbuf = tdb_fetch_compat(tdb, kbuf);
359 if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
360 printing_tdb_migrate_secdesc(tmp_ctx,
362 (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
365 SAFE_FREE(dbuf.dptr);
368 SAFE_FREE(dbuf.dptr);
372 status = NT_STATUS_OK;
375 lp_set_cmdline("dos charset", save_dos_charset);
376 talloc_free(tmp_ctx);
380 static int net_printing_migrate(struct net_context *c,
384 if (argc < 1 || c->display_usage) {
386 "net printing migrate [options] <file.tdb>\n"
389 _("Migrate tdb printing files to new storage"));
390 d_printf(_("Valid options:\n"));
391 d_printf(_(" encoding=<CP> Set the Code Page of the tdb file.\n"
392 " See iconv -l for the list of CP values\n"
393 " (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
397 return run_rpc_command(c,
401 printing_migrate_internal,
406 * 'net printing' entrypoint.
407 * @param argc Standard main() style argc.
408 * @param argv Standard main() style argv. Initial components are already
412 int net_printing(struct net_context *c, int argc, const char **argv)
416 struct functable func[] = {
421 N_("Dump printer databases"),
422 N_("net printing dump\n"
423 " Dump tdb printing file")
428 net_printing_migrate,
429 NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
430 N_("Migrate printer databases"),
431 N_("net printing migrate\n"
432 " Migrate tdb printing files to new storage")
435 { NULL, NULL, 0, NULL, NULL }
438 ret = net_run_function(c, argc, argv, "net printing", func);