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