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.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
25 #include "printing/nt_printing_tdb.h"
26 #include "printing/nt_printing_migrate.h"
28 #include "registry/reg_objects.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "../librpc/gen_ndr/ndr_spoolss.h"
31 #include "rpc_server/srv_spoolss_util.h"
32 #include "nt_printing.h"
34 #include "../librpc/gen_ndr/netlogon.h"
36 /* Map generic permissions to printer object specific permissions */
38 const struct generic_mapping printer_generic_mapping = {
45 /* Map generic permissions to print server object specific permissions */
47 const struct generic_mapping printserver_generic_mapping = {
54 /* Map generic permissions to job object specific permissions */
56 const struct generic_mapping job_generic_mapping = {
63 static const struct print_architecture_table_node archi_table[]= {
65 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
66 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
67 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
68 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
69 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
70 {"Windows IA64", SPL_ARCH_IA64, 3 },
71 {"Windows x64", SPL_ARCH_X64, 3 },
75 /****************************************************************************
76 Open the NT printing tdbs. Done once before fork().
77 ****************************************************************************/
79 bool nt_printing_init(struct messaging_context *msg_ctx)
83 if (!nt_printing_tdb_upgrade()) {
88 * register callback to handle updating printers as new
89 * drivers are installed
91 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
92 do_drv_upgrade_printer);
94 /* of course, none of the message callbacks matter if you don't
95 tell messages.c that you interested in receiving PRINT_GENERAL
96 msgs. This is done in serverid_register() */
98 if ( lp_security() == SEC_ADS ) {
99 win_rc = check_published_printers(msg_ctx);
100 if (!W_ERROR_IS_OK(win_rc))
101 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
107 /*******************************************************************
108 Function to allow filename parsing "the old way".
109 ********************************************************************/
111 static NTSTATUS driver_unix_convert(connection_struct *conn,
112 const char *old_name,
113 struct smb_filename **smb_fname)
116 TALLOC_CTX *ctx = talloc_tos();
117 char *name = talloc_strdup(ctx, old_name);
120 return NT_STATUS_NO_MEMORY;
123 name = unix_clean_name(ctx, name);
125 return NT_STATUS_NO_MEMORY;
127 trim_string(name,"/","/");
129 status = unix_convert(ctx, conn, name, smb_fname, 0);
130 if (!NT_STATUS_IS_OK(status)) {
131 return NT_STATUS_NO_MEMORY;
137 /****************************************************************************
138 Function to do the mapping between the long architecture name and
140 ****************************************************************************/
142 const char *get_short_archi(const char *long_archi)
146 DEBUG(107,("Getting architecture dependant directory\n"));
149 } while ( (archi_table[i].long_archi!=NULL ) &&
150 StrCaseCmp(long_archi, archi_table[i].long_archi) );
152 if (archi_table[i].long_archi==NULL) {
153 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
157 /* this might be client code - but shouldn't this be an fstrcpy etc? */
159 DEBUGADD(108,("index: [%d]\n", i));
160 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
161 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
163 return archi_table[i].short_archi;
166 /****************************************************************************
167 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
168 There are two case to be covered here: PE (Portable Executable) and NE (New
169 Executable) files. Both files support the same INFO structure, but PE files
170 store the signature in unicode, and NE files store it as !unicode.
171 returns -1 on error, 1 on version info found, and 0 on no version info found.
172 ****************************************************************************/
174 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
180 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
181 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
182 fname, DOS_HEADER_SIZE));
186 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
187 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
188 fname, (unsigned long)byte_count));
189 goto no_version_info;
192 /* Is this really a DOS header? */
193 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
194 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
195 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
196 goto no_version_info;
199 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
200 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
201 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
203 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
204 goto no_version_info;
207 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
208 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
209 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
210 fname, (unsigned long)byte_count));
211 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
212 goto no_version_info;
215 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
216 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
217 unsigned int num_sections;
218 unsigned int section_table_bytes;
220 /* Just skip over optional header to get to section table */
221 if (SMB_VFS_LSEEK(fsp,
222 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
223 SEEK_CUR) == (SMB_OFF_T)-1) {
224 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
229 /* get the section table */
230 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
231 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
232 if (section_table_bytes == 0)
236 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
237 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
238 fname, section_table_bytes));
242 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
243 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
244 fname, (unsigned long)byte_count));
248 /* Iterate the section table looking for the resource section ".rsrc" */
249 for (i = 0; i < num_sections; i++) {
250 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
252 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
253 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
254 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
256 if (section_bytes == 0)
260 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
261 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
262 fname, section_bytes));
266 /* Seek to the start of the .rsrc section info */
267 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
268 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
273 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
274 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
275 fname, (unsigned long)byte_count));
279 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
282 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
283 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
284 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
285 /* Align to next long address */
286 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
288 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
289 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
290 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
292 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
293 fname, *major, *minor,
294 (*major>>16)&0xffff, *major&0xffff,
295 (*minor>>16)&0xffff, *minor&0xffff));
304 /* Version info not found, fall back to origin date/time */
305 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
309 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
310 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
311 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
312 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
313 /* At this point, we assume the file is in error. It still could be somthing
314 * else besides a NE file, but it unlikely at this point. */
318 /* Allocate a bit more space to speed up things */
320 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
321 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
322 fname, PE_HEADER_SIZE));
326 /* This is a HACK! I got tired of trying to sort through the messy
327 * 'NE' file format. If anyone wants to clean this up please have at
328 * it, but this works. 'NE' files will eventually fade away. JRR */
329 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
330 /* Cover case that should not occur in a well formed 'NE' .dll file */
331 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
333 for(i=0; i<byte_count; i++) {
334 /* Fast skip past data that can't possibly match */
335 if (buf[i] != 'V') continue;
337 /* Potential match data crosses buf boundry, move it to beginning
338 * of buf, and fill the buf with as much as it will hold. */
339 if (i>byte_count-VS_VERSION_INFO_SIZE) {
342 memcpy(buf, &buf[i], byte_count-i);
343 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
344 (byte_count-i))) < 0) {
346 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
351 byte_count = bc + (byte_count - i);
352 if (byte_count<VS_VERSION_INFO_SIZE) break;
357 /* Check that the full signature string and the magic number that
358 * follows exist (not a perfect solution, but the chances that this
359 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
360 * twice, as it is simpler to read the code. */
361 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
362 /* Compute skip alignment to next long address */
363 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
364 sizeof(VS_SIGNATURE)) & 3;
365 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
367 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
368 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
369 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
370 fname, *major, *minor,
371 (*major>>16)&0xffff, *major&0xffff,
372 (*minor>>16)&0xffff, *minor&0xffff));
379 /* Version info not found, fall back to origin date/time */
380 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
385 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
386 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
387 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
398 /****************************************************************************
399 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
400 share one or more files. During the MS installation process files are checked
401 to insure that only a newer version of a shared file is installed over an
402 older version. There are several possibilities for this comparison. If there
403 is no previous version, the new one is newer (obviously). If either file is
404 missing the version info structure, compare the creation date (on Unix use
405 the modification date). Otherwise chose the numerically larger version number.
406 ****************************************************************************/
408 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
410 bool use_version = true;
414 time_t new_create_time;
418 time_t old_create_time;
420 struct smb_filename *smb_fname = NULL;
421 files_struct *fsp = NULL;
427 SET_STAT_INVALID(st);
428 new_create_time = (time_t)0;
429 old_create_time = (time_t)0;
431 /* Get file version info (if available) for previous file (if it exists) */
432 status = driver_unix_convert(conn, old_file, &smb_fname);
433 if (!NT_STATUS_IS_OK(status)) {
437 status = SMB_VFS_CREATE_FILE(
440 0, /* root_dir_fid */
441 smb_fname, /* fname */
442 FILE_GENERIC_READ, /* access_mask */
443 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
444 FILE_OPEN, /* create_disposition*/
445 0, /* create_options */
446 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
447 INTERNAL_OPEN_ONLY, /* oplock_request */
448 0, /* allocation_size */
449 0, /* private_flags */
455 if (!NT_STATUS_IS_OK(status)) {
456 /* Old file not found, so by definition new file is in fact newer */
457 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
458 "errno = %d\n", smb_fname_str_dbg(smb_fname),
464 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
470 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
473 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
476 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
477 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
478 (long)old_create_time));
481 close_file(NULL, fsp, NORMAL_CLOSE);
484 /* Get file version info (if available) for new file */
485 status = driver_unix_convert(conn, new_file, &smb_fname);
486 if (!NT_STATUS_IS_OK(status)) {
490 status = SMB_VFS_CREATE_FILE(
493 0, /* root_dir_fid */
494 smb_fname, /* fname */
495 FILE_GENERIC_READ, /* access_mask */
496 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
497 FILE_OPEN, /* create_disposition*/
498 0, /* create_options */
499 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
500 INTERNAL_OPEN_ONLY, /* oplock_request */
501 0, /* allocation_size */
502 0, /* private_flags */
508 if (!NT_STATUS_IS_OK(status)) {
509 /* New file not found, this shouldn't occur if the caller did its job */
510 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
511 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
515 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
521 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
524 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
527 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
528 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
529 (long)new_create_time));
532 close_file(NULL, fsp, NORMAL_CLOSE);
535 if (use_version && (new_major != old_major || new_minor != old_minor)) {
536 /* Compare versions and choose the larger version number */
537 if (new_major > old_major ||
538 (new_major == old_major && new_minor > old_minor)) {
540 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
545 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
551 /* Compare modification time/dates and choose the newest time/date */
552 if (new_create_time > old_create_time) {
553 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
558 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
566 close_file(NULL, fsp, NORMAL_CLOSE);
569 TALLOC_FREE(smb_fname);
573 /****************************************************************************
574 Determine the correct cVersion associated with an architecture and driver
575 ****************************************************************************/
576 static uint32 get_correct_cversion(struct pipes_struct *p,
577 const char *architecture,
578 const char *driverpath_in,
583 struct smb_filename *smb_fname = NULL;
584 char *driverpath = NULL;
585 files_struct *fsp = NULL;
586 connection_struct *conn = NULL;
590 int printdollar_snum;
592 *perr = WERR_INVALID_PARAM;
594 /* If architecture is Windows 95/98/ME, the version is always 0. */
595 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
596 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
601 /* If architecture is Windows x64, the version is always 3. */
602 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
603 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
608 fstrcpy(printdollar, "print$");
610 printdollar_snum = find_service(printdollar);
611 if (printdollar_snum == -1) {
612 *perr = WERR_NO_SUCH_SHARE;
616 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
617 lp_pathname(printdollar_snum),
618 p->server_info, &oldcwd);
619 if (!NT_STATUS_IS_OK(nt_status)) {
620 DEBUG(0,("get_correct_cversion: create_conn_struct "
621 "returned %s\n", nt_errstr(nt_status)));
622 *perr = ntstatus_to_werror(nt_status);
626 /* Open the driver file (Portable Executable format) and determine the
627 * deriver the cversion. */
628 driverpath = talloc_asprintf(talloc_tos(),
637 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
638 if (!NT_STATUS_IS_OK(nt_status)) {
639 *perr = ntstatus_to_werror(nt_status);
643 nt_status = vfs_file_exist(conn, smb_fname);
644 if (!NT_STATUS_IS_OK(nt_status)) {
645 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
646 *perr = WERR_BADFILE;
650 status = SMB_VFS_CREATE_FILE(
653 0, /* root_dir_fid */
654 smb_fname, /* fname */
655 FILE_GENERIC_READ, /* access_mask */
656 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
657 FILE_OPEN, /* create_disposition*/
658 0, /* create_options */
659 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
660 INTERNAL_OPEN_ONLY, /* oplock_request */
661 0, /* private_flags */
662 0, /* allocation_size */
668 if (!NT_STATUS_IS_OK(status)) {
669 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
670 "%d\n", smb_fname_str_dbg(smb_fname), errno));
671 *perr = WERR_ACCESS_DENIED;
678 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
679 if (ret == -1) goto error_exit;
682 DEBUG(6,("get_correct_cversion: Version info not "
684 smb_fname_str_dbg(smb_fname)));
689 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
690 * for more details. Version in this case is not just the version of the
691 * file, but the version in the sense of kernal mode (2) vs. user mode
692 * (3) drivers. Other bits of the version fields are the version info.
695 cversion = major & 0x0000ffff;
697 case 2: /* WinNT drivers */
698 case 3: /* Win2K drivers */
702 DEBUG(6,("get_correct_cversion: cversion "
703 "invalid [%s] cversion = %d\n",
704 smb_fname_str_dbg(smb_fname),
709 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
710 " = 0x%x minor = 0x%x\n",
711 smb_fname_str_dbg(smb_fname), major, minor));
714 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
715 smb_fname_str_dbg(smb_fname), cversion));
722 TALLOC_FREE(smb_fname);
724 close_file(NULL, fsp, NORMAL_CLOSE);
727 vfs_ChDir(conn, oldcwd);
730 if (cversion != -1) {
736 /****************************************************************************
737 ****************************************************************************/
739 #define strip_driver_path(_mem_ctx, _element) do { \
740 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
741 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
742 W_ERROR_HAVE_NO_MEMORY((_element)); \
746 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
747 struct pipes_struct *rpc_pipe,
748 const char *architecture,
749 const char **driver_path,
750 const char **data_file,
751 const char **config_file,
752 const char **help_file,
753 struct spoolss_StringArray *dependent_files,
756 const char *short_architecture;
761 if (!*driver_path || !*data_file || !*config_file) {
762 return WERR_INVALID_PARAM;
765 /* clean up the driver name.
766 * we can get .\driver.dll
767 * or worse c:\windows\system\driver.dll !
769 /* using an intermediate string to not have overlaping memcpy()'s */
771 strip_driver_path(mem_ctx, *driver_path);
772 strip_driver_path(mem_ctx, *data_file);
773 strip_driver_path(mem_ctx, *config_file);
775 strip_driver_path(mem_ctx, *help_file);
778 if (dependent_files && dependent_files->string) {
779 for (i=0; dependent_files->string[i]; i++) {
780 strip_driver_path(mem_ctx, dependent_files->string[i]);
784 short_architecture = get_short_archi(architecture);
785 if (!short_architecture) {
786 return WERR_UNKNOWN_PRINTER_DRIVER;
789 /* jfm:7/16/2000 the client always sends the cversion=0.
790 * The server should check which version the driver is by reading
791 * the PE header of driver->driverpath.
793 * For Windows 95/98 the version is 0 (so the value sent is correct)
794 * For Windows NT (the architecture doesn't matter)
796 * NT 3.5/3.51: cversion=1
801 *version = get_correct_cversion(rpc_pipe, short_architecture,
803 if (*version == -1) {
810 /****************************************************************************
811 ****************************************************************************/
813 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
814 struct pipes_struct *rpc_pipe,
815 struct spoolss_AddDriverInfoCtr *r)
819 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
820 r->info.info3->architecture,
821 &r->info.info3->driver_path,
822 &r->info.info3->data_file,
823 &r->info.info3->config_file,
824 &r->info.info3->help_file,
825 r->info.info3->dependent_files,
826 &r->info.info3->version);
828 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
829 r->info.info6->architecture,
830 &r->info.info6->driver_path,
831 &r->info.info6->data_file,
832 &r->info.info6->config_file,
833 &r->info.info6->help_file,
834 r->info.info6->dependent_files,
835 &r->info.info6->version);
837 return WERR_NOT_SUPPORTED;
841 /****************************************************************************
842 This function sucks and should be replaced. JRA.
843 ****************************************************************************/
845 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
846 const struct spoolss_AddDriverInfo6 *src)
848 dst->version = src->version;
850 dst->driver_name = src->driver_name;
851 dst->architecture = src->architecture;
852 dst->driver_path = src->driver_path;
853 dst->data_file = src->data_file;
854 dst->config_file = src->config_file;
855 dst->help_file = src->help_file;
856 dst->monitor_name = src->monitor_name;
857 dst->default_datatype = src->default_datatype;
858 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
859 dst->dependent_files = src->dependent_files;
862 /****************************************************************************
863 ****************************************************************************/
865 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
866 connection_struct *conn,
867 const char *driver_file,
868 const char *short_architecture,
869 uint32_t driver_version,
872 struct smb_filename *smb_fname_old = NULL;
873 struct smb_filename *smb_fname_new = NULL;
874 char *old_name = NULL;
875 char *new_name = NULL;
879 old_name = talloc_asprintf(mem_ctx, "%s/%s",
880 short_architecture, driver_file);
881 W_ERROR_HAVE_NO_MEMORY(old_name);
883 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
884 short_architecture, driver_version, driver_file);
885 if (new_name == NULL) {
886 TALLOC_FREE(old_name);
890 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
892 status = driver_unix_convert(conn, old_name, &smb_fname_old);
893 if (!NT_STATUS_IS_OK(status)) {
898 /* Setup a synthetic smb_filename struct */
899 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
900 if (!smb_fname_new) {
905 smb_fname_new->base_name = new_name;
907 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
908 "'%s'\n", smb_fname_old->base_name,
909 smb_fname_new->base_name));
911 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
912 OPENX_FILE_EXISTS_TRUNCATE |
913 OPENX_FILE_CREATE_IF_NOT_EXIST,
916 if (!NT_STATUS_IS_OK(status)) {
917 DEBUG(0,("move_driver_file_to_download_area: Unable "
918 "to rename [%s] to [%s]: %s\n",
919 smb_fname_old->base_name, new_name,
921 ret = WERR_ACCESS_DENIED;
928 TALLOC_FREE(smb_fname_old);
929 TALLOC_FREE(smb_fname_new);
933 WERROR move_driver_to_download_area(struct pipes_struct *p,
934 struct spoolss_AddDriverInfoCtr *r,
937 struct spoolss_AddDriverInfo3 *driver;
938 struct spoolss_AddDriverInfo3 converted_driver;
939 const char *short_architecture;
940 struct smb_filename *smb_dname = NULL;
941 char *new_dir = NULL;
942 connection_struct *conn = NULL;
945 TALLOC_CTX *ctx = talloc_tos();
949 int printdollar_snum;
955 driver = r->info.info3;
958 convert_level_6_to_level3(&converted_driver, r->info.info6);
959 driver = &converted_driver;
962 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
963 return WERR_UNKNOWN_LEVEL;
966 short_architecture = get_short_archi(driver->architecture);
967 if (!short_architecture) {
968 return WERR_UNKNOWN_PRINTER_DRIVER;
971 fstrcpy(printdollar, "print$");
973 printdollar_snum = find_service(printdollar);
974 if (printdollar_snum == -1) {
975 *perr = WERR_NO_SUCH_SHARE;
976 return WERR_NO_SUCH_SHARE;
979 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
980 lp_pathname(printdollar_snum),
981 p->server_info, &oldcwd);
982 if (!NT_STATUS_IS_OK(nt_status)) {
983 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
984 "returned %s\n", nt_errstr(nt_status)));
985 *perr = ntstatus_to_werror(nt_status);
989 new_dir = talloc_asprintf(ctx,
997 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
998 if (!NT_STATUS_IS_OK(nt_status)) {
1003 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1005 create_directory(conn, NULL, smb_dname);
1007 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1008 * listed for this driver which has already been moved, skip it (note:
1009 * drivers may list the same file name several times. Then check if the
1010 * file already exists in archi\version\, if so, check that the version
1011 * info (or time stamps if version info is unavailable) is newer (or the
1012 * date is later). If it is, move it to archi\version\filexxx.yyy.
1013 * Otherwise, delete the file.
1015 * If a file is not moved to archi\version\ because of an error, all the
1016 * rest of the 'unmoved' driver files are removed from archi\. If one or
1017 * more of the driver's files was already moved to archi\version\, it
1018 * potentially leaves the driver in a partially updated state. Version
1019 * trauma will most likely occur if an client attempts to use any printer
1020 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1021 * done is appropriate... later JRR
1024 DEBUG(5,("Moving files now !\n"));
1026 if (driver->driver_path && strlen(driver->driver_path)) {
1028 *perr = move_driver_file_to_download_area(ctx,
1030 driver->driver_path,
1034 if (!W_ERROR_IS_OK(*perr)) {
1035 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1042 if (driver->data_file && strlen(driver->data_file)) {
1043 if (!strequal(driver->data_file, driver->driver_path)) {
1045 *perr = move_driver_file_to_download_area(ctx,
1051 if (!W_ERROR_IS_OK(*perr)) {
1052 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1060 if (driver->config_file && strlen(driver->config_file)) {
1061 if (!strequal(driver->config_file, driver->driver_path) &&
1062 !strequal(driver->config_file, driver->data_file)) {
1064 *perr = move_driver_file_to_download_area(ctx,
1066 driver->config_file,
1070 if (!W_ERROR_IS_OK(*perr)) {
1071 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1079 if (driver->help_file && strlen(driver->help_file)) {
1080 if (!strequal(driver->help_file, driver->driver_path) &&
1081 !strequal(driver->help_file, driver->data_file) &&
1082 !strequal(driver->help_file, driver->config_file)) {
1084 *perr = move_driver_file_to_download_area(ctx,
1090 if (!W_ERROR_IS_OK(*perr)) {
1091 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1099 if (driver->dependent_files && driver->dependent_files->string) {
1100 for (i=0; driver->dependent_files->string[i]; i++) {
1101 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1102 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1103 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1104 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1106 for (j=0; j < i; j++) {
1107 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1112 *perr = move_driver_file_to_download_area(ctx,
1114 driver->dependent_files->string[i],
1118 if (!W_ERROR_IS_OK(*perr)) {
1119 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1130 TALLOC_FREE(smb_dname);
1133 vfs_ChDir(conn, oldcwd);
1137 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1141 return WERR_UNKNOWN_PRINTER_DRIVER;
1146 /****************************************************************************
1147 Create and allocate a default devicemode.
1148 ****************************************************************************/
1150 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1151 const char *devicename,
1152 struct spoolss_DeviceMode **devmode)
1154 struct spoolss_DeviceMode *dm;
1157 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1162 dname = talloc_asprintf(dm, "%s", devicename);
1163 if (dname == NULL) {
1166 if (strlen(dname) > MAXDEVICENAME) {
1167 dname[MAXDEVICENAME] = '\0';
1169 dm->devicename = dname;
1171 dm->formname = talloc_strdup(dm, "Letter");
1172 if (dm->formname == NULL) {
1176 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1177 dm->driverversion = 0x0400;
1179 dm->__driverextra_length = 0;
1180 dm->fields = DEVMODE_FORMNAME |
1182 DEVMODE_PRINTQUALITY |
1183 DEVMODE_DEFAULTSOURCE |
1187 DEVMODE_ORIENTATION;
1188 dm->orientation = DMORIENT_PORTRAIT;
1189 dm->papersize = DMPAPER_LETTER;
1190 dm->paperlength = 0;
1194 dm->defaultsource = DMBIN_FORMSOURCE;
1195 dm->printquality = DMRES_HIGH; /* 0x0258 */
1196 dm->color = DMRES_MONOCHROME;
1197 dm->duplex = DMDUP_SIMPLEX;
1198 dm->yresolution = 0;
1199 dm->ttoption = DMTT_SUBDEV;
1200 dm->collate = DMCOLLATE_FALSE;
1210 dm->displayflags = 0;
1211 dm->displayfrequency = 0;
1214 dm->panningwidth = 0;
1215 dm->panningheight = 0;
1217 dm->driverextra_data.data = NULL;
1218 dm->driverextra_data.length = 0;
1224 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1225 struct spoolss_security_descriptor **secdesc)
1227 struct security_ace ace[7]; /* max number of ace entries */
1230 struct security_acl *psa = NULL;
1231 struct security_descriptor *psd = NULL;
1232 struct dom_sid adm_sid;
1235 /* Create an ACE where Everyone is allowed to print */
1237 sa = PRINTER_ACE_PRINT;
1238 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1239 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1241 /* Add the domain admins group if we are a DC */
1244 struct dom_sid domadmins_sid;
1246 sid_compose(&domadmins_sid, get_global_sam_sid(),
1249 sa = PRINTER_ACE_FULL_CONTROL;
1250 init_sec_ace(&ace[i++], &domadmins_sid,
1251 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1252 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1253 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1254 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1256 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1257 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1259 sa = PRINTER_ACE_FULL_CONTROL;
1260 init_sec_ace(&ace[i++], &adm_sid,
1261 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1262 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1263 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1264 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1267 /* add BUILTIN\Administrators as FULL CONTROL */
1269 sa = PRINTER_ACE_FULL_CONTROL;
1270 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1271 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1272 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1273 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1274 SEC_ACE_TYPE_ACCESS_ALLOWED,
1275 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1277 /* add BUILTIN\Print Operators as FULL CONTROL */
1279 sa = PRINTER_ACE_FULL_CONTROL;
1280 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1281 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1282 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1283 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1284 SEC_ACE_TYPE_ACCESS_ALLOWED,
1285 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1287 /* Make the security descriptor owned by the BUILTIN\Administrators */
1289 /* The ACL revision number in rpc_secdesc.h differs from the one
1290 created by NT when setting ACE entries in printer
1291 descriptors. NT4 complains about the property being edited by a
1294 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1295 psd = make_sec_desc(mem_ctx,
1297 SEC_DESC_SELF_RELATIVE,
1298 &global_sid_Builtin_Administrators,
1299 &global_sid_Builtin_Administrators,
1306 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1310 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1311 (unsigned int)sd_size));
1318 /****************************************************************************
1319 ***************************************************************************/
1321 static char *win_driver;
1322 static char *os2_driver;
1324 static const char *get_win_driver(void)
1326 if (win_driver == NULL) {
1332 static const char *get_os2_driver(void)
1334 if (os2_driver == NULL) {
1340 static bool set_driver_mapping(const char *from, const char *to)
1342 SAFE_FREE(win_driver);
1343 SAFE_FREE(os2_driver);
1345 win_driver = SMB_STRDUP(from);
1346 os2_driver = SMB_STRDUP(to);
1348 if (win_driver == NULL || os2_driver == NULL) {
1349 SAFE_FREE(win_driver);
1350 SAFE_FREE(os2_driver);
1359 * @brief Map a Windows driver to a OS/2 driver.
1361 * @param[in] mem_ctx The memory context to use.
1363 * @param[in,out] pdrivername The drivername of Windows to remap.
1365 * @return WERR_OK on success, a corresponding WERROR on failure.
1367 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1369 const char *mapfile = lp_os2_driver_map();
1370 char **lines = NULL;
1371 const char *drivername;
1375 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1376 return WERR_INVALID_PARAMETER;
1379 drivername = *pdrivername;
1381 if (mapfile[0] == '\0') {
1382 return WERR_BADFILE;
1385 if (strequal(drivername, get_win_driver())) {
1386 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1387 drivername, get_os2_driver()));
1388 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1389 if (drivername == NULL) {
1392 *pdrivername = drivername;
1396 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1397 if (numlines == 0 || lines == NULL) {
1398 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1403 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1405 for( i = 0; i < numlines; i++) {
1406 char *nt_name = lines[i];
1407 char *os2_name = strchr(nt_name, '=');
1409 if (os2_name == NULL) {
1415 while (isspace(*nt_name)) {
1419 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1424 int l = strlen(nt_name);
1425 while (l && isspace(nt_name[l - 1])) {
1431 while (isspace(*os2_name)) {
1436 int l = strlen(os2_name);
1437 while (l && isspace(os2_name[l-1])) {
1443 if (strequal(nt_name, drivername)) {
1444 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1445 set_driver_mapping(drivername, os2_name);
1446 drivername = talloc_strdup(mem_ctx, os2_name);
1448 if (drivername == NULL) {
1451 *pdrivername = drivername;
1460 /****************************************************************************
1461 ****************************************************************************/
1463 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1464 struct spoolss_DriverInfo8 *_info8)
1466 struct spoolss_DriverInfo8 info8;
1472 info8.version = r->info.info3->version;
1473 info8.driver_name = r->info.info3->driver_name;
1474 info8.architecture = r->info.info3->architecture;
1475 info8.driver_path = r->info.info3->driver_path;
1476 info8.data_file = r->info.info3->data_file;
1477 info8.config_file = r->info.info3->config_file;
1478 info8.help_file = r->info.info3->help_file;
1479 info8.monitor_name = r->info.info3->monitor_name;
1480 info8.default_datatype = r->info.info3->default_datatype;
1481 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1482 info8.dependent_files = r->info.info3->dependent_files->string;
1486 info8.version = r->info.info6->version;
1487 info8.driver_name = r->info.info6->driver_name;
1488 info8.architecture = r->info.info6->architecture;
1489 info8.driver_path = r->info.info6->driver_path;
1490 info8.data_file = r->info.info6->data_file;
1491 info8.config_file = r->info.info6->config_file;
1492 info8.help_file = r->info.info6->help_file;
1493 info8.monitor_name = r->info.info6->monitor_name;
1494 info8.default_datatype = r->info.info6->default_datatype;
1495 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1496 info8.dependent_files = r->info.info6->dependent_files->string;
1498 info8.driver_date = r->info.info6->driver_date;
1499 info8.driver_version = r->info.info6->driver_version;
1500 info8.manufacturer_name = r->info.info6->manufacturer_name;
1501 info8.manufacturer_url = r->info.info6->manufacturer_url;
1502 info8.hardware_id = r->info.info6->hardware_id;
1503 info8.provider = r->info.info6->provider;
1506 info8.version = r->info.info8->version;
1507 info8.driver_name = r->info.info8->driver_name;
1508 info8.architecture = r->info.info8->architecture;
1509 info8.driver_path = r->info.info8->driver_path;
1510 info8.data_file = r->info.info8->data_file;
1511 info8.config_file = r->info.info8->config_file;
1512 info8.help_file = r->info.info8->help_file;
1513 info8.monitor_name = r->info.info8->monitor_name;
1514 info8.default_datatype = r->info.info8->default_datatype;
1515 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1516 info8.dependent_files = r->info.info8->dependent_files->string;
1518 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1519 info8.previous_names = r->info.info8->previous_names->string;
1521 info8.driver_date = r->info.info8->driver_date;
1522 info8.driver_version = r->info.info8->driver_version;
1523 info8.manufacturer_name = r->info.info8->manufacturer_name;
1524 info8.manufacturer_url = r->info.info8->manufacturer_url;
1525 info8.hardware_id = r->info.info8->hardware_id;
1526 info8.provider = r->info.info8->provider;
1527 info8.print_processor = r->info.info8->print_processor;
1528 info8.vendor_setup = r->info.info8->vendor_setup;
1529 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1530 info8.color_profiles = r->info.info8->color_profiles->string;
1532 info8.inf_path = r->info.info8->inf_path;
1533 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1534 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1535 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1537 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1538 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1550 /****************************************************************************
1551 Determine whether or not a particular driver is currently assigned
1553 ****************************************************************************/
1555 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1556 struct auth_serversupplied_info *server_info,
1557 struct messaging_context *msg_ctx,
1558 const struct spoolss_DriverInfo8 *r)
1561 int n_services = lp_numservices();
1562 bool in_use = False;
1563 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1570 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1572 /* loop through the printers.tdb and check for the drivername */
1574 for (snum=0; snum<n_services && !in_use; snum++) {
1575 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1579 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
1580 NULL, lp_servicename(snum),
1582 if (!W_ERROR_IS_OK(result)) {
1583 continue; /* skip */
1586 if (strequal(r->driver_name, pinfo2->drivername)) {
1590 TALLOC_FREE(pinfo2);
1593 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1596 struct spoolss_DriverInfo8 *driver;
1599 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1601 /* we can still remove the driver if there is one of
1602 "Windows NT x86" version 2 or 3 left */
1604 if (!strequal("Windows NT x86", r->architecture)) {
1605 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1610 } else if (r->version == 2) {
1611 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1615 } else if (r->version == 3) {
1616 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1621 DEBUG(0, ("printer_driver_in_use: ERROR!"
1622 " unknown driver version (%d)\n",
1624 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1627 /* now check the error code */
1629 if ( W_ERROR_IS_OK(werr) ) {
1630 /* it's ok to remove the driver, we have other architctures left */
1632 talloc_free(driver);
1636 /* report that the driver is not in use by default */
1642 /**********************************************************************
1643 Check to see if a ogiven file is in use by *info
1644 *********************************************************************/
1646 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1653 /* mz: skip files that are in the list but already deleted */
1654 if (!file || !file[0]) {
1658 if (strequal(file, info->driver_path))
1661 if (strequal(file, info->data_file))
1664 if (strequal(file, info->config_file))
1667 if (strequal(file, info->help_file))
1670 /* see of there are any dependent files to examine */
1672 if (!info->dependent_files)
1675 while (info->dependent_files[i] && *info->dependent_files[i]) {
1676 if (strequal(file, info->dependent_files[i]))
1685 /**********************************************************************
1686 Utility function to remove the dependent file pointed to by the
1687 input parameter from the list
1688 *********************************************************************/
1690 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1693 /* bump everything down a slot */
1695 while (files && files[idx+1]) {
1696 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1705 /**********************************************************************
1706 Check if any of the files used by src are also used by drv
1707 *********************************************************************/
1709 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1710 struct spoolss_DriverInfo8 *src,
1711 const struct spoolss_DriverInfo8 *drv)
1713 bool in_use = False;
1719 /* check each file. Remove it from the src structure if it overlaps */
1721 if (drv_file_in_use(src->driver_path, drv)) {
1723 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1724 src->driver_path = talloc_strdup(mem_ctx, "");
1725 if (!src->driver_path) { return false; }
1728 if (drv_file_in_use(src->data_file, drv)) {
1730 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1731 src->data_file = talloc_strdup(mem_ctx, "");
1732 if (!src->data_file) { return false; }
1735 if (drv_file_in_use(src->config_file, drv)) {
1737 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1738 src->config_file = talloc_strdup(mem_ctx, "");
1739 if (!src->config_file) { return false; }
1742 if (drv_file_in_use(src->help_file, drv)) {
1744 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1745 src->help_file = talloc_strdup(mem_ctx, "");
1746 if (!src->help_file) { return false; }
1749 /* are there any dependentfiles to examine? */
1751 if (!src->dependent_files)
1754 while (src->dependent_files[i] && *src->dependent_files[i]) {
1755 if (drv_file_in_use(src->dependent_files[i], drv)) {
1757 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1758 trim_dependent_file(mem_ctx, src->dependent_files, i);
1766 /****************************************************************************
1767 Determine whether or not a particular driver files are currently being
1768 used by any other driver.
1770 Return value is True if any files were in use by other drivers
1771 and False otherwise.
1773 Upon return, *info has been modified to only contain the driver files
1774 which are not in use
1778 This needs to check all drivers to ensure that all files in use
1779 have been removed from *info, not just the ones in the first
1781 ****************************************************************************/
1783 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1784 struct auth_serversupplied_info *server_info,
1785 struct messaging_context *msg_ctx,
1786 struct spoolss_DriverInfo8 *info)
1790 struct spoolss_DriverInfo8 *driver;
1791 bool in_use = false;
1792 uint32_t num_drivers;
1793 const char **drivers;
1799 version = info->version;
1801 /* loop over all driver versions */
1803 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1805 /* get the list of drivers */
1807 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
1808 info->architecture, version,
1809 &num_drivers, &drivers);
1810 if (!W_ERROR_IS_OK(result)) {
1814 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1815 num_drivers, info->architecture, version));
1817 /* check each driver for overlap in files */
1819 for (i = 0; i < num_drivers; i++) {
1820 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1824 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1825 info->architecture, drivers[i],
1827 if (!W_ERROR_IS_OK(result)) {
1828 talloc_free(drivers);
1832 /* check if d2 uses any files from d1 */
1833 /* only if this is a different driver than the one being deleted */
1835 if (!strequal(info->driver_name, driver->driver_name)) {
1836 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1837 /* mz: Do not instantly return -
1838 * we need to ensure this file isn't
1839 * also in use by other drivers. */
1844 talloc_free(driver);
1847 talloc_free(drivers);
1849 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1854 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1857 struct smb_filename *smb_fname = NULL;
1860 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1862 if (!NT_STATUS_IS_OK(status)) {
1866 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1868 TALLOC_FREE(smb_fname);
1872 /****************************************************************************
1873 Actually delete the driver files. Make sure that
1874 printer_driver_files_in_use() return False before calling
1876 ****************************************************************************/
1878 bool delete_driver_files(struct auth_serversupplied_info *server_info,
1879 const struct spoolss_DriverInfo8 *r)
1884 connection_struct *conn;
1887 fstring printdollar;
1888 int printdollar_snum;
1895 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1896 r->driver_name, r->version));
1898 fstrcpy(printdollar, "print$");
1900 printdollar_snum = find_service(printdollar);
1901 if (printdollar_snum == -1) {
1905 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1906 lp_pathname(printdollar_snum),
1907 server_info, &oldcwd);
1908 if (!NT_STATUS_IS_OK(nt_status)) {
1909 DEBUG(0,("delete_driver_files: create_conn_struct "
1910 "returned %s\n", nt_errstr(nt_status)));
1914 if ( !CAN_WRITE(conn) ) {
1915 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1919 /* now delete the files; must strip the '\print$' string from
1922 if (r->driver_path && r->driver_path[0]) {
1923 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1925 DEBUG(10,("deleting driverfile [%s]\n", s));
1926 driver_unlink_internals(conn, file);
1930 if (r->config_file && r->config_file[0]) {
1931 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1933 DEBUG(10,("deleting configfile [%s]\n", s));
1934 driver_unlink_internals(conn, file);
1938 if (r->data_file && r->data_file[0]) {
1939 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1941 DEBUG(10,("deleting datafile [%s]\n", s));
1942 driver_unlink_internals(conn, file);
1946 if (r->help_file && r->help_file[0]) {
1947 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1949 DEBUG(10,("deleting helpfile [%s]\n", s));
1950 driver_unlink_internals(conn, file);
1954 /* check if we are done removing files */
1956 if (r->dependent_files) {
1957 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1960 /* bypass the "\print$" portion of the path */
1962 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1964 DEBUG(10,("deleting dependent file [%s]\n", file));
1965 driver_unlink_internals(conn, file);
1977 vfs_ChDir(conn, oldcwd);
1985 1: level not implemented
1986 2: file doesn't exist
1987 3: can't allocate memory
1988 4: can't free memory
1989 5: non existant struct
1993 A printer and a printer driver are 2 different things.
1994 NT manages them separatelly, Samba does the same.
1995 Why ? Simply because it's easier and it makes sense !
1997 Now explanation: You have 3 printers behind your samba server,
1998 2 of them are the same make and model (laser A and B). But laser B
1999 has an 3000 sheet feeder and laser A doesn't such an option.
2000 Your third printer is an old dot-matrix model for the accounting :-).
2002 If the /usr/local/samba/lib directory (default dir), you will have
2003 5 files to describe all of this.
2005 3 files for the printers (1 by printer):
2008 NTprinter_accounting
2009 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2010 NTdriver_printer model X
2011 NTdriver_printer model Y
2013 jfm: I should use this comment for the text file to explain
2014 same thing for the forms BTW.
2015 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2019 /* Convert generic access rights to printer object specific access rights.
2020 It turns out that NT4 security descriptors use generic access rights and
2021 NT5 the object specific ones. */
2023 void map_printer_permissions(struct security_descriptor *sd)
2027 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2028 se_map_generic(&sd->dacl->aces[i].access_mask,
2029 &printer_generic_mapping);
2033 void map_job_permissions(struct security_descriptor *sd)
2037 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2038 se_map_generic(&sd->dacl->aces[i].access_mask,
2039 &job_generic_mapping);
2044 /****************************************************************************
2045 Check a user has permissions to perform the given operation. We use the
2046 permission constants defined in include/rpc_spoolss.h to check the various
2047 actions we perform when checking printer access.
2049 PRINTER_ACCESS_ADMINISTER:
2050 print_queue_pause, print_queue_resume, update_printer_sec,
2051 update_printer, spoolss_addprinterex_level_2,
2052 _spoolss_setprinterdata
2057 JOB_ACCESS_ADMINISTER:
2058 print_job_delete, print_job_pause, print_job_resume,
2061 Try access control in the following order (for performance reasons):
2062 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2063 2) check security descriptor (bit comparisons in memory)
2064 3) "printer admins" (may result in numerous calls to winbind)
2066 ****************************************************************************/
2067 bool print_access_check(struct auth_serversupplied_info *server_info,
2068 struct messaging_context *msg_ctx, int snum,
2071 struct spoolss_security_descriptor *secdesc = NULL;
2072 uint32 access_granted;
2077 TALLOC_CTX *mem_ctx = NULL;
2078 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2080 /* If user is NULL then use the current_user structure */
2082 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2084 if (server_info->utok.uid == sec_initial_uid()
2085 || user_has_privileges(server_info->ptok, &se_printop ) ) {
2089 /* Get printer name */
2091 pname = lp_printername(snum);
2093 if (!pname || !*pname) {
2098 /* Get printer security descriptor */
2100 if(!(mem_ctx = talloc_init("print_access_check"))) {
2105 result = winreg_get_printer_secdesc(mem_ctx,
2110 if (!W_ERROR_IS_OK(result)) {
2111 talloc_destroy(mem_ctx);
2116 if (access_type == JOB_ACCESS_ADMINISTER) {
2117 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2119 /* Create a child security descriptor to check permissions
2120 against. This is because print jobs are child objects
2121 objects of a printer. */
2122 status = se_create_child_secdesc(mem_ctx,
2126 parent_secdesc->owner_sid,
2127 parent_secdesc->group_sid,
2129 if (!NT_STATUS_IS_OK(status)) {
2130 talloc_destroy(mem_ctx);
2131 errno = map_errno_from_nt_status(status);
2135 map_job_permissions(secdesc);
2137 map_printer_permissions(secdesc);
2141 status = se_access_check(secdesc, server_info->ptok, access_type,
2144 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2146 /* see if we need to try the printer admin list */
2148 if (!NT_STATUS_IS_OK(status) &&
2149 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2150 server_info->info3->base.domain.string,
2151 NULL, server_info->ptok,
2152 lp_printer_admin(snum)))) {
2153 talloc_destroy(mem_ctx);
2157 talloc_destroy(mem_ctx);
2159 if (!NT_STATUS_IS_OK(status)) {
2163 return NT_STATUS_IS_OK(status);
2166 /****************************************************************************
2167 Check the time parameters allow a print operation.
2168 *****************************************************************************/
2170 bool print_time_access_check(struct auth_serversupplied_info *server_info,
2171 struct messaging_context *msg_ctx,
2172 const char *servicename)
2174 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2177 time_t now = time(NULL);
2181 result = winreg_get_printer(NULL, server_info, msg_ctx,
2182 NULL, servicename, &pinfo2);
2183 if (!W_ERROR_IS_OK(result)) {
2187 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2192 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2194 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2198 TALLOC_FREE(pinfo2);
2207 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2208 struct auth_serversupplied_info *server_info,
2209 struct messaging_context *msg_ctx,
2210 const char *printer)
2214 result = winreg_delete_printer_key(mem_ctx, server_info, msg_ctx,
2216 if (!W_ERROR_IS_OK(result)) {
2217 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",