1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "includes.h"
23 #include "printing/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
27 #include "secrets.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "auth.h"
34 #include "messages.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.h"
37 
38 /* Map generic permissions to printer object specific permissions */
39 
40 const struct generic_mapping printer_generic_mapping = {
41 	PRINTER_READ,
42 	PRINTER_WRITE,
43 	PRINTER_EXECUTE,
44 	PRINTER_ALL_ACCESS
45 };
46 
47 /* Map generic permissions to print server object specific permissions */
48 
49 const struct generic_mapping printserver_generic_mapping = {
50 	SERVER_READ,
51 	SERVER_WRITE,
52 	SERVER_EXECUTE,
53 	SERVER_ALL_ACCESS
54 };
55 
56 /* Map generic permissions to job object specific permissions */
57 
58 const struct generic_mapping job_generic_mapping = {
59 	JOB_READ,
60 	JOB_WRITE,
61 	JOB_EXECUTE,
62 	JOB_ALL_ACCESS
63 };
64 
65 static const struct print_architecture_table_node archi_table[]= {
66 
67 	{"Windows 4.0",          SPL_ARCH_WIN40,	0 },
68 	{"Windows NT x86",       SPL_ARCH_W32X86,	2 },
69 	{"Windows NT R4000",     SPL_ARCH_W32MIPS,	2 },
70 	{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,	2 },
71 	{"Windows NT PowerPC",   SPL_ARCH_W32PPC,	2 },
72 	{"Windows IA64",   	 SPL_ARCH_IA64,		3 },
73 	{"Windows x64",   	 SPL_ARCH_X64,		3 },
74 	{NULL,                   "",		-1 }
75 };
76 
print_driver_directories_init(void)77 static bool print_driver_directories_init(void)
78 {
79 	int service, i;
80 	char *driver_path;
81 	bool ok;
82 	TALLOC_CTX *mem_ctx = talloc_stackframe();
83 	const struct loadparm_substitution *lp_sub =
84 		loadparm_s3_global_substitution();
85 
86 	const char *dir_list[] = {
87 		"W32X86/PCC",
88 		"x64/PCC",
89 		"color"
90 	};
91 
92 	service = lp_servicenumber("print$");
93 	if (service < 0) {
94 		/* We don't have a print$ share */
95 		DEBUG(5, ("No print$ share has been configured.\n"));
96 		talloc_free(mem_ctx);
97 		return true;
98 	}
99 
100 	driver_path = lp_path(mem_ctx, lp_sub, service);
101 	if (driver_path == NULL) {
102 		talloc_free(mem_ctx);
103 		return false;
104 	}
105 
106 	ok = directory_create_or_exist(driver_path, 0755);
107 	if (!ok) {
108 		DEBUG(1, ("Failed to create printer driver directory %s\n",
109 			  driver_path));
110 		talloc_free(mem_ctx);
111 		return false;
112 	}
113 
114 	for (i = 0; archi_table[i].long_archi != NULL; i++) {
115 		const char *arch_path;
116 
117 		arch_path = talloc_asprintf(mem_ctx,
118 					    "%s/%s",
119 					    driver_path,
120 					    archi_table[i].short_archi);
121 		if (arch_path == NULL) {
122 			talloc_free(mem_ctx);
123 			return false;
124 		}
125 
126 		ok = directory_create_or_exist(arch_path, 0755);
127 		if (!ok) {
128 			DEBUG(1, ("Failed to create printer driver "
129 				  "architecture directory %s\n",
130 				  arch_path));
131 			talloc_free(mem_ctx);
132 			return false;
133 		}
134 	}
135 
136 	for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
137 		const char *path;
138 
139 		path = talloc_asprintf(mem_ctx,
140 				       "%s/%s",
141 				       driver_path,
142 				       dir_list[i]);
143 		if (path == NULL) {
144 			talloc_free(mem_ctx);
145 			return false;
146 		}
147 
148 		ok = directory_create_or_exist(path, 0755);
149 		if (!ok) {
150 			DEBUG(1, ("Failed to create printer driver "
151 				  "architecture directory %s\n",
152 				  path));
153 			talloc_free(mem_ctx);
154 			return false;
155 		}
156 	}
157 
158 	driver_path = state_path(talloc_tos(), "DriverStore");
159 	if (driver_path == NULL) {
160 		talloc_free(mem_ctx);
161 		return false;
162 	}
163 
164 	ok = directory_create_or_exist(driver_path, 0755);
165 	if (!ok) {
166 		DEBUG(1,("failed to create path %s\n", driver_path));
167 		talloc_free(mem_ctx);
168 		return false;
169 	}
170 
171 	driver_path = state_path(talloc_tos(), "DriverStore/FileRepository");
172 	if (driver_path == NULL) {
173 		talloc_free(mem_ctx);
174 		return false;
175 	}
176 
177 	ok = directory_create_or_exist(driver_path, 0755);
178 	if (!ok) {
179 		DEBUG(1,("failed to create path %s\n", driver_path));
180 		talloc_free(mem_ctx);
181 		return false;
182 	}
183 
184 	driver_path = state_path(talloc_tos(), "DriverStore/Temp");
185 	if (driver_path == NULL) {
186 		talloc_free(mem_ctx);
187 		return false;
188 	}
189 
190 	ok = directory_create_or_exist(driver_path, 0755);
191 	if (!ok) {
192 		DEBUG(1,("failed to create path %s\n", driver_path));
193 		talloc_free(mem_ctx);
194 		return false;
195 	}
196 
197 	talloc_free(mem_ctx);
198 	return true;
199 }
200 
201 /****************************************************************************
202  Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
203  background lpq updater.
204 ****************************************************************************/
205 
forward_drv_upgrade_printer_msg(struct messaging_context * msg,void * private_data,uint32_t msg_type,struct server_id server_id,DATA_BLOB * data)206 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
207 				void *private_data,
208 				uint32_t msg_type,
209 				struct server_id server_id,
210 				DATA_BLOB *data)
211 {
212 	extern pid_t background_lpq_updater_pid;
213 
214 	if (background_lpq_updater_pid == -1) {
215 		DEBUG(3,("no background lpq queue updater\n"));
216 		return;
217 	}
218 
219 	messaging_send_buf(msg,
220 			pid_to_procid(background_lpq_updater_pid),
221 			MSG_PRINTER_DRVUPGRADE,
222 			data->data,
223 			data->length);
224 }
225 
226 /****************************************************************************
227  Open the NT printing tdbs. Done once before fork().
228 ****************************************************************************/
229 
nt_printing_init(struct messaging_context * msg_ctx)230 bool nt_printing_init(struct messaging_context *msg_ctx)
231 {
232 	WERROR win_rc;
233 
234 	if (!print_driver_directories_init()) {
235 		return false;
236 	}
237 
238 	if (!nt_printing_tdb_upgrade()) {
239 		return false;
240 	}
241 
242 	/*
243 	 * register callback to handle updating printers as new
244 	 * drivers are installed. Forwards to background lpq updater.
245 	 */
246 	messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
247 			forward_drv_upgrade_printer_msg);
248 
249 	if ( lp_security() == SEC_ADS ) {
250 		win_rc = check_published_printers(msg_ctx);
251 		if (!W_ERROR_IS_OK(win_rc))
252 			DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
253 	}
254 
255 	return true;
256 }
257 
258 /*******************************************************************
259  Function to allow filename parsing "the old way".
260 ********************************************************************/
261 
driver_unix_convert(connection_struct * conn,const char * old_name,struct smb_filename ** smb_fname)262 static NTSTATUS driver_unix_convert(connection_struct *conn,
263 				    const char *old_name,
264 				    struct smb_filename **smb_fname)
265 {
266 	NTSTATUS status;
267 	TALLOC_CTX *ctx = talloc_tos();
268 	char *name = talloc_strdup(ctx, old_name);
269 
270 	if (!name) {
271 		return NT_STATUS_NO_MEMORY;
272 	}
273 	unix_format(name);
274 	name = unix_clean_name(ctx, name);
275 	if (!name) {
276 		return NT_STATUS_NO_MEMORY;
277 	}
278 	trim_string(name,"/","/");
279 
280 	status = unix_convert(ctx, conn, name, smb_fname, 0);
281 	if (!NT_STATUS_IS_OK(status)) {
282 		return NT_STATUS_NO_MEMORY;
283 	}
284 
285 	return NT_STATUS_OK;
286 }
287 
288 /****************************************************************************
289  Function to do the mapping between the long architecture name and
290  the short one.
291 ****************************************************************************/
292 
get_short_archi(const char * long_archi)293 const char *get_short_archi(const char *long_archi)
294 {
295         int i=-1;
296 
297         DEBUG(107,("Getting architecture dependent directory\n"));
298         do {
299                 i++;
300         } while ( (archi_table[i].long_archi!=NULL ) &&
301                   strcasecmp_m(long_archi, archi_table[i].long_archi) );
302 
303         if (archi_table[i].long_archi==NULL) {
304                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
305                 return NULL;
306         }
307 
308 	/* this might be client code - but shouldn't this be an fstrcpy etc? */
309 
310         DEBUGADD(108,("index: [%d]\n", i));
311         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
312         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
313 
314 	return archi_table[i].short_archi;
315 }
316 
317 /****************************************************************************
318  Read data from fsp on the vfs.
319 ****************************************************************************/
320 
printing_pread_data(files_struct * fsp,char * buf,off_t * poff,size_t byte_count)321 static ssize_t printing_pread_data(files_struct *fsp,
322 				char *buf,
323 				off_t *poff,
324 				size_t byte_count)
325 {
326 	size_t total=0;
327 	off_t in_pos = *poff;
328 
329 	/* Don't allow integer wrap on read. */
330 	if (in_pos + byte_count < in_pos) {
331 		return -1;
332 	}
333 
334 	while (total < byte_count) {
335 		ssize_t ret = read_file(fsp,
336 					buf + total,
337 					in_pos,
338 					byte_count - total);
339 
340 		if (ret == 0) {
341 			*poff = in_pos;
342 			return total;
343 		}
344 		if (ret == -1) {
345 			if (errno == EINTR) {
346 				continue;
347 			} else {
348 				return -1;
349 			}
350 		}
351 		in_pos += ret;
352 		total += ret;
353 	}
354 	*poff = in_pos;
355 	return (ssize_t)total;
356 }
357 
358 /****************************************************************************
359  Detect the major and minor version of a PE file.
360  Returns:
361 
362  1 if file is a PE file and we got version numbers,
363  0 if this file is a PE file and we couldn't get the version numbers,
364  -1 on error.
365 
366  NB. buf is passed into and freed inside this function. This is a
367  bad API design, but fixing this is a task for another day.
368 ****************************************************************************/
369 
handle_pe_file(files_struct * fsp,off_t in_pos,char * fname,char * buf,uint32_t * major,uint32_t * minor)370 static int handle_pe_file(files_struct *fsp,
371 				off_t in_pos,
372 				char *fname,
373 				char *buf,
374 				uint32_t *major,
375 				uint32_t *minor)
376 {
377 	unsigned int i;
378 	unsigned int num_sections;
379 	unsigned int section_table_bytes;
380 	ssize_t byte_count;
381 	off_t rel_pos;
382 	int ret = -1;
383 
384 	/* Just skip over optional header to get to section table */
385 	rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
386 		(NE_HEADER_SIZE-PE_HEADER_SIZE);
387 
388 	if (in_pos + rel_pos < in_pos) {
389 		/* Integer wrap. */
390 		goto out;
391 	}
392 	in_pos = rel_pos + in_pos;
393 
394 	/* get the section table */
395 	num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
396 
397 	if (num_sections >= (UINT_MAX / PE_HEADER_SECT_HEADER_SIZE)) {
398 		/* Integer wrap. */
399 		goto out;
400 	}
401 
402 	section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
403 	if (section_table_bytes == 0) {
404 		goto out;
405 	}
406 
407 	SAFE_FREE(buf);
408 	buf = (char *)SMB_MALLOC(section_table_bytes);
409 	if (buf == NULL) {
410 		DBG_ERR("PE file [%s] section table malloc "
411 			"failed bytes = %d\n",
412 			fname,
413 			section_table_bytes);
414 		goto out;
415 	}
416 
417 	byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
418 	if (byte_count < section_table_bytes) {
419 		DBG_NOTICE("PE file [%s] Section header too short, "
420 			"bytes read = %lu\n",
421 			fname,
422 			(unsigned long)byte_count);
423 		goto out;
424 	}
425 
426 	/*
427 	 * Iterate the section table looking for
428 	 * the resource section ".rsrc"
429 	 */
430 	for (i = 0; i < num_sections; i++) {
431 		int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
432 
433 		if (strcmp(".rsrc",
434 			&buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
435 			unsigned int section_pos = IVAL(buf,
436 					sec_offset+
437 					PE_HEADER_SECT_PTR_DATA_OFFSET);
438 			unsigned int section_bytes = IVAL(buf,
439 					sec_offset+
440 					PE_HEADER_SECT_SIZE_DATA_OFFSET);
441 
442 			if (section_bytes == 0) {
443 				goto out;
444 			}
445 
446 			SAFE_FREE(buf);
447 			buf=(char *)SMB_MALLOC(section_bytes);
448 			if (buf == NULL) {
449 				DBG_ERR("PE file [%s] version malloc "
450 					"failed bytes = %d\n",
451 					fname,
452 					section_bytes);
453 				goto out;
454 			}
455 
456 			/*
457 			 * Read from the start of the .rsrc
458 			 * section info
459 			 */
460 			in_pos = section_pos;
461 
462 			byte_count = printing_pread_data(fsp,
463 						buf,
464 						&in_pos,
465 						section_bytes);
466 			if (byte_count < section_bytes) {
467 				DBG_NOTICE("PE file "
468 					"[%s] .rsrc section too short, "
469 					"bytes read = %lu\n",
470 					 fname,
471 					(unsigned long)byte_count);
472 				goto out;
473 			}
474 
475 			if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
476 				goto out;
477 			}
478 
479 			for (i=0;
480 				i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
481 					i++) {
482 				/*
483 				 * Scan for 1st 3 unicoded bytes
484 				 * followed by word aligned magic
485 				 * value.
486 				 */
487 				int mpos;
488 				bool magic_match = false;
489 
490 				if (buf[i] == 'V' &&
491 						buf[i+1] == '\0' &&
492 						buf[i+2] == 'S') {
493 					magic_match = true;
494 				}
495 
496 				if (magic_match == false) {
497 					continue;
498 				}
499 
500 				/* Align to next long address */
501 				mpos = (i + sizeof(VS_SIGNATURE)*2 +
502 					3) & 0xfffffffc;
503 
504 				if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
505 					*major = IVAL(buf,
506 							mpos+ VS_MAJOR_OFFSET);
507 					*minor = IVAL(buf,
508 							mpos+ VS_MINOR_OFFSET);
509 
510 					DBG_INFO("PE file [%s] Version = "
511 						"%08x:%08x (%d.%d.%d.%d)\n",
512 						fname,
513 						*major,
514 						*minor,
515 						(*major>>16)&0xffff,
516 						*major&0xffff,
517 						(*minor>>16)&0xffff,
518 						*minor&0xffff);
519 					ret = 1;
520 					goto out;
521 				}
522 			}
523 		}
524 	}
525 
526 	/* Version info not found, fall back to origin date/time */
527 	DBG_DEBUG("PE file [%s] has no version info\n", fname);
528 	ret = 0;
529 
530   out:
531 
532 	SAFE_FREE(buf);
533 	return ret;
534 }
535 
536 /****************************************************************************
537  Detect the major and minor version of an NE file.
538  Returns:
539 
540  1 if file is an NE file and we got version numbers,
541  0 if this file is an NE file and we couldn't get the version numbers,
542  -1 on error.
543 
544  NB. buf is passed into and freed inside this function. This is a
545  bad API design, but fixing this is a task for another day.
546 ****************************************************************************/
547 
handle_ne_file(files_struct * fsp,off_t in_pos,char * fname,char * buf,uint32_t * major,uint32_t * minor)548 static int handle_ne_file(files_struct *fsp,
549 				off_t in_pos,
550 				char *fname,
551 				char *buf,
552 				uint32_t *major,
553 				uint32_t *minor)
554 {
555 	unsigned int i;
556 	ssize_t byte_count;
557 	int ret = -1;
558 
559 	if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
560 		DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
561 			fname,
562 			CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
563 		/*
564 		 * At this point, we assume the file is in error.
565 		 * It still could be something else besides a NE file,
566 		 * but it unlikely at this point.
567 		 */
568 		goto out;
569 	}
570 
571 	/* Allocate a bit more space to speed up things */
572 	SAFE_FREE(buf);
573 	buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
574 	if (buf == NULL) {
575 		DBG_ERR("NE file [%s] malloc failed bytes  = %d\n",
576 			fname,
577 			PE_HEADER_SIZE);
578 		goto out;
579 	}
580 
581 	/*
582 	 * This is a HACK! I got tired of trying to sort through the
583 	 * messy 'NE' file format. If anyone wants to clean this up
584 	 * please have at it, but this works. 'NE' files will
585 	 * eventually fade away. JRR
586 	 */
587 	byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
588 	while (byte_count > 0) {
589 		/*
590 		 * Cover case that should not occur in a well
591 		 * formed 'NE' .dll file
592 		 */
593 		if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
594 			break;
595 		}
596 
597 		for(i=0; i<byte_count; i++) {
598 			/*
599 			 * Fast skip past data that can't
600 			 * possibly match
601 			 */
602 			if (buf[i] != 'V') {
603 				byte_count = printing_pread_data(fsp,
604 						buf,
605 						&in_pos,
606 						VS_NE_BUF_SIZE);
607 				continue;
608 			}
609 
610 			/*
611 			 * Potential match data crosses buf boundry,
612 			 * move it to beginning of buf, and fill the
613 			 * buf with as much as it will hold.
614 			 */
615 			if (i>byte_count-VS_VERSION_INFO_SIZE) {
616 				ssize_t amount_read;
617 				ssize_t amount_unused = byte_count-i;
618 
619 				memmove(buf, &buf[i], amount_unused);
620 				amount_read = printing_pread_data(fsp,
621 						&buf[amount_unused],
622 						&in_pos,
623 						VS_NE_BUF_SIZE- amount_unused);
624 				if (amount_read < 0) {
625 					DBG_ERR("NE file [%s] Read "
626 						"error, errno=%d\n",
627 						fname,
628 						errno);
629 					goto out;
630 				}
631 
632 				if (amount_read + amount_unused <
633 						amount_read) {
634 					/* Check for integer wrap. */
635 					break;
636 				}
637 
638 				byte_count = amount_read +
639 					     amount_unused;
640 				if (byte_count < VS_VERSION_INFO_SIZE) {
641 					break;
642 				}
643 
644 				i = 0;
645 			}
646 
647 			/*
648 			 * Check that the full signature string and
649 			 * the magic number that follows exist (not
650 			 * a perfect solution, but the chances that this
651 			 * occurs in code is, well, remote. Yes I know
652 			 * I'm comparing the 'V' twice, as it is
653 			 * simpler to read the code.
654 			 */
655 			if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
656 				/*
657 				 * Compute skip alignment to next
658 				 * long address.
659 				 */
660 				off_t cpos = in_pos;
661 				int skip = -(cpos - (byte_count - i) +
662 					 sizeof(VS_SIGNATURE)) & 3;
663 				if (IVAL(buf,
664 					i+sizeof(VS_SIGNATURE)+skip)
665 						!= 0xfeef04bd) {
666 					byte_count = printing_pread_data(fsp,
667 							buf,
668 							&in_pos,
669 							VS_NE_BUF_SIZE);
670 					continue;
671 				}
672 
673 				*major = IVAL(buf,
674 					i+sizeof(VS_SIGNATURE)+
675 					skip+VS_MAJOR_OFFSET);
676 				*minor = IVAL(buf,
677 					i+sizeof(VS_SIGNATURE)+
678 					skip+VS_MINOR_OFFSET);
679 				DBG_INFO("NE file [%s] Version "
680 					"= %08x:%08x (%d.%d.%d.%d)\n",
681 					fname,
682 					*major,
683 					*minor,
684 					(*major>>16)&0xffff,
685 					*major&0xffff,
686 					(*minor>>16)&0xffff,
687 					*minor&0xffff);
688 				ret = 1;
689 				goto out;
690 			}
691 		}
692 	}
693 
694 	/* Version info not found, fall back to origin date/time */
695 	DBG_ERR("NE file [%s] Version info not found\n", fname);
696 	ret = 0;
697 
698   out:
699 
700 	SAFE_FREE(buf);
701 	return ret;
702 }
703 
704 /****************************************************************************
705  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
706  There are two case to be covered here: PE (Portable Executable) and NE (New
707  Executable) files. Both files support the same INFO structure, but PE files
708  store the signature in unicode, and NE files store it as !unicode.
709  returns -1 on error, 1 on version info found, and 0 on no version info found.
710 ****************************************************************************/
711 
get_file_version(files_struct * fsp,char * fname,uint32_t * major,uint32_t * minor)712 static int get_file_version(files_struct *fsp,
713 				char *fname,
714 				uint32_t *major,
715 				uint32_t *minor)
716 {
717 	char    *buf = NULL;
718 	ssize_t byte_count;
719 	off_t in_pos = fsp->fh->pos;
720 
721 	buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
722 	if (buf == NULL) {
723 		DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
724 			fname,
725 			DOS_HEADER_SIZE);
726 		goto error_exit;
727 	}
728 
729 	byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
730 	if (byte_count < DOS_HEADER_SIZE) {
731 		DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
732 			 fname,
733 			(unsigned long)byte_count);
734 		goto no_version_info;
735 	}
736 
737 	/* Is this really a DOS header? */
738 	if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
739 		DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
740 			fname,
741 			SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
742 		goto no_version_info;
743 	}
744 
745 	/*
746 	 * Skip OEM header (if any) and the
747 	 * DOS stub to start of Windows header.
748 	 */
749 	in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
750 
751 	/* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
752 	byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
753 	if (byte_count < NE_HEADER_SIZE) {
754 		DBG_NOTICE("File [%s] Windows header too short, "
755 			"bytes read = %lu\n",
756 			fname,
757 			(unsigned long)byte_count);
758 		/*
759 		 * Assume this isn't an error...
760 		 * the file just looks sort of like a PE/NE file
761 		 */
762 		goto no_version_info;
763 	}
764 
765 	/*
766 	 * The header may be a PE (Portable Executable)
767 	 * or an NE (New Executable).
768 	 */
769 	if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
770 		return handle_pe_file(fsp,
771 					in_pos,
772 					fname,
773 					buf,
774 					major,
775 					minor);
776 	} else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
777 			NE_HEADER_SIGNATURE) {
778 		return handle_ne_file(fsp,
779 					in_pos,
780 					fname,
781 					buf,
782 					major,
783 					minor);
784 	} else {
785 		/*
786 		 * Assume this isn't an error... the file just
787 		 * looks sort of like a PE/NE file.
788 		 */
789 		DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
790 			fname,
791 			IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
792 		/* Fallthrough into no_version_info: */
793 	}
794 
795 	no_version_info:
796 		SAFE_FREE(buf);
797 		return 0;
798 
799 	error_exit:
800 		SAFE_FREE(buf);
801 		return -1;
802 }
803 
804 /****************************************************************************
805 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
806 share one or more files. During the MS installation process files are checked
807 to insure that only a newer version of a shared file is installed over an
808 older version. There are several possibilities for this comparison. If there
809 is no previous version, the new one is newer (obviously). If either file is
810 missing the version info structure, compare the creation date (on Unix use
811 the modification date). Otherwise chose the numerically larger version number.
812 ****************************************************************************/
813 
file_version_is_newer(connection_struct * conn,fstring new_file,fstring old_file)814 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
815 {
816 	bool use_version = true;
817 
818 	uint32_t new_major;
819 	uint32_t new_minor;
820 	time_t new_create_time;
821 
822 	uint32_t old_major;
823 	uint32_t old_minor;
824 	time_t old_create_time;
825 
826 	struct smb_filename *smb_fname = NULL;
827 	files_struct    *fsp = NULL;
828 	SMB_STRUCT_STAT st;
829 
830 	NTSTATUS status;
831 	int ret;
832 
833 	SET_STAT_INVALID(st);
834 	new_create_time = (time_t)0;
835 	old_create_time = (time_t)0;
836 
837 	/* Get file version info (if available) for previous file (if it exists) */
838 	status = driver_unix_convert(conn, old_file, &smb_fname);
839 	if (!NT_STATUS_IS_OK(status)) {
840 		goto error_exit;
841 	}
842 
843 	status = SMB_VFS_CREATE_FILE(
844 		conn,					/* conn */
845 		NULL,					/* req */
846 		0,					/* root_dir_fid */
847 		smb_fname,				/* fname */
848 		FILE_GENERIC_READ,			/* access_mask */
849 		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
850 		FILE_OPEN,				/* create_disposition*/
851 		0,					/* create_options */
852 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
853 		INTERNAL_OPEN_ONLY,			/* oplock_request */
854 		NULL,					/* lease */
855 		0,					/* allocation_size */
856 		0,					/* private_flags */
857 		NULL,					/* sd */
858 		NULL,					/* ea_list */
859 		&fsp,					/* result */
860 		NULL,					/* pinfo */
861 		NULL, NULL);                            /* create context */
862 
863 	if (!NT_STATUS_IS_OK(status)) {
864 		/* Old file not found, so by definition new file is in fact newer */
865 		DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
866 			  "errno = %d\n", smb_fname_str_dbg(smb_fname),
867 			  errno));
868 		ret = 1;
869 		goto done;
870 
871 	} else {
872 		ret = get_file_version(fsp, old_file, &old_major, &old_minor);
873 		if (ret == -1) {
874 			goto error_exit;
875 		}
876 
877 		if (!ret) {
878 			DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
879 					 old_file));
880 			use_version = false;
881 			if (SMB_VFS_FSTAT(fsp, &st) == -1) {
882 				 goto error_exit;
883 			}
884 			old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
885 			DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
886 				(long)old_create_time));
887 		}
888 	}
889 	close_file(NULL, fsp, NORMAL_CLOSE);
890 	fsp = NULL;
891 
892 	/* Get file version info (if available) for new file */
893 	status = driver_unix_convert(conn, new_file, &smb_fname);
894 	if (!NT_STATUS_IS_OK(status)) {
895 		goto error_exit;
896 	}
897 
898 	status = SMB_VFS_CREATE_FILE(
899 		conn,					/* conn */
900 		NULL,					/* req */
901 		0,					/* root_dir_fid */
902 		smb_fname,				/* fname */
903 		FILE_GENERIC_READ,			/* access_mask */
904 		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
905 		FILE_OPEN,				/* create_disposition*/
906 		0,					/* create_options */
907 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
908 		INTERNAL_OPEN_ONLY,			/* oplock_request */
909 		NULL,					/* lease */
910 		0,					/* allocation_size */
911 		0,					/* private_flags */
912 		NULL,					/* sd */
913 		NULL,					/* ea_list */
914 		&fsp,					/* result */
915 		NULL,					/* pinfo */
916 		NULL, NULL);				/* create context */
917 
918 	if (!NT_STATUS_IS_OK(status)) {
919 		/* New file not found, this shouldn't occur if the caller did its job */
920 		DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
921 			 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
922 		goto error_exit;
923 
924 	} else {
925 		ret = get_file_version(fsp, new_file, &new_major, &new_minor);
926 		if (ret == -1) {
927 			goto error_exit;
928 		}
929 
930 		if (!ret) {
931 			DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
932 					 new_file));
933 			use_version = false;
934 			if (SMB_VFS_FSTAT(fsp, &st) == -1) {
935 				goto error_exit;
936 			}
937 			new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
938 			DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
939 				(long)new_create_time));
940 		}
941 	}
942 	close_file(NULL, fsp, NORMAL_CLOSE);
943 	fsp = NULL;
944 
945 	if (use_version && (new_major != old_major || new_minor != old_minor)) {
946 		/* Compare versions and choose the larger version number */
947 		if (new_major > old_major ||
948 			(new_major == old_major && new_minor > old_minor)) {
949 
950 			DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
951 			ret = 1;
952 			goto done;
953 		}
954 		else {
955 			DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
956 			ret = 0;
957 			goto done;
958 		}
959 
960 	} else {
961 		/* Compare modification time/dates and choose the newest time/date */
962 		if (new_create_time > old_create_time) {
963 			DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
964 			ret = 1;
965 			goto done;
966 		}
967 		else {
968 			DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
969 			ret = 0;
970 			goto done;
971 		}
972 	}
973 
974  error_exit:
975 	if(fsp)
976 		close_file(NULL, fsp, NORMAL_CLOSE);
977 	ret = -1;
978  done:
979 	TALLOC_FREE(smb_fname);
980 	return ret;
981 }
982 
983 /****************************************************************************
984 Determine the correct cVersion associated with an architecture and driver
985 ****************************************************************************/
get_correct_cversion(const struct auth_session_info * session_info,const char * architecture,const char * driverpath_in,const char * driver_directory,WERROR * perr)986 static uint32_t get_correct_cversion(const struct auth_session_info *session_info,
987 				   const char *architecture,
988 				   const char *driverpath_in,
989 				   const char *driver_directory,
990 				   WERROR *perr)
991 {
992 	TALLOC_CTX *frame = talloc_stackframe();
993 	const struct loadparm_substitution *lp_sub =
994 		loadparm_s3_global_substitution();
995 	int cversion = -1;
996 	NTSTATUS          nt_status;
997 	struct smb_filename *smb_fname = NULL;
998 	files_struct      *fsp = NULL;
999 	struct conn_struct_tos *c = NULL;
1000 	connection_struct *conn = NULL;
1001 	char *printdollar = NULL;
1002 	char *printdollar_path = NULL;
1003 	char *working_dir = NULL;
1004 	int printdollar_snum;
1005 
1006 	*perr = WERR_INVALID_PARAMETER;
1007 
1008 	/* If architecture is Windows 95/98/ME, the version is always 0. */
1009 	if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1010 		DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1011 		*perr = WERR_OK;
1012 		TALLOC_FREE(frame);
1013 		return 0;
1014 	}
1015 
1016 	/* If architecture is Windows x64, the version is always 3. */
1017 	if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1018 		DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1019 		*perr = WERR_OK;
1020 		TALLOC_FREE(frame);
1021 		return 3;
1022 	}
1023 
1024 	printdollar_snum = find_service(frame, "print$", &printdollar);
1025 	if (!printdollar) {
1026 		*perr = WERR_NOT_ENOUGH_MEMORY;
1027 		TALLOC_FREE(frame);
1028 		return -1;
1029 	}
1030 	if (printdollar_snum == -1) {
1031 		*perr = WERR_BAD_NET_NAME;
1032 		TALLOC_FREE(frame);
1033 		return -1;
1034 	}
1035 
1036 	printdollar_path = lp_path(frame, lp_sub, printdollar_snum);
1037 	if (printdollar_path == NULL) {
1038 		*perr = WERR_NOT_ENOUGH_MEMORY;
1039 		TALLOC_FREE(frame);
1040 		return -1;
1041 	}
1042 
1043 	working_dir = talloc_asprintf(frame,
1044 				      "%s/%s",
1045 				      printdollar_path,
1046 				      architecture);
1047 	/*
1048 	 * If the driver has been uploaded into a temorpary driver
1049 	 * directory, switch to the driver directory.
1050 	 */
1051 	if (driver_directory != NULL) {
1052 		working_dir = talloc_asprintf(frame, "%s/%s/%s",
1053 					      printdollar_path,
1054 					      architecture,
1055 					      driver_directory);
1056 	}
1057 
1058 	nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
1059 					       printdollar_snum,
1060 					       working_dir,
1061 					       session_info,
1062 					       &c);
1063 	if (!NT_STATUS_IS_OK(nt_status)) {
1064 		DEBUG(0,("get_correct_cversion: create_conn_struct "
1065 			 "returned %s\n", nt_errstr(nt_status)));
1066 		*perr = ntstatus_to_werror(nt_status);
1067 		TALLOC_FREE(frame);
1068 		return -1;
1069 	}
1070 	conn = c->conn;
1071 
1072 	nt_status = set_conn_force_user_group(conn, printdollar_snum);
1073 	if (!NT_STATUS_IS_OK(nt_status)) {
1074 		DEBUG(0, ("failed set force user / group\n"));
1075 		*perr = ntstatus_to_werror(nt_status);
1076 		goto error_free_conn;
1077 	}
1078 
1079 	if (!become_user_without_service_by_session(conn, session_info)) {
1080 		DEBUG(0, ("failed to become user\n"));
1081 		*perr = WERR_ACCESS_DENIED;
1082 		goto error_free_conn;
1083 	}
1084 
1085 	/*
1086 	 * We switch to the directory where the driver files are located,
1087 	 * so only work on the file names
1088 	 */
1089 	nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1090 	if (!NT_STATUS_IS_OK(nt_status)) {
1091 		*perr = ntstatus_to_werror(nt_status);
1092 		goto error_exit;
1093 	}
1094 
1095 	nt_status = vfs_file_exist(conn, smb_fname);
1096 	if (!NT_STATUS_IS_OK(nt_status)) {
1097 		DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1098 		*perr = WERR_FILE_NOT_FOUND;
1099 		goto error_exit;
1100 	}
1101 
1102 	nt_status = SMB_VFS_CREATE_FILE(
1103 		conn,					/* conn */
1104 		NULL,					/* req */
1105 		0,					/* root_dir_fid */
1106 		smb_fname,				/* fname */
1107 		FILE_GENERIC_READ,			/* access_mask */
1108 		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
1109 		FILE_OPEN,				/* create_disposition*/
1110 		0,					/* create_options */
1111 		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
1112 		INTERNAL_OPEN_ONLY,			/* oplock_request */
1113 		NULL,					/* lease */
1114 		0,					/* private_flags */
1115 		0,					/* allocation_size */
1116 		NULL,					/* sd */
1117 		NULL,					/* ea_list */
1118 		&fsp,					/* result */
1119 		NULL,					/* pinfo */
1120 		NULL, NULL);				/* create context */
1121 
1122 	if (!NT_STATUS_IS_OK(nt_status)) {
1123 		DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1124 			 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1125 		*perr = WERR_ACCESS_DENIED;
1126 		goto error_exit;
1127 	} else {
1128 		uint32_t major;
1129 		uint32_t minor;
1130 		int    ret;
1131 
1132 		ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1133 		if (ret == -1) {
1134 			*perr = WERR_INVALID_PARAMETER;
1135 			goto error_exit;
1136 		} else if (!ret) {
1137 			DEBUG(6,("get_correct_cversion: Version info not "
1138 				 "found [%s]\n",
1139 				 smb_fname_str_dbg(smb_fname)));
1140 			*perr = WERR_INVALID_PARAMETER;
1141 			goto error_exit;
1142 		}
1143 
1144 		/*
1145 		 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1146 		 * for more details. Version in this case is not just the version of the
1147 		 * file, but the version in the sense of kernal mode (2) vs. user mode
1148 		 * (3) drivers. Other bits of the version fields are the version info.
1149 		 * JRR 010716
1150 		*/
1151 		cversion = major & 0x0000ffff;
1152 		switch (cversion) {
1153 			case 2: /* WinNT drivers */
1154 			case 3: /* Win2K drivers */
1155 				break;
1156 
1157 			default:
1158 				DEBUG(6,("get_correct_cversion: cversion "
1159 					 "invalid [%s]  cversion = %d\n",
1160 					 smb_fname_str_dbg(smb_fname),
1161 					 cversion));
1162 				goto error_exit;
1163 		}
1164 
1165 		DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1166 			  " = 0x%x  minor = 0x%x\n",
1167 			  smb_fname_str_dbg(smb_fname), major, minor));
1168 	}
1169 
1170 	DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1171 		  smb_fname_str_dbg(smb_fname), cversion));
1172 	*perr = WERR_OK;
1173 
1174  error_exit:
1175 	unbecome_user_without_service();
1176  error_free_conn:
1177 	if (fsp != NULL) {
1178 		close_file(NULL, fsp, NORMAL_CLOSE);
1179 	}
1180 	if (!W_ERROR_IS_OK(*perr)) {
1181 		cversion = -1;
1182 	}
1183 
1184 	TALLOC_FREE(frame);
1185 	return cversion;
1186 }
1187 
1188 /****************************************************************************
1189 ****************************************************************************/
1190 
1191 #define strip_driver_path(_mem_ctx, _element) do { \
1192 	if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1193 		(_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1194 		W_ERROR_HAVE_NO_MEMORY((_element)); \
1195 	} \
1196 } while (0);
1197 
clean_up_driver_struct_level(TALLOC_CTX * mem_ctx,const struct auth_session_info * session_info,const char * architecture,const char ** driver_path,const char ** data_file,const char ** config_file,const char ** help_file,struct spoolss_StringArray * dependent_files,enum spoolss_DriverOSVersion * version,uint32_t flags,const char ** driver_directory)1198 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1199 					   const struct auth_session_info *session_info,
1200 					   const char *architecture,
1201 					   const char **driver_path,
1202 					   const char **data_file,
1203 					   const char **config_file,
1204 					   const char **help_file,
1205 					   struct spoolss_StringArray *dependent_files,
1206 					   enum spoolss_DriverOSVersion *version,
1207 					   uint32_t flags,
1208 					   const char **driver_directory)
1209 {
1210 	const char *short_architecture;
1211 	int i;
1212 	WERROR err;
1213 	char *_p;
1214 
1215 	if (!*driver_path || !*data_file) {
1216 		return WERR_INVALID_PARAMETER;
1217 	}
1218 
1219 	if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1220 		return WERR_INVALID_PARAMETER;
1221 	}
1222 
1223 	if (flags & APD_COPY_FROM_DIRECTORY) {
1224 		char *path;
1225 		char *q;
1226 
1227 		/*
1228 		 * driver_path is set to:
1229 		 *
1230 		 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1231 		 */
1232 		path = talloc_strdup(mem_ctx, *driver_path);
1233 		if (path == NULL) {
1234 			return WERR_NOT_ENOUGH_MEMORY;
1235 		}
1236 
1237 		/* Remove pscript5.dll */
1238 		q = strrchr_m(path, '\\');
1239 		if (q == NULL) {
1240 			return WERR_INVALID_PARAMETER;
1241 		}
1242 		*q = '\0';
1243 
1244 		/* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1245 		q = strrchr_m(path, '\\');
1246 		if (q == NULL) {
1247 			return WERR_INVALID_PARAMETER;
1248 		}
1249 
1250 		/*
1251 		 * Set driver_directory to:
1252 		 *
1253 		 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1254 		 *
1255 		 * This is the directory where all the files have been uploaded
1256 		 */
1257 		*driver_directory = q + 1;
1258 	}
1259 
1260 	/* clean up the driver name.
1261 	 * we can get .\driver.dll
1262 	 * or worse c:\windows\system\driver.dll !
1263 	 */
1264 	/* using an intermediate string to not have overlaping memcpy()'s */
1265 
1266 	strip_driver_path(mem_ctx, *driver_path);
1267 	strip_driver_path(mem_ctx, *data_file);
1268 	if (*config_file) {
1269 		strip_driver_path(mem_ctx, *config_file);
1270 	}
1271 	if (help_file) {
1272 		strip_driver_path(mem_ctx, *help_file);
1273 	}
1274 
1275 	if (dependent_files && dependent_files->string) {
1276 		for (i=0; dependent_files->string[i]; i++) {
1277 			strip_driver_path(mem_ctx, dependent_files->string[i]);
1278 		}
1279 	}
1280 
1281 	short_architecture = get_short_archi(architecture);
1282 	if (!short_architecture) {
1283 		return WERR_UNKNOWN_PRINTER_DRIVER;
1284 	}
1285 
1286 	/* jfm:7/16/2000 the client always sends the cversion=0.
1287 	 * The server should check which version the driver is by reading
1288 	 * the PE header of driver->driverpath.
1289 	 *
1290 	 * For Windows 95/98 the version is 0 (so the value sent is correct)
1291 	 * For Windows NT (the architecture doesn't matter)
1292 	 *	NT 3.1: cversion=0
1293 	 *	NT 3.5/3.51: cversion=1
1294 	 *	NT 4: cversion=2
1295 	 *	NT2K: cversion=3
1296 	 */
1297 
1298 	*version = get_correct_cversion(session_info,
1299 					short_architecture,
1300 					*driver_path,
1301 					*driver_directory,
1302 					&err);
1303 	if (*version == -1) {
1304 		return err;
1305 	}
1306 
1307 	return WERR_OK;
1308 }
1309 
1310 /****************************************************************************
1311 ****************************************************************************/
1312 
clean_up_driver_struct(TALLOC_CTX * mem_ctx,const struct auth_session_info * session_info,const struct spoolss_AddDriverInfoCtr * r,uint32_t flags,const char ** driver_directory)1313 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1314 			      const struct auth_session_info *session_info,
1315 			      const struct spoolss_AddDriverInfoCtr *r,
1316 			      uint32_t flags,
1317 			      const char **driver_directory)
1318 {
1319 	switch (r->level) {
1320 	case 3:
1321 		return clean_up_driver_struct_level(mem_ctx, session_info,
1322 						    r->info.info3->architecture,
1323 						    &r->info.info3->driver_path,
1324 						    &r->info.info3->data_file,
1325 						    &r->info.info3->config_file,
1326 						    &r->info.info3->help_file,
1327 						    r->info.info3->dependent_files,
1328 						    &r->info.info3->version,
1329 						    flags,
1330 						    driver_directory);
1331 	case 6:
1332 		return clean_up_driver_struct_level(mem_ctx, session_info,
1333 						    r->info.info6->architecture,
1334 						    &r->info.info6->driver_path,
1335 						    &r->info.info6->data_file,
1336 						    &r->info.info6->config_file,
1337 						    &r->info.info6->help_file,
1338 						    r->info.info6->dependent_files,
1339 						    &r->info.info6->version,
1340 						    flags,
1341 						    driver_directory);
1342 	case 8:
1343 		return clean_up_driver_struct_level(mem_ctx, session_info,
1344 						    r->info.info8->architecture,
1345 						    &r->info.info8->driver_path,
1346 						    &r->info.info8->data_file,
1347 						    &r->info.info8->config_file,
1348 						    &r->info.info8->help_file,
1349 						    r->info.info8->dependent_files,
1350 						    &r->info.info8->version,
1351 						    flags,
1352 						    driver_directory);
1353 	default:
1354 		return WERR_NOT_SUPPORTED;
1355 	}
1356 }
1357 
1358 /****************************************************************************
1359  This function sucks and should be replaced. JRA.
1360 ****************************************************************************/
1361 
convert_level_6_to_level3(struct spoolss_AddDriverInfo3 * dst,const struct spoolss_AddDriverInfo6 * src)1362 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1363 				      const struct spoolss_AddDriverInfo6 *src)
1364 {
1365 	dst->version		= src->version;
1366 
1367 	dst->driver_name	= src->driver_name;
1368 	dst->architecture 	= src->architecture;
1369 	dst->driver_path	= src->driver_path;
1370 	dst->data_file		= src->data_file;
1371 	dst->config_file	= src->config_file;
1372 	dst->help_file		= src->help_file;
1373 	dst->monitor_name	= src->monitor_name;
1374 	dst->default_datatype	= src->default_datatype;
1375 	dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1376 	dst->dependent_files	= src->dependent_files;
1377 }
1378 
convert_level_8_to_level3(struct spoolss_AddDriverInfo3 * dst,const struct spoolss_AddDriverInfo8 * src)1379 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1380 				      const struct spoolss_AddDriverInfo8 *src)
1381 {
1382 	dst->version		= src->version;
1383 
1384 	dst->driver_name	= src->driver_name;
1385 	dst->architecture	= src->architecture;
1386 	dst->driver_path	= src->driver_path;
1387 	dst->data_file		= src->data_file;
1388 	dst->config_file	= src->config_file;
1389 	dst->help_file		= src->help_file;
1390 	dst->monitor_name	= src->monitor_name;
1391 	dst->default_datatype	= src->default_datatype;
1392 	dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1393 	dst->dependent_files	= src->dependent_files;
1394 }
1395 
1396 /****************************************************************************
1397 ****************************************************************************/
1398 
move_driver_file_to_download_area(TALLOC_CTX * mem_ctx,connection_struct * conn,const char * driver_file,const char * short_architecture,uint32_t driver_version,uint32_t version,const char * driver_directory)1399 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1400 						connection_struct *conn,
1401 						const char *driver_file,
1402 						const char *short_architecture,
1403 						uint32_t driver_version,
1404 						uint32_t version,
1405 						const char *driver_directory)
1406 {
1407 	struct smb_filename *smb_fname_old = NULL;
1408 	struct smb_filename *smb_fname_new = NULL;
1409 	char *old_name = NULL;
1410 	char *new_name = NULL;
1411 	NTSTATUS status;
1412 	WERROR ret;
1413 
1414 	if (driver_directory != NULL) {
1415 		old_name = talloc_asprintf(mem_ctx,
1416 					   "%s/%s/%s",
1417 					   short_architecture,
1418 					   driver_directory,
1419 					   driver_file);
1420 	} else {
1421 		old_name = talloc_asprintf(mem_ctx,
1422 					   "%s/%s",
1423 					   short_architecture,
1424 					   driver_file);
1425 	}
1426 	if (old_name == NULL) {
1427 		return WERR_NOT_ENOUGH_MEMORY;
1428 	}
1429 
1430 	new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1431 				   short_architecture, driver_version, driver_file);
1432 	if (new_name == NULL) {
1433 		TALLOC_FREE(old_name);
1434 		return WERR_NOT_ENOUGH_MEMORY;
1435 	}
1436 
1437 	if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1438 
1439 		status = driver_unix_convert(conn, old_name, &smb_fname_old);
1440 		if (!NT_STATUS_IS_OK(status)) {
1441 			ret = WERR_NOT_ENOUGH_MEMORY;
1442 			goto out;
1443 		}
1444 
1445 		/* Setup a synthetic smb_filename struct */
1446 		smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1447 		if (!smb_fname_new) {
1448 			ret = WERR_NOT_ENOUGH_MEMORY;
1449 			goto out;
1450 		}
1451 
1452 		smb_fname_new->base_name = new_name;
1453 
1454 		DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1455 			  "'%s'\n", smb_fname_old->base_name,
1456 			  smb_fname_new->base_name));
1457 
1458 		status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1459 				   OPENX_FILE_EXISTS_TRUNCATE |
1460 				   OPENX_FILE_CREATE_IF_NOT_EXIST,
1461 				   0, false);
1462 
1463 		if (!NT_STATUS_IS_OK(status)) {
1464 			DEBUG(0,("move_driver_file_to_download_area: Unable "
1465 				 "to rename [%s] to [%s]: %s\n",
1466 				 smb_fname_old->base_name, new_name,
1467 				 nt_errstr(status)));
1468 			ret = WERR_APP_INIT_FAILURE;
1469 			goto out;
1470 		}
1471 	}
1472 
1473 	ret = WERR_OK;
1474  out:
1475 	TALLOC_FREE(smb_fname_old);
1476 	TALLOC_FREE(smb_fname_new);
1477 	return ret;
1478 }
1479 
move_driver_to_download_area(const struct auth_session_info * session_info,const struct spoolss_AddDriverInfoCtr * r,const char * driver_directory)1480 WERROR move_driver_to_download_area(const struct auth_session_info *session_info,
1481 				    const struct spoolss_AddDriverInfoCtr *r,
1482 				    const char *driver_directory)
1483 {
1484 	TALLOC_CTX *frame = talloc_stackframe();
1485 	const struct loadparm_substitution *lp_sub =
1486 		loadparm_s3_global_substitution();
1487 	struct spoolss_AddDriverInfo3 *driver;
1488 	struct spoolss_AddDriverInfo3 converted_driver;
1489 	const char *short_architecture;
1490 	struct smb_filename *smb_dname = NULL;
1491 	char *new_dir = NULL;
1492 	struct conn_struct_tos *c = NULL;
1493 	connection_struct *conn = NULL;
1494 	NTSTATUS nt_status;
1495 	int i;
1496 	int ver = 0;
1497 	char *printdollar = NULL;
1498 	int printdollar_snum;
1499 	WERROR err = WERR_OK;
1500 
1501 	switch (r->level) {
1502 	case 3:
1503 		driver = r->info.info3;
1504 		break;
1505 	case 6:
1506 		convert_level_6_to_level3(&converted_driver, r->info.info6);
1507 		driver = &converted_driver;
1508 		break;
1509 	case 8:
1510 		convert_level_8_to_level3(&converted_driver, r->info.info8);
1511 		driver = &converted_driver;
1512 		break;
1513 	default:
1514 		DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1515 		TALLOC_FREE(frame);
1516 		return WERR_INVALID_LEVEL;
1517 	}
1518 
1519 	short_architecture = get_short_archi(driver->architecture);
1520 	if (!short_architecture) {
1521 		TALLOC_FREE(frame);
1522 		return WERR_UNKNOWN_PRINTER_DRIVER;
1523 	}
1524 
1525 	printdollar_snum = find_service(frame, "print$", &printdollar);
1526 	if (!printdollar) {
1527 		TALLOC_FREE(frame);
1528 		return WERR_NOT_ENOUGH_MEMORY;
1529 	}
1530 	if (printdollar_snum == -1) {
1531 		TALLOC_FREE(frame);
1532 		return WERR_BAD_NET_NAME;
1533 	}
1534 
1535 	nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
1536 					       printdollar_snum,
1537 					       lp_path(frame, lp_sub, printdollar_snum),
1538 					       session_info,
1539 					       &c);
1540 	if (!NT_STATUS_IS_OK(nt_status)) {
1541 		DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1542 			 "returned %s\n", nt_errstr(nt_status)));
1543 		err = ntstatus_to_werror(nt_status);
1544 		TALLOC_FREE(frame);
1545 		return err;
1546 	}
1547 	conn = c->conn;
1548 
1549 	nt_status = set_conn_force_user_group(conn, printdollar_snum);
1550 	if (!NT_STATUS_IS_OK(nt_status)) {
1551 		DEBUG(0, ("failed set force user / group\n"));
1552 		err = ntstatus_to_werror(nt_status);
1553 		goto err_free_conn;
1554 	}
1555 
1556 	if (!become_user_without_service_by_session(conn, session_info)) {
1557 		DEBUG(0, ("failed to become user\n"));
1558 		err = WERR_ACCESS_DENIED;
1559 		goto err_free_conn;
1560 	}
1561 
1562 	new_dir = talloc_asprintf(frame,
1563 				"%s/%d",
1564 				short_architecture,
1565 				driver->version);
1566 	if (!new_dir) {
1567 		err = WERR_NOT_ENOUGH_MEMORY;
1568 		goto err_exit;
1569 	}
1570 	nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1571 	if (!NT_STATUS_IS_OK(nt_status)) {
1572 		err = WERR_NOT_ENOUGH_MEMORY;
1573 		goto err_exit;
1574 	}
1575 
1576 	DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1577 
1578 	nt_status = create_directory(conn, NULL, smb_dname);
1579 	if (!NT_STATUS_IS_OK(nt_status)
1580 	 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1581 		DEBUG(0, ("failed to create driver destination directory: %s\n",
1582 			  nt_errstr(nt_status)));
1583 		err = ntstatus_to_werror(nt_status);
1584 		goto err_exit;
1585 	}
1586 
1587 	/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1588 	 * listed for this driver which has already been moved, skip it (note:
1589 	 * drivers may list the same file name several times. Then check if the
1590 	 * file already exists in archi\version\, if so, check that the version
1591 	 * info (or time stamps if version info is unavailable) is newer (or the
1592 	 * date is later). If it is, move it to archi\version\filexxx.yyy.
1593 	 * Otherwise, delete the file.
1594 	 *
1595 	 * If a file is not moved to archi\version\ because of an error, all the
1596 	 * rest of the 'unmoved' driver files are removed from archi\. If one or
1597 	 * more of the driver's files was already moved to archi\version\, it
1598 	 * potentially leaves the driver in a partially updated state. Version
1599 	 * trauma will most likely occur if an client attempts to use any printer
1600 	 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1601 	 * done is appropriate... later JRR
1602 	 */
1603 
1604 	DEBUG(5,("Moving files now !\n"));
1605 
1606 	if (driver->driver_path && strlen(driver->driver_path)) {
1607 
1608 		err = move_driver_file_to_download_area(frame,
1609 							conn,
1610 							driver->driver_path,
1611 							short_architecture,
1612 							driver->version,
1613 							ver,
1614 							driver_directory);
1615 		if (!W_ERROR_IS_OK(err)) {
1616 			goto err_exit;
1617 		}
1618 	}
1619 
1620 	if (driver->data_file && strlen(driver->data_file)) {
1621 		if (!strequal(driver->data_file, driver->driver_path)) {
1622 
1623 			err = move_driver_file_to_download_area(frame,
1624 								conn,
1625 								driver->data_file,
1626 								short_architecture,
1627 								driver->version,
1628 								ver,
1629 								driver_directory);
1630 			if (!W_ERROR_IS_OK(err)) {
1631 				goto err_exit;
1632 			}
1633 		}
1634 	}
1635 
1636 	if (driver->config_file && strlen(driver->config_file)) {
1637 		if (!strequal(driver->config_file, driver->driver_path) &&
1638 		    !strequal(driver->config_file, driver->data_file)) {
1639 
1640 			err = move_driver_file_to_download_area(frame,
1641 								conn,
1642 								driver->config_file,
1643 								short_architecture,
1644 								driver->version,
1645 								ver,
1646 								driver_directory);
1647 			if (!W_ERROR_IS_OK(err)) {
1648 				goto err_exit;
1649 			}
1650 		}
1651 	}
1652 
1653 	if (driver->help_file && strlen(driver->help_file)) {
1654 		if (!strequal(driver->help_file, driver->driver_path) &&
1655 		    !strequal(driver->help_file, driver->data_file) &&
1656 		    !strequal(driver->help_file, driver->config_file)) {
1657 
1658 			err = move_driver_file_to_download_area(frame,
1659 								conn,
1660 								driver->help_file,
1661 								short_architecture,
1662 								driver->version,
1663 								ver,
1664 								driver_directory);
1665 			if (!W_ERROR_IS_OK(err)) {
1666 				goto err_exit;
1667 			}
1668 		}
1669 	}
1670 
1671 	if (driver->dependent_files && driver->dependent_files->string) {
1672 		for (i=0; driver->dependent_files->string[i]; i++) {
1673 			if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1674 			    !strequal(driver->dependent_files->string[i], driver->data_file) &&
1675 			    !strequal(driver->dependent_files->string[i], driver->config_file) &&
1676 			    !strequal(driver->dependent_files->string[i], driver->help_file)) {
1677 				int j;
1678 				for (j=0; j < i; j++) {
1679 					if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1680 						goto NextDriver;
1681 					}
1682 				}
1683 
1684 				err = move_driver_file_to_download_area(frame,
1685 									conn,
1686 									driver->dependent_files->string[i],
1687 									short_architecture,
1688 									driver->version,
1689 									ver,
1690 									driver_directory);
1691 				if (!W_ERROR_IS_OK(err)) {
1692 					goto err_exit;
1693 				}
1694 			}
1695 		NextDriver: ;
1696 		}
1697 	}
1698 
1699 	err = WERR_OK;
1700  err_exit:
1701 	unbecome_user_without_service();
1702  err_free_conn:
1703 	TALLOC_FREE(frame);
1704 	return err;
1705 }
1706 
1707 /****************************************************************************
1708   Determine whether or not a particular driver is currently assigned
1709   to a printer
1710 ****************************************************************************/
1711 
printer_driver_in_use(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * b,const struct spoolss_DriverInfo8 * r)1712 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1713 			   struct dcerpc_binding_handle *b,
1714 			   const struct spoolss_DriverInfo8 *r)
1715 {
1716 	const struct loadparm_substitution *lp_sub =
1717 		loadparm_s3_global_substitution();
1718 	int snum;
1719 	int n_services = lp_numservices();
1720 	bool in_use = false;
1721 	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1722 	WERROR result;
1723 
1724 	if (!r) {
1725 		return false;
1726 	}
1727 
1728 	DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1729 
1730 	/* loop through the printers.tdb and check for the drivername */
1731 
1732 	for (snum=0; snum<n_services && !in_use; snum++) {
1733 		if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1734 			continue;
1735 		}
1736 
1737 		result = winreg_get_printer(mem_ctx, b,
1738 					    lp_servicename(talloc_tos(), lp_sub, snum),
1739 					    &pinfo2);
1740 		if (!W_ERROR_IS_OK(result)) {
1741 			continue; /* skip */
1742 		}
1743 
1744 		if (strequal(r->driver_name, pinfo2->drivername)) {
1745 			in_use = true;
1746 		}
1747 
1748 		TALLOC_FREE(pinfo2);
1749 	}
1750 
1751 	DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1752 
1753 	if ( in_use ) {
1754 		struct spoolss_DriverInfo8 *driver = NULL;
1755 		WERROR werr;
1756 
1757 		DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1758 
1759 		/* we can still remove the driver if there is one of
1760 		   "Windows NT x86" version 2 or 3 left */
1761 
1762 		if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1763 			if (r->version == 2) {
1764 				werr = winreg_get_driver(mem_ctx, b,
1765 							 r->architecture,
1766 							 r->driver_name,
1767 							 3, &driver);
1768 			} else if (r->version == 3) {
1769 				werr = winreg_get_driver(mem_ctx, b,
1770 							 r->architecture,
1771 							 r->driver_name,
1772 							 2, &driver);
1773 			} else {
1774 				DBG_ERR("Unknown driver version (%d)\n",
1775 					r->version);
1776 				werr = WERR_UNKNOWN_PRINTER_DRIVER;
1777 			}
1778 		} else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1779 			werr = winreg_get_driver(mem_ctx, b,
1780 						 SPOOLSS_ARCHITECTURE_NT_X86,
1781 						 r->driver_name,
1782 						 DRIVER_ANY_VERSION,
1783 						 &driver);
1784 		} else {
1785 			DBG_ERR("Unknown driver architecture: %s\n",
1786 				r->architecture);
1787 			werr = WERR_UNKNOWN_PRINTER_DRIVER;
1788 		}
1789 
1790 		/* now check the error code */
1791 
1792 		if ( W_ERROR_IS_OK(werr) ) {
1793 			/* it's ok to remove the driver, we have other architctures left */
1794 			in_use = false;
1795 			talloc_free(driver);
1796 		}
1797 	}
1798 
1799 	/* report that the driver is not in use by default */
1800 
1801 	return in_use;
1802 }
1803 
1804 
1805 /**********************************************************************
1806  Check to see if a ogiven file is in use by *info
1807  *********************************************************************/
1808 
drv_file_in_use(const char * file,const struct spoolss_DriverInfo8 * info)1809 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1810 {
1811 	int i = 0;
1812 
1813 	if ( !info )
1814 		return False;
1815 
1816 	/* mz: skip files that are in the list but already deleted */
1817 	if (!file || !file[0]) {
1818 		return false;
1819 	}
1820 
1821 	if (strequal(file, info->driver_path))
1822 		return True;
1823 
1824 	if (strequal(file, info->data_file))
1825 		return True;
1826 
1827 	if (strequal(file, info->config_file))
1828 		return True;
1829 
1830 	if (strequal(file, info->help_file))
1831 		return True;
1832 
1833 	/* see of there are any dependent files to examine */
1834 
1835 	if (!info->dependent_files)
1836 		return False;
1837 
1838 	while (info->dependent_files[i] && *info->dependent_files[i]) {
1839 		if (strequal(file, info->dependent_files[i]))
1840 			return True;
1841 		i++;
1842 	}
1843 
1844 	return False;
1845 
1846 }
1847 
1848 /**********************************************************************
1849  Utility function to remove the dependent file pointed to by the
1850  input parameter from the list
1851  *********************************************************************/
1852 
trim_dependent_file(TALLOC_CTX * mem_ctx,const char ** files,int idx)1853 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1854 {
1855 
1856 	/* bump everything down a slot */
1857 
1858 	while (files && files[idx+1]) {
1859 		files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1860 		idx++;
1861 	}
1862 
1863 	files[idx] = NULL;
1864 
1865 	return;
1866 }
1867 
1868 /**********************************************************************
1869  Check if any of the files used by src are also used by drv
1870  *********************************************************************/
1871 
trim_overlap_drv_files(TALLOC_CTX * mem_ctx,struct spoolss_DriverInfo8 * src,const struct spoolss_DriverInfo8 * drv)1872 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1873 				   struct spoolss_DriverInfo8 *src,
1874 				   const struct spoolss_DriverInfo8 *drv)
1875 {
1876 	bool 	in_use = False;
1877 	int 	i = 0;
1878 
1879 	if ( !src || !drv )
1880 		return False;
1881 
1882 	/* check each file.  Remove it from the src structure if it overlaps */
1883 
1884 	if (drv_file_in_use(src->driver_path, drv)) {
1885 		in_use = True;
1886 		DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1887 		src->driver_path = talloc_strdup(mem_ctx, "");
1888 		if (!src->driver_path) { return false; }
1889 	}
1890 
1891 	if (drv_file_in_use(src->data_file, drv)) {
1892 		in_use = True;
1893 		DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1894 		src->data_file = talloc_strdup(mem_ctx, "");
1895 		if (!src->data_file) { return false; }
1896 	}
1897 
1898 	if (drv_file_in_use(src->config_file, drv)) {
1899 		in_use = True;
1900 		DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1901 		src->config_file = talloc_strdup(mem_ctx, "");
1902 		if (!src->config_file) { return false; }
1903 	}
1904 
1905 	if (drv_file_in_use(src->help_file, drv)) {
1906 		in_use = True;
1907 		DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1908 		src->help_file = talloc_strdup(mem_ctx, "");
1909 		if (!src->help_file) { return false; }
1910 	}
1911 
1912 	/* are there any dependentfiles to examine? */
1913 
1914 	if (!src->dependent_files)
1915 		return in_use;
1916 
1917 	while (src->dependent_files[i] && *src->dependent_files[i]) {
1918 		if (drv_file_in_use(src->dependent_files[i], drv)) {
1919 			in_use = True;
1920 			DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1921 			trim_dependent_file(mem_ctx, src->dependent_files, i);
1922 		} else
1923 			i++;
1924 	}
1925 
1926 	return in_use;
1927 }
1928 
1929 /****************************************************************************
1930   Determine whether or not a particular driver files are currently being
1931   used by any other driver.
1932 
1933   Return value is True if any files were in use by other drivers
1934   and False otherwise.
1935 
1936   Upon return, *info has been modified to only contain the driver files
1937   which are not in use
1938 
1939   Fix from mz:
1940 
1941   This needs to check all drivers to ensure that all files in use
1942   have been removed from *info, not just the ones in the first
1943   match.
1944 ****************************************************************************/
1945 
printer_driver_files_in_use(TALLOC_CTX * mem_ctx,struct dcerpc_binding_handle * b,struct spoolss_DriverInfo8 * info)1946 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1947 				 struct dcerpc_binding_handle *b,
1948 				 struct spoolss_DriverInfo8 *info)
1949 {
1950 	int 				i;
1951 	uint32_t 				version;
1952 	struct spoolss_DriverInfo8 	*driver;
1953 	bool in_use = false;
1954 	uint32_t num_drivers;
1955 	const char **drivers;
1956 	WERROR result;
1957 
1958 	if ( !info )
1959 		return False;
1960 
1961 	version = info->version;
1962 
1963 	/* loop over all driver versions */
1964 
1965 	DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1966 
1967 	/* get the list of drivers */
1968 
1969 	result = winreg_get_driver_list(mem_ctx, b,
1970 					info->architecture, version,
1971 					&num_drivers, &drivers);
1972 	if (!W_ERROR_IS_OK(result)) {
1973 		return true;
1974 	}
1975 
1976 	DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1977 		     num_drivers, info->architecture, version));
1978 
1979 	/* check each driver for overlap in files */
1980 
1981 	for (i = 0; i < num_drivers; i++) {
1982 		DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1983 
1984 		driver = NULL;
1985 
1986 		result = winreg_get_driver(mem_ctx, b,
1987 					   info->architecture, drivers[i],
1988 					   version, &driver);
1989 		if (!W_ERROR_IS_OK(result)) {
1990 			talloc_free(drivers);
1991 			return True;
1992 		}
1993 
1994 		/* check if d2 uses any files from d1 */
1995 		/* only if this is a different driver than the one being deleted */
1996 
1997 		if (!strequal(info->driver_name, driver->driver_name)) {
1998 			if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1999 				/* mz: Do not instantly return -
2000 				 * we need to ensure this file isn't
2001 				 * also in use by other drivers. */
2002 				in_use = true;
2003 			}
2004 		}
2005 
2006 		talloc_free(driver);
2007 	}
2008 
2009 	talloc_free(drivers);
2010 
2011 	DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2012 
2013 	return in_use;
2014 }
2015 
driver_unlink_internals(connection_struct * conn,const char * short_arch,int vers,const char * fname)2016 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2017 					const char *short_arch,
2018 					int vers,
2019 					const char *fname)
2020 {
2021 	TALLOC_CTX *tmp_ctx = talloc_new(conn);
2022 	struct smb_filename *smb_fname = NULL;
2023 	char *print_dlr_path;
2024 	NTSTATUS status = NT_STATUS_NO_MEMORY;
2025 
2026 	print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2027 					 short_arch, vers, fname);
2028 	if (print_dlr_path == NULL) {
2029 		goto err_out;
2030 	}
2031 
2032 	smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2033 	if (smb_fname == NULL) {
2034 		goto err_out;
2035 	}
2036 
2037 	status = unlink_internals(conn, NULL, 0, smb_fname, false);
2038 err_out:
2039 	talloc_free(tmp_ctx);
2040 	return status;
2041 }
2042 
2043 /****************************************************************************
2044   Actually delete the driver files.  Make sure that
2045   printer_driver_files_in_use() return False before calling
2046   this.
2047 ****************************************************************************/
2048 
delete_driver_files(const struct auth_session_info * session_info,const struct spoolss_DriverInfo8 * r)2049 bool delete_driver_files(const struct auth_session_info *session_info,
2050 			 const struct spoolss_DriverInfo8 *r)
2051 {
2052 	TALLOC_CTX *frame = talloc_stackframe();
2053 	const struct loadparm_substitution *lp_sub =
2054 		loadparm_s3_global_substitution();
2055 	const char *short_arch;
2056 	struct conn_struct_tos *c = NULL;
2057 	connection_struct *conn = NULL;
2058 	NTSTATUS nt_status;
2059 	char *printdollar = NULL;
2060 	int printdollar_snum;
2061 	bool ret = false;
2062 
2063 	if (!r) {
2064 		TALLOC_FREE(frame);
2065 		return false;
2066 	}
2067 
2068 	DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2069 		r->driver_name, r->version));
2070 
2071 	printdollar_snum = find_service(frame, "print$", &printdollar);
2072 	if (!printdollar) {
2073 		TALLOC_FREE(frame);
2074 		return false;
2075 	}
2076 	if (printdollar_snum == -1) {
2077 		TALLOC_FREE(frame);
2078 		return false;
2079 	}
2080 
2081 	nt_status = create_conn_struct_tos_cwd(global_messaging_context(),
2082 					       printdollar_snum,
2083 					       lp_path(frame, lp_sub, printdollar_snum),
2084 					       session_info,
2085 					       &c);
2086 	if (!NT_STATUS_IS_OK(nt_status)) {
2087 		DEBUG(0,("delete_driver_files: create_conn_struct "
2088 			 "returned %s\n", nt_errstr(nt_status)));
2089 		TALLOC_FREE(frame);
2090 		return false;
2091 	}
2092 	conn = c->conn;
2093 
2094 	nt_status = set_conn_force_user_group(conn, printdollar_snum);
2095 	if (!NT_STATUS_IS_OK(nt_status)) {
2096 		DEBUG(0, ("failed set force user / group\n"));
2097 		ret = false;
2098 		goto err_free_conn;
2099 	}
2100 
2101 	if (!become_user_without_service_by_session(conn, session_info)) {
2102 		DEBUG(0, ("failed to become user\n"));
2103 		ret = false;
2104 		goto err_free_conn;
2105 	}
2106 
2107 	if ( !CAN_WRITE(conn) ) {
2108 		DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2109 		ret = false;
2110 		goto err_out;
2111 	}
2112 
2113 	short_arch = get_short_archi(r->architecture);
2114 	if (short_arch == NULL) {
2115 		DEBUG(0, ("bad architecture %s\n", r->architecture));
2116 		ret = false;
2117 		goto err_out;
2118 	}
2119 
2120 	/* now delete the files */
2121 
2122 	if (r->driver_path && r->driver_path[0]) {
2123 		DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2124 		driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2125 	}
2126 
2127 	if (r->config_file && r->config_file[0]) {
2128 		DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2129 		driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2130 	}
2131 
2132 	if (r->data_file && r->data_file[0]) {
2133 		DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2134 		driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2135 	}
2136 
2137 	if (r->help_file && r->help_file[0]) {
2138 		DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2139 		driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2140 	}
2141 
2142 	if (r->dependent_files) {
2143 		int i = 0;
2144 		while (r->dependent_files[i] && r->dependent_files[i][0]) {
2145 			DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2146 			driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2147 			i++;
2148 		}
2149 	}
2150 
2151 	ret = true;
2152  err_out:
2153 	unbecome_user_without_service();
2154  err_free_conn:
2155 	TALLOC_FREE(frame);
2156 	return ret;
2157 }
2158 
2159 /* error code:
2160 	0: everything OK
2161 	1: level not implemented
2162 	2: file doesn't exist
2163 	3: can't allocate memory
2164 	4: can't free memory
2165 	5: non existent struct
2166 */
2167 
2168 /*
2169 	A printer and a printer driver are 2 different things.
2170 	NT manages them separatelly, Samba does the same.
2171 	Why ? Simply because it's easier and it makes sense !
2172 
2173 	Now explanation: You have 3 printers behind your samba server,
2174 	2 of them are the same make and model (laser A and B). But laser B
2175 	has an 3000 sheet feeder and laser A doesn't such an option.
2176 	Your third printer is an old dot-matrix model for the accounting :-).
2177 
2178 	If the /usr/local/samba/lib directory (default dir), you will have
2179 	5 files to describe all of this.
2180 
2181 	3 files for the printers (1 by printer):
2182 		NTprinter_laser A
2183 		NTprinter_laser B
2184 		NTprinter_accounting
2185 	2 files for the drivers (1 for the laser and 1 for the dot matrix)
2186 		NTdriver_printer model X
2187 		NTdriver_printer model Y
2188 
2189 jfm: I should use this comment for the text file to explain
2190 	same thing for the forms BTW.
2191 	Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2192 
2193 */
2194 
2195 /* Convert generic access rights to printer object specific access rights.
2196    It turns out that NT4 security descriptors use generic access rights and
2197    NT5 the object specific ones. */
2198 
map_printer_permissions(struct security_descriptor * sd)2199 void map_printer_permissions(struct security_descriptor *sd)
2200 {
2201 	int i;
2202 
2203 	for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2204 		se_map_generic(&sd->dacl->aces[i].access_mask,
2205 			       &printer_generic_mapping);
2206 	}
2207 }
2208 
map_job_permissions(struct security_descriptor * sd)2209 void map_job_permissions(struct security_descriptor *sd)
2210 {
2211 	int i;
2212 
2213 	for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2214 		se_map_generic(&sd->dacl->aces[i].access_mask,
2215 			       &job_generic_mapping);
2216 	}
2217 }
2218 
2219 
2220 /****************************************************************************
2221  Check a user has permissions to perform the given operation.  We use the
2222  permission constants defined in include/rpc_spoolss.h to check the various
2223  actions we perform when checking printer access.
2224 
2225    PRINTER_ACCESS_ADMINISTER:
2226        print_queue_pause, print_queue_resume, update_printer_sec,
2227        update_printer, spoolss_addprinterex_level_2,
2228        _spoolss_setprinterdata
2229 
2230    PRINTER_ACCESS_USE:
2231        print_job_start
2232 
2233    JOB_ACCESS_ADMINISTER:
2234        print_job_delete, print_job_pause, print_job_resume,
2235        print_queue_purge
2236 
2237   Try access control in the following order (for performance reasons):
2238     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
2239     2)  check security descriptor (bit comparisons in memory)
2240     3)  "printer admins" (may result in numerous calls to winbind)
2241 
2242  ****************************************************************************/
print_access_check(const struct auth_session_info * session_info,struct messaging_context * msg_ctx,int snum,int access_type)2243 WERROR print_access_check(const struct auth_session_info *session_info,
2244 			  struct messaging_context *msg_ctx, int snum,
2245 			  int access_type)
2246 {
2247 	struct spoolss_security_descriptor *secdesc = NULL;
2248 	const struct loadparm_substitution *lp_sub =
2249 		loadparm_s3_global_substitution();
2250 	uint32_t access_granted;
2251 	size_t sd_size;
2252 	NTSTATUS status;
2253 	WERROR result;
2254 	const char *pname;
2255 	TALLOC_CTX *mem_ctx = NULL;
2256 
2257 	/* If user is NULL then use the current_user structure */
2258 
2259 	/* Always allow root or SE_PRINT_OPERATROR to do anything */
2260 
2261 	if ((session_info->unix_token->uid == sec_initial_uid())
2262 	    || security_token_has_privilege(session_info->security_token,
2263 					    SEC_PRIV_PRINT_OPERATOR)) {
2264 		return WERR_OK;
2265 	}
2266 
2267 	/* Get printer name */
2268 
2269 	pname = lp_printername(talloc_tos(), lp_sub, snum);
2270 
2271 	if (!pname || !*pname) {
2272 		return WERR_ACCESS_DENIED;
2273 	}
2274 
2275 	/* Get printer security descriptor */
2276 
2277 	if(!(mem_ctx = talloc_init("print_access_check"))) {
2278 		return WERR_NOT_ENOUGH_MEMORY;
2279 	}
2280 
2281 	result = winreg_get_printer_secdesc_internal(mem_ctx,
2282 					    get_session_info_system(),
2283 					    msg_ctx,
2284 					    pname,
2285 					    &secdesc);
2286 	if (!W_ERROR_IS_OK(result)) {
2287 		talloc_destroy(mem_ctx);
2288 		return WERR_NOT_ENOUGH_MEMORY;
2289 	}
2290 
2291 	if (access_type == JOB_ACCESS_ADMINISTER) {
2292 		struct spoolss_security_descriptor *parent_secdesc = secdesc;
2293 
2294 		/* Create a child security descriptor to check permissions
2295 		   against.  This is because print jobs are child objects
2296 		   objects of a printer. */
2297 		status = se_create_child_secdesc(mem_ctx,
2298 						 &secdesc,
2299 						 &sd_size,
2300 						 parent_secdesc,
2301 						 parent_secdesc->owner_sid,
2302 						 parent_secdesc->group_sid,
2303 						 false);
2304 		if (!NT_STATUS_IS_OK(status)) {
2305 			talloc_destroy(mem_ctx);
2306 			return ntstatus_to_werror(status);
2307 		}
2308 
2309 		map_job_permissions(secdesc);
2310 	} else {
2311 		map_printer_permissions(secdesc);
2312 	}
2313 
2314 	/* Check access */
2315 	status = se_access_check(secdesc, session_info->security_token, access_type,
2316 				 &access_granted);
2317 
2318 	DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2319 
2320 	talloc_destroy(mem_ctx);
2321 
2322 	return ntstatus_to_werror(status);
2323 }
2324 
2325 /****************************************************************************
2326  Check the time parameters allow a print operation.
2327 *****************************************************************************/
2328 
print_time_access_check(const struct auth_session_info * session_info,struct messaging_context * msg_ctx,const char * servicename)2329 bool print_time_access_check(const struct auth_session_info *session_info,
2330 			     struct messaging_context *msg_ctx,
2331 			     const char *servicename)
2332 {
2333 	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2334 	WERROR result;
2335 	bool ok = False;
2336 	time_t now = time(NULL);
2337 	struct tm *t;
2338 	uint32_t mins;
2339 
2340 	result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2341 				    servicename, &pinfo2);
2342 	if (!W_ERROR_IS_OK(result)) {
2343 		return False;
2344 	}
2345 
2346 	if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2347 		ok = True;
2348 	}
2349 
2350 	t = gmtime(&now);
2351 	mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2352 
2353 	if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2354 		ok = True;
2355 	}
2356 
2357 	TALLOC_FREE(pinfo2);
2358 
2359 	if (!ok) {
2360 		errno = EACCES;
2361 	}
2362 
2363 	return ok;
2364 }
2365 
nt_printer_remove(TALLOC_CTX * mem_ctx,const struct auth_session_info * session_info,struct messaging_context * msg_ctx,const char * printer)2366 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2367 			const struct auth_session_info *session_info,
2368 			struct messaging_context *msg_ctx,
2369 			const char *printer)
2370 {
2371 	WERROR result;
2372 
2373 	result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2374 					   printer, "");
2375 	if (!W_ERROR_IS_OK(result)) {
2376 		DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2377 		"%s\n", printer, win_errstr(result)));
2378 	}
2379 }
2380 
nt_printer_add(TALLOC_CTX * mem_ctx,const struct auth_session_info * session_info,struct messaging_context * msg_ctx,const char * printer)2381 void nt_printer_add(TALLOC_CTX *mem_ctx,
2382 		    const struct auth_session_info *session_info,
2383 		    struct messaging_context *msg_ctx,
2384 		    const char *printer)
2385 {
2386 	WERROR result;
2387 
2388 	result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2389 						printer);
2390 	if (!W_ERROR_IS_OK(result)) {
2391 		DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2392 			  printer, win_errstr(result)));
2393 	}
2394 }
2395