summaryrefslogtreecommitdiffstats
path: root/source3/utils/net_printing.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:20:00 +0000
commit8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch)
tree4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source3/utils/net_printing.c
parentInitial commit. (diff)
downloadsamba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz
samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/utils/net_printing.c')
-rw-r--r--source3/utils/net_printing.c592
1 files changed, 592 insertions, 0 deletions
diff --git a/source3/utils/net_printing.c b/source3/utils/net_printing.c
new file mode 100644
index 0000000..04a3acc
--- /dev/null
+++ b/source3/utils/net_printing.c
@@ -0,0 +1,592 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Local printing tdb migration interface
+
+ Copyright (C) Guenther Deschner 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "utils/net.h"
+#include "rpc_client/rpc_client.h"
+#include "rpc_client/cli_pipe.h"
+#include "librpc/gen_ndr/ndr_ntprinting.h"
+#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "../libcli/security/security.h"
+#include "../librpc/gen_ndr/ndr_security.h"
+#include "../librpc/gen_ndr/ndr_winreg.h"
+#include "util_tdb.h"
+#include "printing/nt_printing_migrate.h"
+#include "lib/param/param.h"
+
+#define FORMS_PREFIX "FORMS/"
+#define FORMS_PREFIX_LEN 6
+#define DRIVERS_PREFIX "DRIVERS/"
+#define DRIVERS_PREFIX_LEN 8
+#define PRINTERS_PREFIX "PRINTERS/"
+#define PRINTERS_PREFIX_LEN 9
+#define SECDESC_PREFIX "SECDESC/"
+#define SECDESC_PREFIX_LEN 8
+
+#define ARG_ENCODING "encoding="
+
+struct printing_opts {
+ const char *encoding;
+ const char *tdb;
+};
+
+static NTSTATUS printing_parse_args(TALLOC_CTX *mem_ctx,
+ struct printing_opts **popts,
+ int argc, const char **argv)
+{
+ size_t c;
+ struct printing_opts *o;
+
+ if (argc == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ o = talloc_zero(mem_ctx, struct printing_opts);
+ if (o == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ for (c = 0; c < argc; c++) {
+ if (strnequal(argv[c], ARG_ENCODING, sizeof(ARG_ENCODING) - 1)) {
+ o->encoding = talloc_strdup(o,
+ argv[c] + sizeof(ARG_ENCODING) - 1);
+ if (o->encoding == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ o->tdb = talloc_strdup(o, argv[c]);
+ if (o->tdb == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ }
+
+ *popts = o;
+ return NT_STATUS_OK;
+}
+
+static void dump_form(TALLOC_CTX *mem_ctx,
+ const char *key_name,
+ unsigned char *data,
+ size_t length)
+{
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ char *s;
+ struct ntprinting_form r;
+
+ printf("found form: %s\n", key_name);
+
+ blob = data_blob_const(data, length);
+
+ ZERO_STRUCT(r);
+
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_ntprinting_form);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ d_fprintf(stderr, _("form pull failed: %s\n"),
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_form, &r);
+ if (s) {
+ printf("%s\n", s);
+ }
+}
+
+static void dump_driver(TALLOC_CTX *mem_ctx,
+ const char *key_name,
+ unsigned char *data,
+ size_t length,
+ bool do_string_conversion)
+{
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ char *s;
+ struct ntprinting_driver r;
+
+ printf("found driver: %s\n", key_name);
+
+ blob = data_blob_const(data, length);
+
+ ZERO_STRUCT(r);
+
+ if (do_string_conversion) {
+ r.string_flags = LIBNDR_FLAG_STR_ASCII;
+ }
+
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_ntprinting_driver);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ d_fprintf(stderr, _("driver pull failed: %s\n"),
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_driver, &r);
+ if (s) {
+ printf("%s\n", s);
+ }
+}
+
+static void dump_printer(TALLOC_CTX *mem_ctx,
+ const char *key_name,
+ unsigned char *data,
+ size_t length,
+ bool do_string_conversion)
+{
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ char *s;
+ struct ntprinting_printer r;
+
+ printf("found printer: %s\n", key_name);
+
+ blob = data_blob_const(data, length);
+
+ ZERO_STRUCT(r);
+
+ if (do_string_conversion) {
+ r.info.string_flags = LIBNDR_FLAG_STR_ASCII;
+ }
+
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_ntprinting_printer);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ d_fprintf(stderr, _("printer pull failed: %s\n"),
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ s = NDR_PRINT_STRUCT_STRING(mem_ctx, ntprinting_printer, &r);
+ if (s) {
+ printf("%s\n", s);
+ }
+}
+
+static void dump_sd(TALLOC_CTX *mem_ctx,
+ const char *key_name,
+ unsigned char *data,
+ size_t length)
+{
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ char *s;
+ struct sec_desc_buf r;
+
+ printf("found security descriptor: %s\n", key_name);
+
+ blob = data_blob_const(data, length);
+
+ ZERO_STRUCT(r);
+
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ d_fprintf(stderr, _("security descriptor pull failed: %s\n"),
+ ndr_errstr(ndr_err));
+ return;
+ }
+
+ s = NDR_PRINT_STRUCT_STRING(mem_ctx, sec_desc_buf, &r);
+ if (s) {
+ printf("%s\n", s);
+ }
+}
+
+
+static int net_printing_dump(struct net_context *c, int argc,
+ const char **argv)
+{
+ int ret = -1;
+ TALLOC_CTX *ctx = talloc_stackframe();
+ TDB_CONTEXT *tdb;
+ TDB_DATA kbuf, newkey, dbuf;
+ struct printing_opts *o;
+ const char *save_dos_charset = lp_dos_charset();
+ bool do_string_conversion = false;
+ NTSTATUS status;
+
+ if (argc < 1 || c->display_usage) {
+ d_printf( "%s\n"
+ "net printing dump [options] <file.tdb>\n"
+ " %s\n",
+ _("Usage:"),
+ _("Dump formatted printer information of the tdb."));
+ d_printf(_("Valid options:\n"));
+ d_printf(_(" encoding=<CP> Set the Code Page of the tdb file.\n"
+ " See iconv -l for the list of CP values\n"
+ " (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
+ goto done;
+ }
+
+ status = printing_parse_args(ctx, &o, argc, argv);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, _("failed to parse arguments\n"));
+ goto done;
+ }
+
+ tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
+ if (!tdb) {
+ d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
+ goto done;
+ }
+
+ if (o->encoding != NULL) {
+ lpcfg_set_cmdline(c->lp_ctx, "dos charset", o->encoding);
+ d_fprintf(stderr, _("do string conversion from %s to %s\n"),
+ lp_dos_charset(), lp_unix_charset());
+ do_string_conversion = true;
+ }
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf=newkey)
+ {
+ int cmp;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr) {
+ continue;
+ }
+
+ cmp = strncmp((const char *)kbuf.dptr,
+ FORMS_PREFIX,
+ FORMS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ dump_form(ctx, key_name, dbuf.dptr, dbuf.dsize);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ cmp = strncmp((const char *)kbuf.dptr,
+ DRIVERS_PREFIX,
+ DRIVERS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ dump_driver(ctx,
+ key_name,
+ dbuf.dptr,
+ dbuf.dsize,
+ do_string_conversion);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ cmp = strncmp((const char *)kbuf.dptr,
+ PRINTERS_PREFIX,
+ PRINTERS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ dump_printer(ctx,
+ key_name,
+ dbuf.dptr,
+ dbuf.dsize,
+ do_string_conversion);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ cmp = strncmp((const char *)kbuf.dptr,
+ SECDESC_PREFIX,
+ SECDESC_PREFIX_LEN);
+ if (cmp == 0) {
+ dump_sd(ctx, (const char *)kbuf.dptr+strlen(SECDESC_PREFIX), dbuf.dptr, dbuf.dsize);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ }
+
+ ret = 0;
+
+ done:
+ lpcfg_set_cmdline(c->lp_ctx, "dos charset", save_dos_charset);
+ talloc_free(ctx);
+ return ret;
+}
+
+static NTSTATUS printing_migrate_internal(struct net_context *c,
+ const struct dom_sid *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli,
+ struct rpc_pipe_client *winreg_pipe,
+ TALLOC_CTX *mem_ctx,
+ int argc,
+ const char **argv)
+{
+ struct printing_opts *o;
+ TALLOC_CTX *tmp_ctx;
+ TDB_CONTEXT *tdb;
+ TDB_DATA kbuf, newkey, dbuf;
+ NTSTATUS status;
+ const char *save_dos_charset = lp_dos_charset();
+ bool do_string_conversion = false;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ status = printing_parse_args(tmp_ctx, &o, argc, argv);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_fprintf(stderr, _("failed to parse arguments\n"));
+ goto done;
+ }
+
+ tdb = tdb_open_log(o->tdb, 0, TDB_DEFAULT, O_RDONLY, 0600);
+ if (tdb == NULL) {
+ d_fprintf(stderr, _("failed to open tdb file: %s\n"), o->tdb);
+ status = NT_STATUS_NO_SUCH_FILE;
+ goto done;
+ }
+
+ if (o->encoding != NULL) {
+ lpcfg_set_cmdline(c->lp_ctx, "dos charset", o->encoding);
+ d_fprintf(stderr, _("do string conversion from %s to %s\n"),
+ lp_dos_charset(), lp_unix_charset());
+ do_string_conversion = true;
+ }
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
+ {
+ int cmp;
+
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr) {
+ continue;
+ }
+
+ cmp = strncmp((const char *) kbuf.dptr,
+ FORMS_PREFIX,
+ FORMS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(tmp_ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ printing_tdb_migrate_form(tmp_ctx,
+ winreg_pipe,
+ key_name,
+ dbuf.dptr,
+ dbuf.dsize);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ cmp = strncmp((const char *) kbuf.dptr,
+ DRIVERS_PREFIX,
+ DRIVERS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(tmp_ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ printing_tdb_migrate_driver(tmp_ctx,
+ winreg_pipe,
+ key_name,
+ dbuf.dptr,
+ dbuf.dsize,
+ do_string_conversion);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+
+ cmp = strncmp((const char *) kbuf.dptr,
+ PRINTERS_PREFIX,
+ PRINTERS_PREFIX_LEN);
+ if (cmp == 0) {
+ char *key_name = NULL;
+ size_t converted_size = 0;
+ bool ok;
+
+ ok = pull_ascii_talloc(tmp_ctx,
+ &key_name,
+ (const char *) kbuf.dptr + strlen(PRINTERS_PREFIX),
+ &converted_size);
+ if (!ok) {
+ continue;
+ }
+
+ printing_tdb_migrate_printer(tmp_ctx,
+ winreg_pipe,
+ key_name,
+ dbuf.dptr,
+ dbuf.dsize,
+ do_string_conversion);
+ TALLOC_FREE(key_name);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+ SAFE_FREE(dbuf.dptr);
+ }
+
+ for (kbuf = tdb_firstkey(tdb);
+ kbuf.dptr;
+ newkey = tdb_nextkey(tdb, kbuf), free(kbuf.dptr), kbuf = newkey)
+ {
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr) {
+ continue;
+ }
+
+ if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
+ printing_tdb_migrate_secdesc(tmp_ctx,
+ winreg_pipe,
+ (const char *) kbuf.dptr + strlen(SECDESC_PREFIX),
+ dbuf.dptr,
+ dbuf.dsize);
+ SAFE_FREE(dbuf.dptr);
+ continue;
+ }
+ SAFE_FREE(dbuf.dptr);
+
+ }
+
+ status = NT_STATUS_OK;
+
+ done:
+ lpcfg_set_cmdline(c->lp_ctx, "dos charset", save_dos_charset);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+static int net_printing_migrate(struct net_context *c,
+ int argc,
+ const char **argv)
+{
+ if (argc < 1 || c->display_usage) {
+ d_printf( "%s\n"
+ "net printing migrate [options] <file.tdb>\n"
+ " %s\n",
+ _("Usage:"),
+ _("Migrate tdb printing files to new storage"));
+ d_printf(_("Valid options:\n"));
+ d_printf(_(" encoding=<CP> Set the Code Page of the tdb file.\n"
+ " See iconv -l for the list of CP values\n"
+ " (CP1252 is Western latin1, CP1251 is Cyrillic).\n"));
+ return 0;
+ }
+
+ return run_rpc_command(c,
+ NULL,
+ &ndr_table_winreg,
+ 0,
+ printing_migrate_internal,
+ argc,
+ argv);
+}
+/**
+ * 'net printing' entrypoint.
+ * @param argc Standard main() style argc.
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped.
+ **/
+
+int net_printing(struct net_context *c, int argc, const char **argv)
+{
+ int ret = -1;
+
+ struct functable func[] = {
+ {
+ "dump",
+ net_printing_dump,
+ NET_TRANSPORT_LOCAL,
+ N_("Dump printer databases"),
+ N_("net printing dump\n"
+ " Dump tdb printing file")
+ },
+
+ {
+ "migrate",
+ net_printing_migrate,
+ NET_TRANSPORT_LOCAL | NET_TRANSPORT_RPC,
+ N_("Migrate printer databases"),
+ N_("net printing migrate\n"
+ " Migrate tdb printing files to new storage")
+ },
+
+ { NULL, NULL, 0, NULL, NULL }
+ };
+
+ ret = net_run_function(c, argc, argv, "net printing", func);
+
+ return ret;
+}