1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2004,2009 Guenther Deschner (gd@samba.org)
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "system/filesys.h"
21 #include "utils/net.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
25 #include "rpc_client/init_spoolss.h"
26 #include "nt_printing.h"
27 #include "registry.h"
28 #include "../libcli/security/security.h"
29 #include "../libcli/registry/util_reg.h"
30 #include "libsmb/libsmb.h"
31 #include "../libcli/smb/smbXcli_base.h"
32 #include "auth/gensec/gensec.h"
33 #include "auth/credentials/credentials.h"
34 
35 /* support itanium as well */
36 static const struct print_architecture_table_node archi_table[]= {
37 
38 	{"Windows 4.0",          "WIN40",	0 },
39 	{"Windows NT x86",       "W32X86",	2 },
40 	{"Windows NT x86",       "W32X86",	3 },
41 	{"Windows NT R4000",     "W32MIPS",	2 },
42 	{"Windows NT Alpha_AXP", "W32ALPHA",	2 },
43 	{"Windows NT PowerPC",   "W32PPC",	2 },
44 	{"Windows IA64",         "IA64",	3 },
45 	{"Windows x64",          "x64",		3 },
46 	{NULL,                   "",		-1 }
47 };
48 
49 
50 /**
51  * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
52  * It is here for debugging purpose and should be removed later on.
53  **/
54 
55 /****************************************************************************
56  Printer info level 3 display function.
57 ****************************************************************************/
58 
display_print_driver3(struct spoolss_DriverInfo3 * r)59 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
60 {
61 	int i;
62 
63 	if (!r) {
64 		return;
65 	}
66 
67 	printf(_("Printer Driver Info 3:\n"));
68 	printf(_("\tVersion: [%x]\n"), r->version);
69 	printf(_("\tDriver Name: [%s]\n"), r->driver_name);
70 	printf(_("\tArchitecture: [%s]\n"), r->architecture);
71 	printf(_("\tDriver Path: [%s]\n"), r->driver_path);
72 	printf(_("\tDatafile: [%s]\n"), r->data_file);
73 	printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
74 	printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
75 
76 	for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
77 		printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
78 	}
79 
80 	printf("\n");
81 
82 	printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
83 	printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
84 }
85 
display_reg_value(const char * subkey,const char * name,struct registry_value * value)86 static void display_reg_value(const char *subkey, const char *name, struct registry_value *value)
87 {
88 	const char *text;
89 
90 	switch(value->type) {
91 	case REG_DWORD:
92 		if (value->data.length == sizeof(uint32_t)) {
93 			d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
94 				 name, IVAL(value->data.data,0));
95 		} else {
96 			d_printf(_("\t[%s:%s]: REG_DWORD: <invalid>\n"), subkey,
97 				 name);
98 		}
99 		break;
100 
101 	case REG_SZ:
102 		pull_reg_sz(talloc_tos(), &value->data, &text);
103 		if (!text) {
104 			break;
105 		}
106 		d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, name, text);
107 		break;
108 
109 	case REG_BINARY:
110 		d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
111 			   "displayed\n"),
112 			 subkey, name);
113 		break;
114 
115 	case REG_MULTI_SZ: {
116 		uint32_t i;
117 		const char **values;
118 
119 		if (!pull_reg_multi_sz(NULL, &value->data, &values)) {
120 			d_printf("pull_reg_multi_sz failed\n");
121 			break;
122 		}
123 
124 		printf("%s: REG_MULTI_SZ: \n", name);
125 		for (i=0; values[i] != NULL; i++) {
126 			d_printf("%s\n", values[i]);
127 		}
128 		TALLOC_FREE(values);
129 		break;
130 	}
131 
132 	default:
133 		d_printf(_("\t%s: unknown type %d\n"), name, value->type);
134 	}
135 
136 }
137 
138 /**
139  * Copies ACLs, DOS-attributes and timestamps from one
140  * file or directory from one connected share to another connected share
141  *
142  * @param c			A net_context structure
143  * @param mem_ctx		A talloc-context
144  * @param cli_share_src		A connected cli_state
145  * @param cli_share_dst		A connected cli_state
146  * @param src_file		The source file-name
147  * @param dst_file		The destination file-name
148  * @param copy_acls		Whether to copy acls
149  * @param copy_attrs		Whether to copy DOS attributes
150  * @param copy_timestamps	Whether to preserve timestamps
151  * @param is_file		Whether this file is a file or a dir
152  *
153  * @return Normal NTSTATUS return.
154  **/
155 
net_copy_fileattr(struct net_context * c,TALLOC_CTX * mem_ctx,struct cli_state * cli_share_src,struct cli_state * cli_share_dst,const char * src_name,const char * dst_name,bool copy_acls,bool copy_attrs,bool copy_timestamps,bool is_file)156 NTSTATUS net_copy_fileattr(struct net_context *c,
157 		  TALLOC_CTX *mem_ctx,
158 		  struct cli_state *cli_share_src,
159 		  struct cli_state *cli_share_dst,
160 		  const char *src_name, const char *dst_name,
161 		  bool copy_acls, bool copy_attrs,
162 		  bool copy_timestamps, bool is_file)
163 {
164 	NTSTATUS nt_status;
165 	uint16_t fnum_src = 0;
166 	uint16_t fnum_dst = 0;
167 	struct security_descriptor *sd = NULL;
168 	uint16_t attr;
169 	time_t f_atime, f_ctime, f_mtime;
170 
171 	if (!copy_timestamps && !copy_acls && !copy_attrs)
172 		return NT_STATUS_OK;
173 
174 	/* open file/dir on the originating server */
175 
176 	DEBUGADD(3,("opening %s %s on originating server\n",
177 		is_file?"file":"dir", src_name));
178 
179 	nt_status = cli_ntcreate(cli_share_src, src_name, 0,
180 				 READ_CONTROL_ACCESS, 0,
181 				 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
182 				 0x0, 0x0, &fnum_src, NULL);
183 	if (!NT_STATUS_IS_OK(nt_status)) {
184 		DEBUGADD(0,("cannot open %s %s on originating server %s\n",
185 			is_file?"file":"dir", src_name, nt_errstr(nt_status)));
186 		goto out;
187 	}
188 
189 	if (copy_acls) {
190 		/* get the security descriptor */
191 		nt_status = cli_query_secdesc(cli_share_src, fnum_src,
192 					      mem_ctx, &sd);
193 		if (!NT_STATUS_IS_OK(nt_status)) {
194 			DEBUG(0,("failed to get security descriptor: %s\n",
195 				 nt_errstr(nt_status)));
196 			goto out;
197 		}
198 
199 		if (c->opt_verbose && DEBUGLEVEL >= 3)
200 			display_sec_desc(sd);
201 	}
202 
203 	if (copy_attrs || copy_timestamps) {
204 
205 		/* get file attributes */
206 		nt_status = cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
207 		                      &f_ctime, &f_atime, &f_mtime);
208 		if (!NT_STATUS_IS_OK(nt_status)) {
209 			DEBUG(0,("failed to get file-attrs: %s\n",
210 				nt_errstr(nt_status)));
211 			goto out;
212 		}
213 	}
214 
215 	/* open the file/dir on the destination server */
216 	nt_status = cli_ntcreate(cli_share_dst, dst_name, 0,
217 				 WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
218 				 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
219 				 0x0, 0x0, &fnum_dst, NULL);
220 	if (!NT_STATUS_IS_OK(nt_status)) {
221 		DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
222 			is_file?"file":"dir", dst_name, nt_errstr(nt_status)));
223 		goto out;
224 	}
225 
226 	if (copy_timestamps) {
227 		/* set timestamps */
228 		nt_status = cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime);
229 		if (!NT_STATUS_IS_OK(nt_status)) {
230 			DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
231 				nt_errstr(nt_status)));
232 			goto out;
233 		}
234 	}
235 
236 	if (copy_acls) {
237 		/* set acls */
238 		nt_status = cli_set_secdesc(cli_share_dst, fnum_dst, sd);
239 		if (!NT_STATUS_IS_OK(nt_status)) {
240 			DEBUG(0, ("could not set secdesc on %s: %s\n",
241 				  dst_name, nt_errstr(nt_status)));
242 			goto out;
243 		}
244 	}
245 
246 	if (copy_attrs) {
247 		/* set attrs */
248 		nt_status = cli_setatr(cli_share_dst, dst_name, attr, 0);
249 		if (!NT_STATUS_IS_OK(nt_status)) {
250 			DEBUG(0,("failed to set file-attrs: %s\n",
251 				nt_errstr(nt_status)));
252 			goto out;
253 		}
254 	}
255 
256 
257 	/* closing files */
258 	nt_status = cli_close(cli_share_src, fnum_src);
259 	if (!NT_STATUS_IS_OK(nt_status)) {
260 		d_fprintf(stderr,
261 			_("could not close %s on originating server: %s\n"),
262 			is_file?"file":"dir", nt_errstr(nt_status));
263 		goto out;
264 	}
265 
266 	nt_status = cli_close(cli_share_dst, fnum_dst);
267 	if (!NT_STATUS_IS_OK(nt_status)) {
268 		d_fprintf(stderr,
269 			_("could not close %s on destination server: %s\n"),
270 			is_file?"file":"dir", nt_errstr(nt_status));
271 		goto out;
272 	}
273 
274 
275 	nt_status = NT_STATUS_OK;
276 
277 out:
278 
279 	/* cleaning up */
280 	if (fnum_src)
281 		cli_close(cli_share_src, fnum_src);
282 
283 	if (fnum_dst)
284 		cli_close(cli_share_dst, fnum_dst);
285 
286 	return nt_status;
287 }
288 
289 /**
290  * Copy a file or directory from a connected share to another connected share
291  *
292  * @param c			A net_context structure
293  * @param mem_ctx		A talloc-context
294  * @param cli_share_src		A connected cli_state
295  * @param cli_share_dst		A connected cli_state
296  * @param src_file		The source file-name
297  * @param dst_file		The destination file-name
298  * @param copy_acls		Whether to copy acls
299  * @param copy_attrs		Whether to copy DOS attributes
300  * @param copy_timestamps	Whether to preserve timestamps
301  * @param is_file		Whether this file is a file or a dir
302  *
303  * @return Normal NTSTATUS return.
304  **/
305 
net_copy_file(struct net_context * c,TALLOC_CTX * mem_ctx,struct cli_state * cli_share_src,struct cli_state * cli_share_dst,const char * src_name,const char * dst_name,bool copy_acls,bool copy_attrs,bool copy_timestamps,bool is_file)306 NTSTATUS net_copy_file(struct net_context *c,
307 		       TALLOC_CTX *mem_ctx,
308 		       struct cli_state *cli_share_src,
309 		       struct cli_state *cli_share_dst,
310 		       const char *src_name, const char *dst_name,
311 		       bool copy_acls, bool copy_attrs,
312 		       bool copy_timestamps, bool is_file)
313 {
314 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
315 	uint16_t fnum_src = 0;
316 	uint16_t fnum_dst = 0;
317 	static int io_bufsize = 64512;
318 	int read_size = io_bufsize;
319 	char *data = NULL;
320 	off_t nread = 0;
321 
322 
323 	if (!src_name || !dst_name)
324 		goto out;
325 
326 	if (cli_share_src == NULL || cli_share_dst == NULL)
327 		goto out;
328 
329 	/* open on the originating server */
330 	DEBUGADD(3,("opening %s %s on originating server\n",
331 		is_file ? "file":"dir", src_name));
332 	if (is_file)
333 		nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
334 	else
335 		nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
336 				FILE_SHARE_READ|FILE_SHARE_WRITE,
337 				FILE_OPEN, 0x0, 0x0, &fnum_src, NULL);
338 
339 	if (!NT_STATUS_IS_OK(nt_status)) {
340 		DEBUGADD(0,("cannot open %s %s on originating server %s\n",
341 			is_file ? "file":"dir",
342 			src_name, nt_errstr(nt_status)));
343 		goto out;
344 	}
345 
346 
347 	if (is_file) {
348 
349 		/* open file on the destination server */
350 		DEBUGADD(3,("opening file %s on destination server\n", dst_name));
351 		nt_status = cli_open(cli_share_dst, dst_name,
352 				O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
353 
354 		if (!NT_STATUS_IS_OK(nt_status)) {
355 			DEBUGADD(1,("cannot create file %s on destination server: %s\n",
356 				dst_name, nt_errstr(nt_status)));
357 			goto out;
358 		}
359 
360 		/* allocate memory */
361 		if (!(data = (char *)SMB_MALLOC(read_size))) {
362 			d_fprintf(stderr, _("malloc fail for size %d\n"),
363 				  read_size);
364 			nt_status = NT_STATUS_NO_MEMORY;
365 			goto out;
366 		}
367 
368 	}
369 
370 
371 	if (c->opt_verbose) {
372 
373 		d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
374 			   "%s ACLs and %s DOS Attributes %s\n"),
375 			smbXcli_conn_remote_name(cli_share_src->conn),
376 			cli_share_src->share, src_name,
377 			smbXcli_conn_remote_name(cli_share_dst->conn),
378 			cli_share_dst->share, dst_name,
379 			copy_acls ?  _("with") : _("without"),
380 			copy_attrs ? _("with") : _("without"),
381 			copy_timestamps ? _("(preserving timestamps)") : "" );
382 	}
383 
384 
385 	while (is_file) {
386 
387 		/* copying file */
388 		size_t n;
389 
390 		nt_status = cli_read(cli_share_src, fnum_src, data, nread,
391 				     read_size, &n);
392 		if (!NT_STATUS_IS_OK(nt_status)) {
393 			d_fprintf(stderr,
394 				  _("Error reading file [\\\\%s\\%s%s]: %s\n"),
395 				  smbXcli_conn_remote_name(cli_share_src->conn),
396 				  cli_share_src->share,
397 				  src_name, nt_errstr(nt_status));
398 			goto out;
399 		}
400 
401 		if (n == 0)
402 			break;
403 
404 		nt_status = cli_writeall(cli_share_dst, fnum_dst, 0,
405 					 (uint8_t *)data, nread, n, NULL);
406 
407 		if (!NT_STATUS_IS_OK(nt_status)) {
408 			d_fprintf(stderr,
409 				  _("Error writing file: [\\\\%s\\%s%s]: %s\n"),
410 				  smbXcli_conn_remote_name(cli_share_dst->conn),
411 				  cli_share_dst->share,
412 				  dst_name, nt_errstr(nt_status));
413 			goto out;
414 		}
415 
416 		nread += n;
417 	}
418 
419 
420 	if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
421 
422 		/* creating dir */
423 		DEBUGADD(3,("creating dir %s on the destination server\n",
424 			dst_name));
425 
426 		nt_status = cli_mkdir(cli_share_dst, dst_name);
427 		if (!NT_STATUS_IS_OK(nt_status)) {
428 			DEBUG(0,("cannot create directory %s: %s\n",
429 				dst_name, nt_errstr(nt_status)));
430 			nt_status = NT_STATUS_NO_SUCH_FILE;
431 		}
432 
433 
434 		nt_status = cli_chkpath(cli_share_dst, dst_name);
435 		if (!NT_STATUS_IS_OK(nt_status)) {
436 			d_fprintf(stderr,
437 				_("cannot check for directory %s: %s\n"),
438 				dst_name, nt_errstr(nt_status));
439 			goto out;
440 		}
441 	}
442 
443 
444 	/* closing files */
445 	nt_status = cli_close(cli_share_src, fnum_src);
446 	if (!NT_STATUS_IS_OK(nt_status)) {
447 		d_fprintf(stderr,
448 			_("could not close file on originating server: %s\n"),
449 			nt_errstr(nt_status));
450 		goto out;
451 	}
452 
453 	if (is_file) {
454 		nt_status = cli_close(cli_share_dst, fnum_dst);
455 		if (!NT_STATUS_IS_OK(nt_status)) {
456 			d_fprintf(stderr,
457 			_("could not close file on destination server: %s\n"),
458 			nt_errstr(nt_status));
459 			goto out;
460 		}
461 	}
462 
463 	/* possibly we have to copy some file-attributes / acls / sd */
464 	nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
465 				      src_name, dst_name, copy_acls,
466 				      copy_attrs, copy_timestamps, is_file);
467 	if (!NT_STATUS_IS_OK(nt_status))
468 		goto out;
469 
470 
471 	nt_status = NT_STATUS_OK;
472 
473 out:
474 
475 	/* cleaning up */
476 	if (fnum_src)
477 		cli_close(cli_share_src, fnum_src);
478 
479 	if (fnum_dst)
480 		cli_close(cli_share_dst, fnum_dst);
481 
482 	SAFE_FREE(data);
483 
484 	return nt_status;
485 }
486 
487 /**
488  * Copy a driverfile from on connected share to another connected share
489  * This silently assumes that a driver-file is picked up from
490  *
491  *	\\src_server\print$\{arch}\{version}\file
492  *
493  * and copied to
494  *
495  * 	\\dst_server\print$\{arch}\file
496  *
497  * to be added via setdriver-calls later.
498  * @param c			A net_context structure
499  * @param mem_ctx		A talloc-context
500  * @param cli_share_src		A cli_state connected to source print$-share
501  * @param cli_share_dst		A cli_state connected to destination print$-share
502  * @param file			The file-name to be copied
503  * @param short_archi		The name of the driver-architecture (short form)
504  *
505  * @return Normal NTSTATUS return.
506  **/
507 
net_copy_driverfile(struct net_context * c,TALLOC_CTX * mem_ctx,struct cli_state * cli_share_src,struct cli_state * cli_share_dst,const char * file,const char * short_archi)508 static NTSTATUS net_copy_driverfile(struct net_context *c,
509 				    TALLOC_CTX *mem_ctx,
510 				    struct cli_state *cli_share_src,
511 				    struct cli_state *cli_share_dst,
512 				    const char *file, const char *short_archi) {
513 
514 	const char *p;
515 	char *src_name;
516 	char *dst_name;
517 	char *version = NULL;
518 	char *filename = NULL;
519 	char *tok;
520 
521 	if (!file) {
522 		return NT_STATUS_OK;
523 	}
524 
525 	/* scroll through the file until we have the part
526 	   beyond archi_table.short_archi */
527 	p = file;
528 	while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
529 		if (strequal(tok, short_archi)) {
530 			next_token_talloc(mem_ctx, &p, &version, "\\");
531 			next_token_talloc(mem_ctx, &p, &filename, "\\");
532 		}
533 	}
534 
535 	if (version == NULL || filename == NULL) {
536 		return NT_STATUS_UNSUCCESSFUL;
537 	}
538 
539 	/* build source file name */
540 	src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
541 				   short_archi, version, filename);
542 	if (src_name == NULL) {
543 		return NT_STATUS_NO_MEMORY;
544 	}
545 
546 	/* create destination file name */
547 	dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
548 	if (dst_name == NULL) {
549 		return NT_STATUS_NO_MEMORY;
550 	}
551 
552 
553 	/* finally copy the file */
554 	return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
555 			     src_name, dst_name, false, false, false, true);
556 }
557 
558 /**
559  * Check for existing Architecture directory on a given server
560  *
561  * @param cli_share		A cli_state connected to a print$-share
562  * @param short_archi		The Architecture for the print-driver
563  *
564  * @return Normal NTSTATUS return.
565  **/
566 
check_arch_dir(struct cli_state * cli_share,const char * short_archi)567 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
568 {
569 
570 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
571 	char *dir;
572 
573 	if (asprintf(&dir, "\\%s", short_archi) < 0) {
574 		return NT_STATUS_NO_MEMORY;
575 	}
576 
577 	DEBUG(10,("creating print-driver dir for architecture: %s\n",
578 		short_archi));
579 
580 	nt_status = cli_mkdir(cli_share, dir);
581 	if (!NT_STATUS_IS_OK(nt_status)) {
582                 DEBUG(1,("cannot create directory %s: %s\n",
583                          dir, nt_errstr(nt_status)));
584         }
585 
586 	nt_status = cli_chkpath(cli_share, dir);
587 	if (!NT_STATUS_IS_OK(nt_status)) {
588 		d_fprintf(stderr, _("cannot check %s: %s\n"),
589 			dir, nt_errstr(nt_status));
590 		goto out;
591 	}
592 
593 	nt_status = NT_STATUS_OK;
594 
595 out:
596 	SAFE_FREE(dir);
597 	return nt_status;
598 }
599 
600 /**
601  * Copy a print-driver (level 3) from one connected print$-share to another
602  * connected print$-share
603  *
604  * @param c			A net_context structure
605  * @param mem_ctx		A talloc-context
606  * @param cli_share_src		A cli_state connected to a print$-share
607  * @param cli_share_dst		A cli_state connected to a print$-share
608  * @param short_archi		The Architecture for the print-driver
609  * @param i1			The DRIVER_INFO_3-struct
610  *
611  * @return Normal NTSTATUS return.
612  **/
613 
copy_print_driver_3(struct net_context * c,TALLOC_CTX * mem_ctx,struct cli_state * cli_share_src,struct cli_state * cli_share_dst,const char * short_archi,struct spoolss_DriverInfo3 * r)614 static NTSTATUS copy_print_driver_3(struct net_context *c,
615 		    TALLOC_CTX *mem_ctx,
616 		    struct cli_state *cli_share_src,
617 		    struct cli_state *cli_share_dst,
618 		    const char *short_archi,
619 		    struct spoolss_DriverInfo3 *r)
620 {
621 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
622 	int i;
623 
624 	if (r == NULL) {
625 		return nt_status;
626 	}
627 
628 	if (c->opt_verbose)
629 		d_printf(_("copying driver: [%s], for architecture: [%s], "
630 			   "version: [%d]\n"),
631 			  r->driver_name, short_archi, r->version);
632 
633 	nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
634 		r->driver_path, short_archi);
635 	if (!NT_STATUS_IS_OK(nt_status))
636 		return nt_status;
637 
638 	nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
639 		r->data_file, short_archi);
640 	if (!NT_STATUS_IS_OK(nt_status))
641 		return nt_status;
642 
643 	nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
644 		r->config_file, short_archi);
645 	if (!NT_STATUS_IS_OK(nt_status))
646 		return nt_status;
647 
648 	nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
649 		r->help_file, short_archi);
650 	if (!NT_STATUS_IS_OK(nt_status))
651 		return nt_status;
652 
653 	for (i=0; r->dependent_files[i] != NULL; i++) {
654 
655 		nt_status = net_copy_driverfile(c, mem_ctx,
656 				cli_share_src, cli_share_dst,
657 				r->dependent_files[i], short_archi);
658 		if (!NT_STATUS_IS_OK(nt_status)) {
659 			return nt_status;
660 		}
661 	}
662 
663 	return NT_STATUS_OK;
664 }
665 
666 /**
667  * net_spoolss-functions
668  * =====================
669  *
670  * the net_spoolss-functions aim to simplify spoolss-client-functions
671  * required during the migration-process wrt buffer-sizes, returned
672  * error-codes, etc.
673  *
674  * this greatly reduces the complexitiy of the migrate-functions.
675  *
676  **/
677 
net_spoolss_enum_printers(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,char * name,uint32_t flags,uint32_t level,uint32_t * num_printers,union spoolss_PrinterInfo ** info)678 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
679 					TALLOC_CTX *mem_ctx,
680 					char *name,
681 					uint32_t flags,
682 					uint32_t level,
683 					uint32_t *num_printers,
684 					union spoolss_PrinterInfo **info)
685 {
686 	WERROR result;
687 
688 	/* enum printers */
689 
690 	result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
691 					     flags,
692 					     name,
693 					     level,
694 					     0,
695 					     num_printers,
696 					     info);
697 	if (!W_ERROR_IS_OK(result)) {
698 		printf(_("cannot enum printers: %s\n"), win_errstr(result));
699 		return false;
700 	}
701 
702 	return true;
703 }
704 
net_spoolss_open_printer_ex(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,const char * printername,uint32_t access_required,struct policy_handle * hnd)705 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
706 					TALLOC_CTX *mem_ctx,
707 					const char *printername,
708 					uint32_t access_required,
709 					struct policy_handle *hnd)
710 {
711 	struct cli_credentials *creds = gensec_get_credentials(pipe_hnd->auth->auth_ctx);
712 	const char *username = cli_credentials_get_username(creds);
713 	WERROR result;
714 	fstring printername2;
715 
716 	fstrcpy(printername2, pipe_hnd->srv_name_slash);
717 	fstrcat(printername2, "\\");
718 	fstrcat(printername2, printername);
719 
720 	DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
721 		pipe_hnd->srv_name_slash, username, printername2, access_required));
722 
723 	/* open printer */
724 	result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
725 					       printername2,
726 					       access_required,
727 					       hnd);
728 
729 	/* be more verbose */
730 	if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
731 		d_fprintf(stderr,
732 			_("no access to printer [%s] on [%s] for user [%s] "
733 			  "granted\n"),
734 			printername2, pipe_hnd->srv_name_slash, username);
735 		return false;
736 	}
737 
738 	if (!W_ERROR_IS_OK(result)) {
739 		d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
740 			printername2, pipe_hnd->srv_name_slash, win_errstr(result));
741 		return false;
742 	}
743 
744 	DEBUG(2,("got printer handle for printer: %s, server: %s\n",
745 		printername2, pipe_hnd->srv_name_slash));
746 
747 	return true;
748 }
749 
net_spoolss_getprinter(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,uint32_t level,union spoolss_PrinterInfo * info)750 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
751 				TALLOC_CTX *mem_ctx,
752 				struct policy_handle *hnd,
753 				uint32_t level,
754 				union spoolss_PrinterInfo *info)
755 {
756 	WERROR result;
757 
758 	/* getprinter call */
759 	result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
760 					   hnd,
761 					   level,
762 					   0, /* offered */
763 					   info);
764 	if (!W_ERROR_IS_OK(result)) {
765 		printf(_("cannot get printer-info: %s\n"), win_errstr(result));
766 		return false;
767 	}
768 
769 	return true;
770 }
771 
net_spoolss_setprinter(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,uint32_t level,union spoolss_PrinterInfo * info)772 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
773 				TALLOC_CTX *mem_ctx,
774 				struct policy_handle *hnd,
775 				uint32_t level,
776 				union spoolss_PrinterInfo *info)
777 {
778 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
779 	WERROR result;
780 	NTSTATUS status;
781 	struct spoolss_SetPrinterInfoCtr info_ctr;
782 	struct spoolss_SetPrinterInfo2 info2;
783 	struct spoolss_DevmodeContainer devmode_ctr;
784 	struct sec_desc_buf secdesc_ctr;
785 
786 	ZERO_STRUCT(devmode_ctr);
787 	ZERO_STRUCT(secdesc_ctr);
788 
789 	/* setprinter call */
790 
791 	info_ctr.level = level;
792 	switch (level) {
793 	case 0:
794 		info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)
795 			(void *)&info->info0;
796 		break;
797 	case 1:
798 		info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)
799 			(void *)&info->info1;
800 		break;
801 	case 2:
802 		spoolss_printerinfo2_to_setprinterinfo2(&info->info2, &info2);
803 		info_ctr.info.info2 = &info2;
804 		break;
805 	case 3:
806 		info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)
807 			(void *)&info->info3;
808 		break;
809 	case 4:
810 		info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)
811 			(void *)&info->info4;
812 		break;
813 	case 5:
814 		info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)
815 			(void *)&info->info5;
816 		break;
817 	case 6:
818 		info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)
819 			(void *)&info->info6;
820 		break;
821 	case 7:
822 		info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
823 			(void *)&info->info7;
824 		break;
825 #if 0 /* FIXME GD */
826 	case 8:
827 		info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)
828 			(void *)&info->info8;
829 		break;
830 	case 9:
831 		info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)
832 			(void *)&info->info9;
833 		break;
834 #endif
835 	default:
836 		break; /* FIXME */
837 	}
838 
839 	status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
840 					   hnd,
841 					   &info_ctr,
842 					   &devmode_ctr,
843 					   &secdesc_ctr,
844 					   0, /* command */
845 					   &result);
846 	if (!NT_STATUS_IS_OK(status)) {
847 		printf(_("cannot set printer-info: %s\n"), nt_errstr(status));
848 		return false;
849 	}
850 	if (!W_ERROR_IS_OK(result)) {
851 		printf(_("cannot set printer-info: %s\n"), win_errstr(result));
852 		return false;
853 	}
854 
855 	return true;
856 }
857 
858 
net_spoolss_setprinterdata(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,const char * value_name,enum winreg_Type type,uint8_t * data,uint32_t offered)859 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
860 				       TALLOC_CTX *mem_ctx,
861 				       struct policy_handle *hnd,
862 				       const char *value_name,
863 				       enum winreg_Type type,
864 				       uint8_t *data,
865 				       uint32_t offered)
866 {
867 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
868 	WERROR result;
869 	NTSTATUS status;
870 
871 	/* setprinterdata call */
872 	status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
873 					       hnd,
874 					       value_name,
875 					       type,
876 					       data,
877 					       offered,
878 					       &result);
879 	if (!NT_STATUS_IS_OK(status)) {
880 		printf (_("unable to set printerdata: %s\n"),
881 			nt_errstr(status));
882 		return false;
883 	}
884 	if (!W_ERROR_IS_OK(result)) {
885 		printf (_("unable to set printerdata: %s\n"),
886 			win_errstr(result));
887 		return false;
888 	}
889 
890 	return true;
891 }
892 
893 
net_spoolss_enumprinterkey(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,const char * keyname,const char *** keylist)894 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
895 					TALLOC_CTX *mem_ctx,
896 					struct policy_handle *hnd,
897 					const char *keyname,
898 					const char ***keylist)
899 {
900 	WERROR result;
901 
902 	/* enumprinterkey call */
903 	result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
904 
905 	if (!W_ERROR_IS_OK(result)) {
906 		printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
907 		return false;
908 	}
909 
910 	return true;
911 }
912 
net_spoolss_enumprinterdataex(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,uint32_t offered,struct policy_handle * hnd,const char * keyname,uint32_t * count,struct spoolss_PrinterEnumValues ** info)913 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
914 					TALLOC_CTX *mem_ctx,
915 					uint32_t offered,
916 					struct policy_handle *hnd,
917 					const char *keyname,
918 					uint32_t *count,
919 					struct spoolss_PrinterEnumValues **info)
920 {
921 	WERROR result;
922 
923 	/* enumprinterdataex call */
924 	result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
925 						  hnd,
926 						  keyname,
927 						  0, /* offered */
928 						  count,
929 						  info);
930 
931 	if (!W_ERROR_IS_OK(result)) {
932 		printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
933 		return false;
934 	}
935 
936 	return true;
937 }
938 
939 
net_spoolss_setprinterdataex(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,const char * keyname,const char * name,struct registry_value * value)940 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
941 					 TALLOC_CTX *mem_ctx,
942 					 struct policy_handle *hnd,
943 					 const char *keyname,
944 					 const char *name,
945 					 struct registry_value *value)
946 {
947 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
948 	WERROR result;
949 	NTSTATUS status;
950 
951 	/* setprinterdataex call */
952 	status = dcerpc_spoolss_SetPrinterDataEx(b, mem_ctx,
953 						 hnd,
954 						 keyname,
955 						 name,
956 						 value->type,
957 						 value->data.data,
958 						 value->data.length,
959 						 &result);
960 	if (!NT_STATUS_IS_OK(status)) {
961 		printf(_("could not set printerdataex: %s\n"),
962 		       nt_errstr(status));
963 		return false;
964 	}
965 	if (!W_ERROR_IS_OK(result)) {
966 		printf(_("could not set printerdataex: %s\n"),
967 		       win_errstr(result));
968 		return false;
969 	}
970 
971 	return true;
972 }
973 
net_spoolss_enumforms(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,int level,uint32_t * num_forms,union spoolss_FormInfo ** forms)974 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
975 				TALLOC_CTX *mem_ctx,
976 				struct policy_handle *hnd,
977 				int level,
978 				uint32_t *num_forms,
979 				union spoolss_FormInfo **forms)
980 {
981 	WERROR result;
982 
983 	/* enumforms call */
984 	result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
985 					  hnd,
986 					  level,
987 					  0,
988 					  num_forms,
989 					  forms);
990 	if (!W_ERROR_IS_OK(result)) {
991 		printf(_("could not enum forms: %s\n"), win_errstr(result));
992 		return false;
993 	}
994 
995 	return true;
996 }
997 
net_spoolss_enumprinterdrivers(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,uint32_t level,const char * env,uint32_t * count,union spoolss_DriverInfo ** info)998 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
999 					TALLOC_CTX *mem_ctx,
1000 					uint32_t level, const char *env,
1001 					uint32_t *count,
1002 					union spoolss_DriverInfo **info)
1003 {
1004 	WERROR result;
1005 
1006 	/* enumprinterdrivers call */
1007 	result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
1008 						   pipe_hnd->srv_name_slash,
1009 						   env,
1010 						   level,
1011 						   0,
1012 						   count,
1013 						   info);
1014 	if (!W_ERROR_IS_OK(result)) {
1015 		if (W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1016 			printf(_("cannot enum drivers for environment %s: %s\n"), env,
1017 				win_errstr(result));
1018 			return false;
1019 		} else {
1020 			printf(_("Server does not support environment [%s]\n"),
1021 				env);
1022 		}
1023 	}
1024 
1025 	return true;
1026 }
1027 
net_spoolss_getprinterdriver(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,struct policy_handle * hnd,uint32_t level,const char * env,int version,union spoolss_DriverInfo * info)1028 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
1029 			     TALLOC_CTX *mem_ctx,
1030 			     struct policy_handle *hnd, uint32_t level,
1031 			     const char *env, int version,
1032 			     union spoolss_DriverInfo *info)
1033 {
1034 	WERROR result;
1035 	uint32_t server_major_version;
1036 	uint32_t server_minor_version;
1037 
1038 	/* getprinterdriver call */
1039 	result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
1040 						  hnd,
1041 						  env,
1042 						  level,
1043 						  0,
1044 						  version,
1045 						  2,
1046 						  info,
1047 						  &server_major_version,
1048 						  &server_minor_version);
1049 	if (!W_ERROR_IS_OK(result)) {
1050 		DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1051 			env, win_errstr(result)));
1052 		if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1053 		    W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1054 			printf(_("cannot get driver: %s\n"),
1055 			       win_errstr(result));
1056 		}
1057 		return false;
1058 	}
1059 
1060 	return true;
1061 }
1062 
1063 
net_spoolss_addprinterdriver(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,uint32_t level,union spoolss_DriverInfo * info)1064 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1065 			     TALLOC_CTX *mem_ctx, uint32_t level,
1066 			     union spoolss_DriverInfo *info)
1067 {
1068 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1069 	WERROR result;
1070 	NTSTATUS status;
1071 	struct spoolss_AddDriverInfoCtr info_ctr;
1072 
1073 	info_ctr.level = level;
1074 
1075 	switch (level) {
1076 	case 2:
1077 		info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1078 			(void *)&info->info2;
1079 		break;
1080 	case 3:
1081 		info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1082 			(void *)&info->info3;
1083 		break;
1084 	default:
1085 		printf(_("unsupported info level: %d\n"), level);
1086 		return false;
1087 	}
1088 
1089 	/* addprinterdriver call */
1090 	status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1091 						 pipe_hnd->srv_name_slash,
1092 						 &info_ctr,
1093 						 &result);
1094 	if (!NT_STATUS_IS_OK(status)) {
1095 		printf(_("cannot add driver: %s\n"), nt_errstr(status));
1096 		return false;
1097 	}
1098 	/* be more verbose */
1099 	if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1100 		printf(_("You are not allowed to add drivers\n"));
1101 		return false;
1102 	}
1103 	if (!W_ERROR_IS_OK(result)) {
1104 		printf(_("cannot add driver: %s\n"), win_errstr(result));
1105 		return false;
1106 	}
1107 
1108 	return true;
1109 }
1110 
1111 /**
1112  * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1113  * for a single printer or for all printers depending on argc/argv
1114  **/
1115 
get_printer_info(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int level,int argc,const char ** argv,uint32_t * num_printers,union spoolss_PrinterInfo ** info_p)1116 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1117 			TALLOC_CTX *mem_ctx,
1118 			int level,
1119 			int argc,
1120 			const char **argv,
1121 			uint32_t *num_printers,
1122 			union spoolss_PrinterInfo **info_p)
1123 {
1124 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1125 	struct policy_handle hnd;
1126 	WERROR werr;
1127 
1128 	/* no arguments given, enumerate all printers */
1129 	if (argc == 0) {
1130 
1131 		if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1132 				PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1133 				level, num_printers, info_p))
1134 			return false;
1135 
1136 		goto out;
1137 	}
1138 
1139 	/* argument given, get a single printer by name */
1140 	if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1141 					 MAXIMUM_ALLOWED_ACCESS,
1142 					 &hnd))
1143 		return false;
1144 
1145 	*info_p = talloc_zero(mem_ctx, union spoolss_PrinterInfo);
1146 	if (*info_p == NULL) {
1147 		return false;
1148 	}
1149 
1150 	if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1151 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1152 		return false;
1153 	}
1154 
1155 	dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1156 
1157 	*num_printers = 1;
1158 
1159 out:
1160 	DEBUG(3,("got %d printers\n", *num_printers));
1161 
1162 	return true;
1163 
1164 }
1165 
1166 /**
1167  * List print-queues (including local printers that are not shared)
1168  *
1169  * All parameters are provided by the run_rpc_command function, except for
1170  * argc, argv which are passed through.
1171  *
1172  * @param c	A net_context structure
1173  * @param domain_sid The domain sid aquired from the remote server
1174  * @param cli A cli_state connected to the server.
1175  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1176  * @param argc  Standard main() style argc
1177  * @param argv  Standard main() style argv.  Initial components are already
1178  *              stripped
1179  *
1180  * @return Normal NTSTATUS return.
1181  **/
1182 
rpc_printer_list_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1183 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1184 					const struct dom_sid *domain_sid,
1185 					const char *domain_name,
1186 					struct cli_state *cli,
1187 					struct rpc_pipe_client *pipe_hnd,
1188 					TALLOC_CTX *mem_ctx,
1189 					int argc,
1190 					const char **argv)
1191 {
1192 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1193 	uint32_t i, num_printers;
1194 	uint32_t level = 2;
1195 	const char *printername, *sharename;
1196 	union spoolss_PrinterInfo *info;
1197 
1198 	printf("listing printers\n");
1199 
1200 	if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1201 		return nt_status;
1202 
1203 	for (i = 0; i < num_printers; i++) {
1204 
1205 		/* do some initialization */
1206 		printername = info[i].info2.printername;
1207 		sharename = info[i].info2.sharename;
1208 
1209 		if (printername && sharename) {
1210 			d_printf(_("printer %d: %s, shared as: %s\n"),
1211 				i+1, printername, sharename);
1212 		}
1213 	}
1214 
1215 	return NT_STATUS_OK;
1216 }
1217 
1218 /**
1219  * List printer-drivers from a server
1220  *
1221  * All parameters are provided by the run_rpc_command function, except for
1222  * argc, argv which are passed through.
1223  *
1224  * @param c	A net_context structure
1225  * @param domain_sid The domain sid aquired from the remote server
1226  * @param cli A cli_state connected to the server.
1227  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1228  * @param argc  Standard main() style argc
1229  * @param argv  Standard main() style argv.  Initial components are already
1230  *              stripped
1231  *
1232  * @return Normal NTSTATUS return.
1233  **/
1234 
rpc_printer_driver_list_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1235 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1236 						const struct dom_sid *domain_sid,
1237 						const char *domain_name,
1238 						struct cli_state *cli,
1239 						struct rpc_pipe_client *pipe_hnd,
1240 						TALLOC_CTX *mem_ctx,
1241 						int argc,
1242 						const char **argv)
1243 {
1244 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1245 	uint32_t i;
1246 	uint32_t level = 3;
1247 	union spoolss_DriverInfo *info;
1248 	int d;
1249 
1250 	printf(_("listing printer-drivers\n"));
1251 
1252         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1253 
1254 		uint32_t num_drivers;
1255 
1256 		/* enum remote drivers */
1257 		if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1258 				archi_table[i].long_archi,
1259 				&num_drivers, &info)) {
1260 			nt_status = NT_STATUS_UNSUCCESSFUL;
1261 			goto done;
1262 		}
1263 
1264 		if (num_drivers == 0) {
1265 			d_printf(_("no drivers found on server for "
1266 				   "architecture: [%s].\n"),
1267 				archi_table[i].long_archi);
1268 			continue;
1269 		}
1270 
1271 		d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1272 			num_drivers, archi_table[i].long_archi);
1273 
1274 
1275 		/* do something for all drivers for architecture */
1276 		for (d = 0; d < num_drivers; d++) {
1277 			display_print_driver3(&info[d].info3);
1278 		}
1279 	}
1280 
1281 	nt_status = NT_STATUS_OK;
1282 
1283 done:
1284 	return nt_status;
1285 
1286 }
1287 
1288 /**
1289  * Publish print-queues with args-wrapper
1290  *
1291  * @param cli A cli_state connected to the server.
1292  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1293  * @param argc  Standard main() style argc
1294  * @param argv  Standard main() style argv.  Initial components are already
1295  *              stripped
1296  * @param action
1297  *
1298  * @return Normal NTSTATUS return.
1299  **/
1300 
rpc_printer_publish_internals_args(struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv,uint32_t action)1301 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1302 					TALLOC_CTX *mem_ctx,
1303 					int argc,
1304 					const char **argv,
1305 					uint32_t action)
1306 {
1307 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1308 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1309 	uint32_t i, num_printers;
1310 	uint32_t level = 7;
1311 	const char *printername, *sharename;
1312 	union spoolss_PrinterInfo *info_enum;
1313 	union spoolss_PrinterInfo info;
1314 	struct spoolss_SetPrinterInfoCtr info_ctr;
1315 	struct spoolss_DevmodeContainer devmode_ctr;
1316 	struct sec_desc_buf secdesc_ctr;
1317 	struct policy_handle hnd = { 0, };
1318 	WERROR result;
1319 	const char *action_str;
1320 
1321 	if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1322 		return nt_status;
1323 
1324 	for (i = 0; i < num_printers; i++) {
1325 
1326 		/* do some initialization */
1327 		printername = info_enum[i].info2.printername;
1328 		sharename = info_enum[i].info2.sharename;
1329 		if (!printername || !sharename) {
1330 			goto done;
1331 		}
1332 
1333 		/* open printer handle */
1334 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1335 			PRINTER_ALL_ACCESS, &hnd))
1336 			goto done;
1337 
1338 		/* check for existing dst printer */
1339 		if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1340 			goto done;
1341 
1342 		/* check action and set string */
1343 		switch (action) {
1344 		case DSPRINT_PUBLISH:
1345 			action_str = N_("published");
1346 			break;
1347 		case DSPRINT_UPDATE:
1348 			action_str = N_("updated");
1349 			break;
1350 		case DSPRINT_UNPUBLISH:
1351 			action_str = N_("unpublished");
1352 			break;
1353 		default:
1354 			action_str = N_("unknown action");
1355 			printf(_("unknown action: %d\n"), action);
1356 			break;
1357 		}
1358 
1359 		info.info7.action = action;
1360 		info_ctr.level = 7;
1361 		info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1362 			(void *)&info.info7;
1363 
1364 		ZERO_STRUCT(devmode_ctr);
1365 		ZERO_STRUCT(secdesc_ctr);
1366 
1367 		nt_status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1368 						      &hnd,
1369 						      &info_ctr,
1370 						      &devmode_ctr,
1371 						      &secdesc_ctr,
1372 						      0, /* command */
1373 						      &result);
1374 		if (!NT_STATUS_IS_OK(nt_status)) {
1375 			printf(_("cannot set printer-info: %s\n"),
1376 			       nt_errstr(nt_status));
1377 			goto done;
1378 		}
1379 		if (!W_ERROR_IS_OK(result) && !W_ERROR_EQUAL(result, WERR_IO_PENDING)) {
1380 			if ((action == DSPRINT_UPDATE) && W_ERROR_EQUAL(result, W_ERROR(0x80070002))) {
1381 				printf(_("printer not published yet\n"));
1382 			} else {
1383 				printf(_("cannot set printer-info: %s\n"),
1384 				       win_errstr(result));
1385 			}
1386 			nt_status = werror_to_ntstatus(result);
1387 			goto done;
1388 		}
1389 
1390 		printf(_("successfully %s printer %s in Active Directory\n"),
1391 		       action_str, sharename);
1392 	}
1393 
1394 	nt_status = NT_STATUS_OK;
1395 
1396 done:
1397 	if (is_valid_policy_hnd(&hnd)) {
1398 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
1399 	}
1400 
1401 	return nt_status;
1402 }
1403 
rpc_printer_publish_publish_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1404 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1405 						const struct dom_sid *domain_sid,
1406 						const char *domain_name,
1407 						struct cli_state *cli,
1408 						struct rpc_pipe_client *pipe_hnd,
1409 						TALLOC_CTX *mem_ctx,
1410 						int argc,
1411 						const char **argv)
1412 {
1413 	return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1414 }
1415 
rpc_printer_publish_unpublish_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1416 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1417 						const struct dom_sid *domain_sid,
1418 						const char *domain_name,
1419 						struct cli_state *cli,
1420 						struct rpc_pipe_client *pipe_hnd,
1421 						TALLOC_CTX *mem_ctx,
1422 						int argc,
1423 						const char **argv)
1424 {
1425 	return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1426 }
1427 
rpc_printer_publish_update_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1428 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1429 						const struct dom_sid *domain_sid,
1430 						const char *domain_name,
1431 						struct cli_state *cli,
1432 						struct rpc_pipe_client *pipe_hnd,
1433 						TALLOC_CTX *mem_ctx,
1434 						int argc,
1435 						const char **argv)
1436 {
1437 	return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1438 }
1439 
1440 /**
1441  * List print-queues w.r.t. their publishing state
1442  *
1443  * All parameters are provided by the run_rpc_command function, except for
1444  * argc, argv which are passed through.
1445  *
1446  * @param c	A net_context structure
1447  * @param domain_sid The domain sid aquired from the remote server
1448  * @param cli A cli_state connected to the server.
1449  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1450  * @param argc  Standard main() style argc
1451  * @param argv  Standard main() style argv.  Initial components are already
1452  *              stripped
1453  *
1454  * @return Normal NTSTATUS return.
1455  **/
1456 
rpc_printer_publish_list_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1457 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1458 						const struct dom_sid *domain_sid,
1459 						const char *domain_name,
1460 						struct cli_state *cli,
1461 						struct rpc_pipe_client *pipe_hnd,
1462 						TALLOC_CTX *mem_ctx,
1463 						int argc,
1464 						const char **argv)
1465 {
1466 	struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1467 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1468 	uint32_t i, num_printers;
1469 	uint32_t level = 7;
1470 	const char *printername, *sharename;
1471 	union spoolss_PrinterInfo *info_enum;
1472 	union spoolss_PrinterInfo info;
1473 	struct policy_handle hnd = { 0, };
1474 	int state;
1475 	WERROR werr;
1476 
1477 	if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1478 		return nt_status;
1479 
1480 	for (i = 0; i < num_printers; i++) {
1481 
1482 		/* do some initialization */
1483 		printername = info_enum[i].info2.printername;
1484 		sharename = info_enum[i].info2.sharename;
1485 
1486 		if (!printername || !sharename) {
1487 			goto done;
1488 		}
1489 
1490 		/* open printer handle */
1491 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1492 			PRINTER_ALL_ACCESS, &hnd))
1493 			goto done;
1494 
1495 		/* check for existing dst printer */
1496 		if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1497 			goto done;
1498 
1499 		if (!info.info7.guid) {
1500 			goto done;
1501 		}
1502 		state = info.info7.action;
1503 		switch (state) {
1504 			case DSPRINT_PUBLISH:
1505 				printf(_("printer [%s] is published"),
1506 				       sharename);
1507 				if (c->opt_verbose)
1508 					printf(_(", guid: %s"),info.info7.guid);
1509 				printf("\n");
1510 				break;
1511 			case DSPRINT_UNPUBLISH:
1512 				printf(_("printer [%s] is unpublished\n"),
1513 				       sharename);
1514 				break;
1515 			case DSPRINT_UPDATE:
1516 				printf(_("printer [%s] is currently updating\n"),
1517 				       sharename);
1518 				break;
1519 			default:
1520 				printf(_("unknown state: %d\n"), state);
1521 				break;
1522 		}
1523 	}
1524 
1525 	nt_status = NT_STATUS_OK;
1526 
1527 done:
1528 	if (is_valid_policy_hnd(&hnd)) {
1529 		dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1530 	}
1531 
1532 	return nt_status;
1533 }
1534 
1535 /**
1536  * Migrate Printer-ACLs from a source server to the destination server
1537  *
1538  * All parameters are provided by the run_rpc_command function, except for
1539  * argc, argv which are passed through.
1540  *
1541  * @param c	A net_context structure
1542  * @param domain_sid The domain sid aquired from the remote server
1543  * @param cli A cli_state connected to the server.
1544  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1545  * @param argc  Standard main() style argc
1546  * @param argv  Standard main() style argv.  Initial components are already
1547  *              stripped
1548  *
1549  * @return Normal NTSTATUS return.
1550  **/
1551 
rpc_printer_migrate_security_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1552 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1553 						const struct dom_sid *domain_sid,
1554 						const char *domain_name,
1555 						struct cli_state *cli,
1556 						struct rpc_pipe_client *pipe_hnd,
1557 						TALLOC_CTX *mem_ctx,
1558 						int argc,
1559 						const char **argv)
1560 {
1561 	struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1562 	/* TODO: what now, info2 or info3 ?
1563 	   convince jerry that we should add clientside setacls level 3 at least
1564 	*/
1565 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1566 	uint32_t i = 0;
1567 	uint32_t num_printers;
1568 	uint32_t level = 2;
1569 	const char *printername, *sharename;
1570 	struct rpc_pipe_client *pipe_hnd_dst = NULL;
1571 	struct dcerpc_binding_handle *b_dst = NULL;
1572 	struct policy_handle hnd_src = { 0, };
1573 	struct policy_handle hnd_dst = { 0, };
1574 	union spoolss_PrinterInfo *info_enum;
1575 	struct cli_state *cli_dst = NULL;
1576 	union spoolss_PrinterInfo info_src, info_dst;
1577 	WERROR werr;
1578 
1579 	DEBUG(3,("copying printer ACLs\n"));
1580 
1581 	/* connect destination PI_SPOOLSS */
1582 	nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1583 				     &ndr_table_spoolss);
1584 	if (!NT_STATUS_IS_OK(nt_status)) {
1585 		return nt_status;
1586 	}
1587 	b_dst = pipe_hnd_dst->binding_handle;
1588 
1589 	/* enum source printers */
1590 	if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1591 		nt_status = NT_STATUS_UNSUCCESSFUL;
1592 		goto done;
1593 	}
1594 
1595 	if (!num_printers) {
1596 		printf (_("no printers found on server.\n"));
1597 		nt_status = NT_STATUS_OK;
1598 		goto done;
1599 	}
1600 
1601 	/* do something for all printers */
1602 	for (i = 0; i < num_printers; i++) {
1603 
1604 		/* do some initialization */
1605 		printername = info_enum[i].info2.printername;
1606 		sharename = info_enum[i].info2.sharename;
1607 
1608 		if (!printername || !sharename) {
1609 			nt_status = NT_STATUS_UNSUCCESSFUL;
1610 			goto done;
1611 		}
1612 
1613 		/* we can reset NT_STATUS here because we do not
1614 		   get any real NT_STATUS-codes anymore from now on */
1615 		nt_status = NT_STATUS_UNSUCCESSFUL;
1616 
1617 		d_printf(_("migrating printer ACLs for:     [%s] / [%s]\n"),
1618 			printername, sharename);
1619 
1620 		/* according to msdn you have specify these access-rights
1621 		   to see the security descriptor
1622 			- READ_CONTROL (DACL)
1623 			- ACCESS_SYSTEM_SECURITY (SACL)
1624 		*/
1625 
1626 		/* open src printer handle */
1627 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1628 			MAXIMUM_ALLOWED_ACCESS, &hnd_src))
1629 			goto done;
1630 
1631 		/* open dst printer handle */
1632 		if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1633 			PRINTER_ALL_ACCESS, &hnd_dst))
1634 			goto done;
1635 
1636 		/* check for existing dst printer */
1637 		if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1638 			goto done;
1639 
1640 		/* check for existing src printer */
1641 		if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1642 			goto done;
1643 
1644 		/* Copy Security Descriptor */
1645 
1646 		/* copy secdesc (info level 2) */
1647 		info_dst.info2.devmode = NULL;
1648 		if (info_src.info3.secdesc == NULL) {
1649 			info_dst.info2.secdesc = NULL;
1650 		} else {
1651 			info_dst.info2.secdesc
1652 				= security_descriptor_copy(mem_ctx,
1653 							info_src.info3.secdesc);
1654 			if (info_dst.info2.secdesc == NULL) {
1655 				nt_status = NT_STATUS_NO_MEMORY;
1656 				goto done;
1657 			}
1658 		}
1659 
1660 		if (c->opt_verbose)
1661 			display_sec_desc(info_dst.info2.secdesc);
1662 
1663 		if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1664 			goto done;
1665 
1666 		DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1667 
1668 
1669 		/* close printer handles here */
1670 		if (is_valid_policy_hnd(&hnd_src)) {
1671 			dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1672 		}
1673 
1674 		if (is_valid_policy_hnd(&hnd_dst)) {
1675 			dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1676 		}
1677 
1678 	}
1679 
1680 	nt_status = NT_STATUS_OK;
1681 
1682 done:
1683 
1684 	if (is_valid_policy_hnd(&hnd_src)) {
1685 		dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1686 	}
1687 
1688 	if (is_valid_policy_hnd(&hnd_dst)) {
1689 		dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1690 	}
1691 
1692 	if (cli_dst) {
1693 		cli_shutdown(cli_dst);
1694 	}
1695 	return nt_status;
1696 }
1697 
1698 /**
1699  * Migrate printer-forms from a src server to the dst server
1700  *
1701  * All parameters are provided by the run_rpc_command function, except for
1702  * argc, argv which are passed through.
1703  *
1704  * @param c	A net_context structure
1705  * @param domain_sid The domain sid aquired from the remote server
1706  * @param cli A cli_state connected to the server.
1707  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1708  * @param argc  Standard main() style argc
1709  * @param argv  Standard main() style argv.  Initial components are already
1710  *              stripped
1711  *
1712  * @return Normal NTSTATUS return.
1713  **/
1714 
rpc_printer_migrate_forms_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1715 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1716 						const struct dom_sid *domain_sid,
1717 						const char *domain_name,
1718 						struct cli_state *cli,
1719 						struct rpc_pipe_client *pipe_hnd,
1720 						TALLOC_CTX *mem_ctx,
1721 						int argc,
1722 						const char **argv)
1723 {
1724 	struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1725 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1726 	WERROR result;
1727 	uint32_t i, f;
1728 	uint32_t num_printers;
1729 	uint32_t level = 1;
1730 	const char *printername, *sharename;
1731 	struct rpc_pipe_client *pipe_hnd_dst = NULL;
1732 	struct dcerpc_binding_handle *b_dst = NULL;
1733 	struct policy_handle hnd_src = { 0, };
1734 	struct policy_handle hnd_dst = { 0, };
1735 	union spoolss_PrinterInfo *info_enum;
1736 	union spoolss_PrinterInfo info_dst;
1737 	uint32_t num_forms;
1738 	union spoolss_FormInfo *forms;
1739 	struct cli_state *cli_dst = NULL;
1740 
1741 	DEBUG(3,("copying forms\n"));
1742 
1743 	/* connect destination PI_SPOOLSS */
1744 	nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1745 				     &ndr_table_spoolss);
1746 	if (!NT_STATUS_IS_OK(nt_status)) {
1747 		return nt_status;
1748 	}
1749 	b_dst = pipe_hnd_dst->binding_handle;
1750 
1751 	/* enum src printers */
1752 	if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1753 		nt_status = NT_STATUS_UNSUCCESSFUL;
1754 		goto done;
1755 	}
1756 
1757 	if (!num_printers) {
1758 		printf (_("no printers found on server.\n"));
1759 		nt_status = NT_STATUS_OK;
1760 		goto done;
1761 	}
1762 
1763 	/* do something for all printers */
1764 	for (i = 0; i < num_printers; i++) {
1765 
1766 		/* do some initialization */
1767 		printername = info_enum[i].info2.printername;
1768 		sharename = info_enum[i].info2.sharename;
1769 
1770 		if (!printername || !sharename) {
1771 			nt_status = NT_STATUS_UNSUCCESSFUL;
1772 			goto done;
1773 		}
1774 		/* we can reset NT_STATUS here because we do not
1775 		   get any real NT_STATUS-codes anymore from now on */
1776 		nt_status = NT_STATUS_UNSUCCESSFUL;
1777 
1778 		d_printf(_("migrating printer forms for:    [%s] / [%s]\n"),
1779 			printername, sharename);
1780 
1781 
1782 		/* open src printer handle */
1783 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1784 			MAXIMUM_ALLOWED_ACCESS, &hnd_src))
1785 			goto done;
1786 
1787 		/* open dst printer handle */
1788 		if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1789 			PRINTER_ALL_ACCESS, &hnd_dst))
1790 			goto done;
1791 
1792 		/* check for existing dst printer */
1793 		if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1794 			goto done;
1795 
1796 		/* finally migrate forms */
1797 		if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1798 			goto done;
1799 
1800 		DEBUG(1,("got %d forms for printer\n", num_forms));
1801 
1802 
1803 		for (f = 0; f < num_forms; f++) {
1804 
1805 			struct spoolss_AddFormInfoCtr info_ctr;
1806 			NTSTATUS status;
1807 
1808 			/* only migrate FORM_PRINTER types, according to jerry
1809 			   FORM_BUILTIN-types are hard-coded in samba */
1810 			if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1811 				continue;
1812 
1813 			if (c->opt_verbose)
1814 				d_printf(_("\tmigrating form # %d [%s] of type "
1815 					   "[%d]\n"),
1816 					f, forms[f].info1.form_name,
1817 					forms[f].info1.flags);
1818 			info_ctr.level = 1;
1819 			info_ctr.info.info1 = (struct spoolss_AddFormInfo1 *)
1820 				(void *)&forms[f].info1;
1821 
1822 			/* FIXME: there might be something wrong with samba's
1823 			   builtin-forms */
1824 			status = dcerpc_spoolss_AddForm(b_dst, mem_ctx,
1825 							&hnd_dst,
1826 							&info_ctr,
1827 							&result);
1828 			if (!NT_STATUS_IS_OK(status)) {
1829 				d_printf(_("\tdcerpc_spoolss_AddForm form %d: [%s] - %s\n"),
1830 					f, forms[f].info1.form_name, nt_errstr(status));
1831 				continue;
1832 			}
1833 			if (!W_ERROR_IS_OK(result)) {
1834 				d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1835 					f, forms[f].info1.form_name);
1836 				continue;
1837 			}
1838 
1839 			DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1840 				forms[f].info1.form_name));
1841 		}
1842 
1843 
1844 		/* close printer handles here */
1845 		if (is_valid_policy_hnd(&hnd_src)) {
1846 			dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1847 		}
1848 
1849 		if (is_valid_policy_hnd(&hnd_dst)) {
1850 			dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1851 		}
1852 	}
1853 
1854 	nt_status = NT_STATUS_OK;
1855 
1856 done:
1857 
1858 	if (is_valid_policy_hnd(&hnd_src)) {
1859 		dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1860 	}
1861 
1862 	if (is_valid_policy_hnd(&hnd_dst)) {
1863 		dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1864 	}
1865 
1866 	if (cli_dst) {
1867 		cli_shutdown(cli_dst);
1868 	}
1869 	return nt_status;
1870 }
1871 
1872 /**
1873  * Migrate printer-drivers from a src server to the dst server
1874  *
1875  * All parameters are provided by the run_rpc_command function, except for
1876  * argc, argv which are passed through.
1877  *
1878  * @param c	A net_context structure
1879  * @param domain_sid The domain sid aquired from the remote server
1880  * @param cli A cli_state connected to the server.
1881  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1882  * @param argc  Standard main() style argc
1883  * @param argv  Standard main() style argv.  Initial components are already
1884  *              stripped
1885  *
1886  * @return Normal NTSTATUS return.
1887  **/
1888 
rpc_printer_migrate_drivers_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)1889 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1890 						const struct dom_sid *domain_sid,
1891 						const char *domain_name,
1892 						struct cli_state *cli,
1893 						struct rpc_pipe_client *pipe_hnd,
1894 						TALLOC_CTX *mem_ctx,
1895 						int argc,
1896 						const char **argv)
1897 {
1898 	struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1899 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1900 	uint32_t i, p;
1901 	uint32_t num_printers;
1902 	uint32_t level = 3;
1903 	const char *printername, *sharename;
1904 	bool got_src_driver_share = false;
1905 	bool got_dst_driver_share = false;
1906 	struct rpc_pipe_client *pipe_hnd_dst = NULL;
1907 	struct dcerpc_binding_handle *b_dst = NULL;
1908 	struct policy_handle hnd_src = { 0, };
1909 	struct policy_handle hnd_dst = { 0, };
1910 	union spoolss_DriverInfo drv_info_src;
1911 	union spoolss_PrinterInfo *info_enum;
1912 	union spoolss_PrinterInfo info_dst;
1913 	struct cli_state *cli_dst = NULL;
1914 	struct cli_state *cli_share_src = NULL;
1915 	struct cli_state *cli_share_dst = NULL;
1916 	const char *drivername = NULL;
1917 	WERROR werr;
1918 
1919 	DEBUG(3,("copying printer-drivers\n"));
1920 
1921 	nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1922 				     &ndr_table_spoolss);
1923 	if (!NT_STATUS_IS_OK(nt_status)) {
1924 		return nt_status;
1925 	}
1926 	b_dst = pipe_hnd_dst->binding_handle;
1927 
1928 	/* open print$-share on the src server */
1929 	nt_status = connect_to_service(c, &cli_share_src,
1930 				       smbXcli_conn_remote_sockaddr(cli->conn),
1931 				       smbXcli_conn_remote_name(cli->conn),
1932 				       "print$", "A:");
1933 	if (!NT_STATUS_IS_OK(nt_status))
1934 		goto done;
1935 
1936 	got_src_driver_share = true;
1937 
1938 
1939 	/* open print$-share on the dst server */
1940 	nt_status = connect_to_service(c, &cli_share_dst,
1941 				       smbXcli_conn_remote_sockaddr(cli_dst->conn),
1942 				       smbXcli_conn_remote_name(cli_dst->conn),
1943 				       "print$", "A:");
1944 	if (!NT_STATUS_IS_OK(nt_status))
1945 		return nt_status;
1946 
1947 	got_dst_driver_share = true;
1948 
1949 
1950 	/* enum src printers */
1951 	if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1952 		nt_status = NT_STATUS_UNSUCCESSFUL;
1953 		goto done;
1954 	}
1955 
1956 	if (num_printers == 0) {
1957 		printf (_("no printers found on server.\n"));
1958 		nt_status = NT_STATUS_OK;
1959 		goto done;
1960 	}
1961 
1962 
1963 	/* do something for all printers */
1964 	for (p = 0; p < num_printers; p++) {
1965 
1966 		/* do some initialization */
1967 		printername = info_enum[p].info2.printername;
1968 		sharename = info_enum[p].info2.sharename;
1969 
1970 		if (!printername || !sharename) {
1971 			nt_status = NT_STATUS_UNSUCCESSFUL;
1972 			goto done;
1973 		}
1974 
1975 		/* we can reset NT_STATUS here because we do not
1976 		   get any real NT_STATUS-codes anymore from now on */
1977 		nt_status = NT_STATUS_UNSUCCESSFUL;
1978 
1979 		d_printf(_("migrating printer driver for:   [%s] / [%s]\n"),
1980 			printername, sharename);
1981 
1982 		/* open dst printer handle */
1983 		if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1984 			PRINTER_ALL_ACCESS, &hnd_dst))
1985 			goto done;
1986 
1987 		/* check for existing dst printer */
1988 		if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1989 			goto done;
1990 
1991 
1992 		/* open src printer handle */
1993 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1994 						 MAXIMUM_ALLOWED_ACCESS,
1995 						 &hnd_src))
1996 			goto done;
1997 
1998 		/* in a first step call getdriver for each shared printer (per arch)
1999 		   to get a list of all files that have to be copied */
2000 
2001 	        for (i=0; archi_table[i].long_archi!=NULL; i++) {
2002 
2003 			/* getdriver src */
2004 			if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
2005 					level, archi_table[i].long_archi,
2006 					archi_table[i].version, &drv_info_src))
2007 				continue;
2008 
2009 			drivername = drv_info_src.info3.driver_name;
2010 
2011 			if (c->opt_verbose)
2012 				display_print_driver3(&drv_info_src.info3);
2013 
2014 			/* check arch dir */
2015 			nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
2016 			if (!NT_STATUS_IS_OK(nt_status))
2017 				goto done;
2018 
2019 
2020 			/* copy driver-files */
2021 			nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
2022 							archi_table[i].short_archi,
2023 							&drv_info_src.info3);
2024 			if (!NT_STATUS_IS_OK(nt_status))
2025 				goto done;
2026 
2027 
2028 			/* adddriver dst */
2029 			if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
2030 				nt_status = NT_STATUS_UNSUCCESSFUL;
2031 				goto done;
2032 			}
2033 
2034 			DEBUGADD(1,("Successfully added driver [%s] for printer [%s]\n",
2035 				drivername, printername));
2036 
2037 		}
2038 
2039 		if (!drivername || strlen(drivername) == 0) {
2040 			DEBUGADD(1,("Did not get driver for printer %s\n",
2041 				    printername));
2042 			goto done;
2043 		}
2044 
2045 		/* setdriver dst */
2046 		info_dst.info2.drivername = drivername;
2047 
2048 		if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
2049 			nt_status = NT_STATUS_UNSUCCESSFUL;
2050 			goto done;
2051 		}
2052 
2053 		DEBUGADD(1,("Successfully set driver %s for printer %s\n",
2054 			drivername, printername));
2055 
2056 		/* close dst */
2057 		if (is_valid_policy_hnd(&hnd_dst)) {
2058 			dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2059 		}
2060 
2061 		/* close src */
2062 		if (is_valid_policy_hnd(&hnd_src)) {
2063 			dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2064 		}
2065 	}
2066 
2067 	nt_status = NT_STATUS_OK;
2068 
2069 done:
2070 
2071 	if (is_valid_policy_hnd(&hnd_dst)) {
2072 		dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2073 	}
2074 
2075 	/* close src */
2076 	if (is_valid_policy_hnd(&hnd_src)) {
2077 		dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2078 	}
2079 
2080 	if (cli_dst) {
2081 		cli_shutdown(cli_dst);
2082 	}
2083 
2084 	if (got_src_driver_share)
2085 		cli_shutdown(cli_share_src);
2086 
2087 	if (got_dst_driver_share)
2088 		cli_shutdown(cli_share_dst);
2089 
2090 	return nt_status;
2091 
2092 }
2093 
2094 /**
2095  * Migrate printer-queues from a src to the dst server
2096  * (requires a working "addprinter command" to be installed for the local smbd)
2097  *
2098  * All parameters are provided by the run_rpc_command function, except for
2099  * argc, argv which are passed through.
2100  *
2101  * @param c	A net_context structure
2102  * @param domain_sid The domain sid aquired from the remote server
2103  * @param cli A cli_state connected to the server.
2104  * @param mem_ctx Talloc context, destoyed on compleation of the function.
2105  * @param argc  Standard main() style argc
2106  * @param argv  Standard main() style argv.  Initial components are already
2107  *              stripped
2108  *
2109  * @return Normal NTSTATUS return.
2110  **/
2111 
rpc_printer_migrate_printers_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2112 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2113 						const struct dom_sid *domain_sid,
2114 						const char *domain_name,
2115 						struct cli_state *cli,
2116 						struct rpc_pipe_client *pipe_hnd,
2117 						TALLOC_CTX *mem_ctx,
2118 						int argc,
2119 						const char **argv)
2120 {
2121 	struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2122 	WERROR result;
2123 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2124 	uint32_t i = 0, num_printers;
2125 	uint32_t level = 2;
2126 	union spoolss_PrinterInfo info_dst, info_src;
2127 	union spoolss_PrinterInfo *info_enum;
2128 	struct cli_state *cli_dst = NULL;
2129 	struct policy_handle hnd_src = { 0, };
2130 	struct policy_handle hnd_dst = { 0, };
2131 	const char *printername, *sharename;
2132 	struct rpc_pipe_client *pipe_hnd_dst = NULL;
2133 	struct dcerpc_binding_handle *b_dst = NULL;
2134 	struct spoolss_SetPrinterInfoCtr info_ctr;
2135 
2136 	DEBUG(3,("copying printers\n"));
2137 
2138 	/* connect destination PI_SPOOLSS */
2139 	nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2140 				     &ndr_table_spoolss);
2141 	if (!NT_STATUS_IS_OK(nt_status)) {
2142 		return nt_status;
2143 	}
2144 	b_dst = pipe_hnd_dst->binding_handle;
2145 
2146 	/* enum printers */
2147 	if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2148 		nt_status = NT_STATUS_UNSUCCESSFUL;
2149 		goto done;
2150 	}
2151 
2152 	if (!num_printers) {
2153 		printf (_("no printers found on server.\n"));
2154 		nt_status = NT_STATUS_OK;
2155 		goto done;
2156 	}
2157 
2158 	/* do something for all printers */
2159 	for (i = 0; i < num_printers; i++) {
2160 
2161 		struct spoolss_SetPrinterInfo2 info2;
2162 
2163 		/* do some initialization */
2164 		printername = info_enum[i].info2.printername;
2165 		sharename = info_enum[i].info2.sharename;
2166 
2167 		if (!printername || !sharename) {
2168 			nt_status = NT_STATUS_UNSUCCESSFUL;
2169 			goto done;
2170 		}
2171 		/* we can reset NT_STATUS here because we do not
2172 		   get any real NT_STATUS-codes anymore from now on */
2173 		nt_status = NT_STATUS_UNSUCCESSFUL;
2174 
2175 		d_printf(_("migrating printer queue for:    [%s] / [%s]\n"),
2176 			printername, sharename);
2177 
2178 		/* open dst printer handle */
2179 		if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2180 			PRINTER_ALL_ACCESS, &hnd_dst)) {
2181 
2182 			DEBUG(1,("could not open printer: %s\n", sharename));
2183 		}
2184 
2185 		/* check for existing dst printer */
2186 		if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2187 			printf (_("could not get printer, creating printer.\n"));
2188 		} else {
2189 			DEBUG(1,("printer already exists: %s\n", sharename));
2190 			/* close printer handle here - dst only, not got src yet. */
2191 			if (is_valid_policy_hnd(&hnd_dst)) {
2192 				dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2193 			}
2194 			continue;
2195 		}
2196 
2197 		/* now get again src printer ctr via getprinter,
2198 		   we first need a handle for that */
2199 
2200 		/* open src printer handle */
2201 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2202 			MAXIMUM_ALLOWED_ACCESS, &hnd_src))
2203 			goto done;
2204 
2205 		/* getprinter on the src server */
2206 		if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2207 			goto done;
2208 
2209 		/* copy each src printer to a dst printer 1:1,
2210 		   maybe some values have to be changed though */
2211 		d_printf(_("creating printer: %s\n"), printername);
2212 
2213 		info_ctr.level = level;
2214 		spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2215 		info_ctr.info.info2 = &info2;
2216 
2217 		result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2218 						     mem_ctx,
2219 						     &info_ctr);
2220 
2221 		if (W_ERROR_IS_OK(result))
2222 			d_printf (_("printer [%s] successfully added.\n"),
2223 				  printername);
2224 		else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2225 			d_fprintf (stderr, _("printer [%s] already exists.\n"),
2226 				   printername);
2227 		else {
2228 			d_fprintf (stderr, _("could not create printer [%s]\n"),
2229 				   printername);
2230 			goto done;
2231 		}
2232 
2233 		/* close printer handles here */
2234 		if (is_valid_policy_hnd(&hnd_src)) {
2235 			dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2236 		}
2237 
2238 		if (is_valid_policy_hnd(&hnd_dst)) {
2239 			dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2240 		}
2241 	}
2242 
2243 	nt_status = NT_STATUS_OK;
2244 
2245 done:
2246 	if (is_valid_policy_hnd(&hnd_src)) {
2247 		dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2248 	}
2249 
2250 	if (is_valid_policy_hnd(&hnd_dst)) {
2251 		dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2252 	}
2253 
2254 	if (cli_dst) {
2255 		cli_shutdown(cli_dst);
2256 	}
2257 	return nt_status;
2258 }
2259 
2260 /**
2261  * Migrate Printer-Settings from a src server to the dst server
2262  * (for this to work, printers and drivers already have to be migrated earlier)
2263  *
2264  * All parameters are provided by the run_rpc_command function, except for
2265  * argc, argv which are passed through.
2266  *
2267  * @param c	A net_context structure
2268  * @param domain_sid The domain sid aquired from the remote server
2269  * @param cli A cli_state connected to the server.
2270  * @param mem_ctx Talloc context, destoyed on compleation of the function.
2271  * @param argc  Standard main() style argc
2272  * @param argv  Standard main() style argv.  Initial components are already
2273  *              stripped
2274  *
2275  * @return Normal NTSTATUS return.
2276  **/
2277 
rpc_printer_migrate_settings_internals(struct net_context * c,const struct dom_sid * domain_sid,const char * domain_name,struct cli_state * cli,struct rpc_pipe_client * pipe_hnd,TALLOC_CTX * mem_ctx,int argc,const char ** argv)2278 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2279 						const struct dom_sid *domain_sid,
2280 						const char *domain_name,
2281 						struct cli_state *cli,
2282 						struct rpc_pipe_client *pipe_hnd,
2283 						TALLOC_CTX *mem_ctx,
2284 						int argc,
2285 						const char **argv)
2286 {
2287 	struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2288 
2289 	/* FIXME: Here the nightmare begins */
2290 
2291 	WERROR result;
2292 	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2293 	uint32_t i = 0, j = 0;
2294 	uint32_t num_printers;
2295 	uint32_t level = 2;
2296 	const char *printername, *sharename;
2297 	struct rpc_pipe_client *pipe_hnd_dst = NULL;
2298 	struct dcerpc_binding_handle *b_dst = NULL;
2299 	struct policy_handle hnd_src = { 0, };
2300 	struct policy_handle hnd_dst = { 0, };
2301 	union spoolss_PrinterInfo *info_enum;
2302 	union spoolss_PrinterInfo info_dst_publish;
2303 	union spoolss_PrinterInfo info_dst;
2304 	struct cli_state *cli_dst = NULL;
2305 	const char *longname;
2306 	const char **keylist = NULL;
2307 
2308 	/* FIXME GD */
2309 	ZERO_STRUCT(info_dst_publish);
2310 
2311 	DEBUG(3,("copying printer settings\n"));
2312 
2313 	/* connect destination PI_SPOOLSS */
2314 	nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2315 				     &ndr_table_spoolss);
2316 	if (!NT_STATUS_IS_OK(nt_status)) {
2317 		return nt_status;
2318 	}
2319 	b_dst = pipe_hnd_dst->binding_handle;
2320 
2321 	/* enum src printers */
2322 	if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2323 		nt_status = NT_STATUS_UNSUCCESSFUL;
2324 		goto done;
2325 	}
2326 
2327 	if (!num_printers) {
2328 		printf (_("no printers found on server.\n"));
2329 		nt_status = NT_STATUS_OK;
2330 		goto done;
2331 	}
2332 
2333 
2334 	/* needed for dns-strings in regkeys */
2335 	longname = get_mydnsfullname();
2336 	if (!longname) {
2337 		nt_status = NT_STATUS_UNSUCCESSFUL;
2338 		goto done;
2339 	}
2340 
2341 	/* do something for all printers */
2342 	for (i = 0; i < num_printers; i++) {
2343 
2344 		uint32_t value_needed;
2345 		uint32_t data_needed;
2346 		enum winreg_Type type;
2347 		struct spoolss_EnumPrinterData r;
2348 
2349 		/* do some initialization */
2350 		printername = info_enum[i].info2.printername;
2351 		sharename = info_enum[i].info2.sharename;
2352 
2353 		if (!printername || !sharename) {
2354 			nt_status = NT_STATUS_UNSUCCESSFUL;
2355 			goto done;
2356 		}
2357 		/* we can reset NT_STATUS here because we do not
2358 		   get any real NT_STATUS-codes anymore from now on */
2359 		nt_status = NT_STATUS_UNSUCCESSFUL;
2360 
2361 		d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2362 			printername, sharename);
2363 
2364 
2365 		/* open src printer handle */
2366 		if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2367 			MAXIMUM_ALLOWED_ACCESS, &hnd_src))
2368 			goto done;
2369 
2370 		/* open dst printer handle */
2371 		if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2372 			PRINTER_ALL_ACCESS, &hnd_dst))
2373 			goto done;
2374 
2375 		/* check for existing dst printer */
2376 		if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2377 				level, &info_dst))
2378 			goto done;
2379 
2380 
2381 		/* STEP 1: COPY DEVICE-MODE and other
2382 			   PRINTER_INFO_2-attributes
2383 		*/
2384 
2385 		info_dst.info2 = info_enum[i].info2;
2386 
2387 		/* why is the port always disconnected when the printer
2388 		   is correctly installed (incl. driver ???) */
2389 		info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2390 
2391 		/* check if printer is published */
2392 		if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2393 
2394 			/* check for existing dst printer */
2395 			if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2396 				goto done;
2397 
2398 			info_dst_publish.info7.action = DSPRINT_PUBLISH;
2399 
2400 			/* ignore false from setprinter due to WERR_IO_PENDING */
2401 			net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2402 
2403 			DEBUG(3,("republished printer\n"));
2404 		}
2405 
2406 		if (info_enum[i].info2.devmode != NULL) {
2407 
2408 			/* copy devmode (info level 2) */
2409 			info_dst.info2.devmode = info_enum[i].info2.devmode;
2410 
2411 			/* do not copy security descriptor (we have another
2412 			 * command for that) */
2413 			info_dst.info2.secdesc = NULL;
2414 
2415 #if 0
2416 			info_dst.info2.devmode.devicename =
2417 				talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2418 						longname, printername);
2419 			if (!info_dst.info2.devmode.devicename) {
2420 				nt_status = NT_STATUS_NO_MEMORY;
2421 				goto done;
2422 			}
2423 #endif
2424 			if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2425 						    level, &info_dst))
2426 				goto done;
2427 
2428 			DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2429 		}
2430 
2431 		/* STEP 2: COPY REGISTRY VALUES */
2432 
2433 		/* please keep in mind that samba parse_spools gives horribly
2434 		   crippled results when used to rpccli_spoolss_enumprinterdataex
2435 		   a win2k3-server.  (Bugzilla #1851)
2436 		   FIXME: IIRC I've seen it too on a win2k-server
2437 		*/
2438 
2439 		r.in.handle = &hnd_src;
2440 		r.in.enum_index = 0;
2441 		r.in.value_offered = 0;
2442 		r.in.data_offered = 0;
2443 		r.out.value_name = NULL;
2444 		r.out.value_needed = &value_needed;
2445 		r.out.type = &type;
2446 		r.out.data = NULL;
2447 		r.out.data_needed = &data_needed;
2448 
2449 		/* enumerate data on src handle */
2450 		nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2451 
2452 		r.in.data_offered	= *r.out.data_needed;
2453 		r.in.value_offered	= *r.out.value_needed;
2454 		r.out.data		= talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
2455 		r.out.value_name	= talloc_zero_array(mem_ctx, char, r.in.value_offered);
2456 
2457 		/* loop for all printerdata of "PrinterDriverData" */
2458 		while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2459 
2460 			r.in.enum_index++;
2461 
2462 			nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2463 
2464 			/* loop for all reg_keys */
2465 			if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2466 
2467 				/* display_value */
2468 				if (c->opt_verbose) {
2469 					struct registry_value v;
2470 					v.type = *r.out.type;
2471 					v.data = data_blob_const(
2472 						r.out.data, r.in.data_offered);
2473 
2474 					display_reg_value(SPOOL_PRINTERDATA_KEY,
2475 							  r.out.value_name, &v);
2476 				}
2477 
2478 				/* set_value */
2479 				if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2480 								&hnd_dst, r.out.value_name,
2481 								*r.out.type, r.out.data, r.in.data_offered))
2482 					goto done;
2483 
2484 				DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2485 					    r.out.value_name));
2486 			}
2487 		}
2488 
2489 		/* STEP 3: COPY SUBKEY VALUES */
2490 
2491 		/* here we need to enum all printer_keys and then work
2492 		   on the result with enum_printer_key_ex. nt4 does not
2493 		   respond to enumprinterkey, win2k does, so continue
2494 		   in case of an error */
2495 
2496 		if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2497 			printf(_("got no key-data\n"));
2498 			continue;
2499 		}
2500 
2501 
2502 		/* work on a list of printer keys
2503 		   each key has to be enumerated to get all required
2504 		   information.  information is then set via setprinterdataex-calls */
2505 
2506 		if (keylist == NULL)
2507 			continue;
2508 
2509 		for (i=0; keylist && keylist[i] != NULL; i++) {
2510 
2511 			const char *subkey = keylist[i];
2512 			uint32_t count;
2513 			struct spoolss_PrinterEnumValues *info;
2514 
2515 			/* enumerate all src subkeys */
2516 			if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2517 							   &hnd_src, subkey,
2518 							   &count, &info)) {
2519 				goto done;
2520 			}
2521 
2522 			for (j=0; j < count; j++) {
2523 
2524 				struct registry_value value;
2525 				const char *value_name = info[j].value_name;
2526 				bool ok;
2527 
2528 				value.type = REG_SZ;
2529 
2530 				/* although samba replies with sane data in most cases we
2531 				   should try to avoid writing wrong registry data */
2532 
2533 				if (strequal(value_name, SPOOL_REG_PORTNAME)) {
2534 					/* although windows uses a multi-sz, we use a sz */
2535 					ok = push_reg_sz(mem_ctx, &value.data, SAMBA_PRINTER_PORT_NAME);
2536 					if (!ok) {
2537 						nt_status = NT_STATUS_NO_MEMORY;
2538 						goto done;
2539 					}
2540 				}
2541 				else if (strequal(value_name, SPOOL_REG_UNCNAME)) {
2542 					char *unc_name;
2543 					if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2544 						nt_status = NT_STATUS_NO_MEMORY;
2545 						goto done;
2546 					}
2547 					ok = push_reg_sz(mem_ctx, &value.data, unc_name);
2548 					if (!ok) {
2549 						nt_status = NT_STATUS_NO_MEMORY;
2550 						goto done;
2551 					}
2552 					free(unc_name);
2553 				}
2554 				else if (strequal(value_name, SPOOL_REG_URL)) {
2555 					continue;
2556 #if 0
2557 					/* FIXME: should we really do that ??? */
2558 					if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2559 						nt_status = NT_STATUS_NO_MEMORY;
2560 						goto done;
2561 					}
2562 					push_reg_sz(mem_ctx, NULL, &value.data, url);
2563 					free(url);
2564 #endif
2565 				}
2566 				else if (strequal(value_name, SPOOL_REG_SERVERNAME)) {
2567 					ok = push_reg_sz(mem_ctx, &value.data, longname);
2568 					if (!ok) {
2569 						nt_status = NT_STATUS_NO_MEMORY;
2570 						goto done;
2571 					}
2572 				}
2573 				else if (strequal(value_name, SPOOL_REG_SHORTSERVERNAME)) {
2574 					ok = push_reg_sz(mem_ctx, &value.data, lp_netbios_name());
2575 					if (!ok) {
2576 						nt_status = NT_STATUS_NO_MEMORY;
2577 						goto done;
2578 					}
2579 				}
2580 				else {
2581 					value.type = info[j].type;
2582 					value.data = *info[j].data;
2583 				}
2584 
2585 				if (c->opt_verbose) {
2586 					display_reg_value(subkey, value_name, &value);
2587 				}
2588 
2589 				/* here we have to set all subkeys on the dst server */
2590 				if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2591 								  subkey, value_name, &value))
2592 				{
2593 					goto done;
2594 				}
2595 
2596 				DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2597 						subkey, info[j].value_name));
2598 
2599 			}
2600 		}
2601 
2602 		TALLOC_FREE(keylist);
2603 
2604 		/* close printer handles here */
2605 		if (is_valid_policy_hnd(&hnd_src)) {
2606 			dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2607 		}
2608 
2609 		if (is_valid_policy_hnd(&hnd_dst)) {
2610 			dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2611 		}
2612 	}
2613 
2614 	nt_status = NT_STATUS_OK;
2615 
2616 done:
2617 	if (is_valid_policy_hnd(&hnd_src)) {
2618 		dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2619 	}
2620 
2621 	if (is_valid_policy_hnd(&hnd_dst)) {
2622 		dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2623 	}
2624 
2625 	if (cli_dst) {
2626 		cli_shutdown(cli_dst);
2627 	}
2628 	return nt_status;
2629 }
2630