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"
35 /* Map generic permissions to printer object specific permissions */
37 const struct generic_mapping printer_generic_mapping = {
44 /* Map generic permissions to print server object specific permissions */
46 const struct generic_mapping printserver_generic_mapping = {
53 /* Map generic permissions to job object specific permissions */
55 const struct generic_mapping job_generic_mapping = {
62 static const struct print_architecture_table_node archi_table[]= {
64 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
65 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
66 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
67 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
68 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
69 {"Windows IA64", SPL_ARCH_IA64, 3 },
70 {"Windows x64", SPL_ARCH_X64, 3 },
74 /****************************************************************************
75 Open the NT printing tdbs. Done once before fork().
76 ****************************************************************************/
78 bool nt_printing_init(struct messaging_context *msg_ctx)
82 if (!nt_printing_tdb_upgrade()) {
87 * register callback to handle updating printers as new
88 * drivers are installed
90 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
91 do_drv_upgrade_printer);
93 /* of course, none of the message callbacks matter if you don't
94 tell messages.c that you interested in receiving PRINT_GENERAL
95 msgs. This is done in serverid_register() */
97 if ( lp_security() == SEC_ADS ) {
98 win_rc = check_published_printers();
99 if (!W_ERROR_IS_OK(win_rc))
100 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
106 /*******************************************************************
107 Function to allow filename parsing "the old way".
108 ********************************************************************/
110 static NTSTATUS driver_unix_convert(connection_struct *conn,
111 const char *old_name,
112 struct smb_filename **smb_fname)
115 TALLOC_CTX *ctx = talloc_tos();
116 char *name = talloc_strdup(ctx, old_name);
119 return NT_STATUS_NO_MEMORY;
122 name = unix_clean_name(ctx, name);
124 return NT_STATUS_NO_MEMORY;
126 trim_string(name,"/","/");
128 status = unix_convert(ctx, conn, name, smb_fname, 0);
129 if (!NT_STATUS_IS_OK(status)) {
130 return NT_STATUS_NO_MEMORY;
136 /****************************************************************************
137 Function to do the mapping between the long architecture name and
139 ****************************************************************************/
141 const char *get_short_archi(const char *long_archi)
145 DEBUG(107,("Getting architecture dependant directory\n"));
148 } while ( (archi_table[i].long_archi!=NULL ) &&
149 StrCaseCmp(long_archi, archi_table[i].long_archi) );
151 if (archi_table[i].long_archi==NULL) {
152 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
156 /* this might be client code - but shouldn't this be an fstrcpy etc? */
158 DEBUGADD(108,("index: [%d]\n", i));
159 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
160 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
162 return archi_table[i].short_archi;
165 /****************************************************************************
166 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
167 There are two case to be covered here: PE (Portable Executable) and NE (New
168 Executable) files. Both files support the same INFO structure, but PE files
169 store the signature in unicode, and NE files store it as !unicode.
170 returns -1 on error, 1 on version info found, and 0 on no version info found.
171 ****************************************************************************/
173 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
179 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
180 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
181 fname, DOS_HEADER_SIZE));
185 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
186 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
187 fname, (unsigned long)byte_count));
188 goto no_version_info;
191 /* Is this really a DOS header? */
192 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
193 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
194 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
195 goto no_version_info;
198 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
199 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
200 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
202 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
203 goto no_version_info;
206 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
207 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
208 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
209 fname, (unsigned long)byte_count));
210 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
211 goto no_version_info;
214 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
215 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
216 unsigned int num_sections;
217 unsigned int section_table_bytes;
219 /* Just skip over optional header to get to section table */
220 if (SMB_VFS_LSEEK(fsp,
221 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
222 SEEK_CUR) == (SMB_OFF_T)-1) {
223 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
228 /* get the section table */
229 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
230 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
231 if (section_table_bytes == 0)
235 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
236 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
237 fname, section_table_bytes));
241 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
242 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
243 fname, (unsigned long)byte_count));
247 /* Iterate the section table looking for the resource section ".rsrc" */
248 for (i = 0; i < num_sections; i++) {
249 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
251 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
252 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
253 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
255 if (section_bytes == 0)
259 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
260 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
261 fname, section_bytes));
265 /* Seek to the start of the .rsrc section info */
266 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
267 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
272 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
273 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
274 fname, (unsigned long)byte_count));
278 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
281 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
282 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
283 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
284 /* Align to next long address */
285 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
287 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
288 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
289 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
291 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
292 fname, *major, *minor,
293 (*major>>16)&0xffff, *major&0xffff,
294 (*minor>>16)&0xffff, *minor&0xffff));
303 /* Version info not found, fall back to origin date/time */
304 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
308 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
309 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
310 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
311 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
312 /* At this point, we assume the file is in error. It still could be somthing
313 * else besides a NE file, but it unlikely at this point. */
317 /* Allocate a bit more space to speed up things */
319 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
320 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
321 fname, PE_HEADER_SIZE));
325 /* This is a HACK! I got tired of trying to sort through the messy
326 * 'NE' file format. If anyone wants to clean this up please have at
327 * it, but this works. 'NE' files will eventually fade away. JRR */
328 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
329 /* Cover case that should not occur in a well formed 'NE' .dll file */
330 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
332 for(i=0; i<byte_count; i++) {
333 /* Fast skip past data that can't possibly match */
334 if (buf[i] != 'V') continue;
336 /* Potential match data crosses buf boundry, move it to beginning
337 * of buf, and fill the buf with as much as it will hold. */
338 if (i>byte_count-VS_VERSION_INFO_SIZE) {
341 memcpy(buf, &buf[i], byte_count-i);
342 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
343 (byte_count-i))) < 0) {
345 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
350 byte_count = bc + (byte_count - i);
351 if (byte_count<VS_VERSION_INFO_SIZE) break;
356 /* Check that the full signature string and the magic number that
357 * follows exist (not a perfect solution, but the chances that this
358 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
359 * twice, as it is simpler to read the code. */
360 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
361 /* Compute skip alignment to next long address */
362 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
363 sizeof(VS_SIGNATURE)) & 3;
364 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
366 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
367 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
368 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
369 fname, *major, *minor,
370 (*major>>16)&0xffff, *major&0xffff,
371 (*minor>>16)&0xffff, *minor&0xffff));
378 /* Version info not found, fall back to origin date/time */
379 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
384 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
385 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
386 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
397 /****************************************************************************
398 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
399 share one or more files. During the MS installation process files are checked
400 to insure that only a newer version of a shared file is installed over an
401 older version. There are several possibilities for this comparison. If there
402 is no previous version, the new one is newer (obviously). If either file is
403 missing the version info structure, compare the creation date (on Unix use
404 the modification date). Otherwise chose the numerically larger version number.
405 ****************************************************************************/
407 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
409 bool use_version = true;
413 time_t new_create_time;
417 time_t old_create_time;
419 struct smb_filename *smb_fname = NULL;
420 files_struct *fsp = NULL;
426 SET_STAT_INVALID(st);
427 new_create_time = (time_t)0;
428 old_create_time = (time_t)0;
430 /* Get file version info (if available) for previous file (if it exists) */
431 status = driver_unix_convert(conn, old_file, &smb_fname);
432 if (!NT_STATUS_IS_OK(status)) {
436 status = SMB_VFS_CREATE_FILE(
439 0, /* root_dir_fid */
440 smb_fname, /* fname */
441 FILE_GENERIC_READ, /* access_mask */
442 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
443 FILE_OPEN, /* create_disposition*/
444 0, /* create_options */
445 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
446 INTERNAL_OPEN_ONLY, /* oplock_request */
447 0, /* allocation_size */
448 0, /* private_flags */
454 if (!NT_STATUS_IS_OK(status)) {
455 /* Old file not found, so by definition new file is in fact newer */
456 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
457 "errno = %d\n", smb_fname_str_dbg(smb_fname),
463 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
469 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
472 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
475 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
476 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
477 (long)old_create_time));
480 close_file(NULL, fsp, NORMAL_CLOSE);
483 /* Get file version info (if available) for new file */
484 status = driver_unix_convert(conn, new_file, &smb_fname);
485 if (!NT_STATUS_IS_OK(status)) {
489 status = SMB_VFS_CREATE_FILE(
492 0, /* root_dir_fid */
493 smb_fname, /* fname */
494 FILE_GENERIC_READ, /* access_mask */
495 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
496 FILE_OPEN, /* create_disposition*/
497 0, /* create_options */
498 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
499 INTERNAL_OPEN_ONLY, /* oplock_request */
500 0, /* allocation_size */
501 0, /* private_flags */
507 if (!NT_STATUS_IS_OK(status)) {
508 /* New file not found, this shouldn't occur if the caller did its job */
509 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
510 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
514 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
520 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
523 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
526 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
527 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
528 (long)new_create_time));
531 close_file(NULL, fsp, NORMAL_CLOSE);
534 if (use_version && (new_major != old_major || new_minor != old_minor)) {
535 /* Compare versions and choose the larger version number */
536 if (new_major > old_major ||
537 (new_major == old_major && new_minor > old_minor)) {
539 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
544 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
550 /* Compare modification time/dates and choose the newest time/date */
551 if (new_create_time > old_create_time) {
552 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
557 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
565 close_file(NULL, fsp, NORMAL_CLOSE);
568 TALLOC_FREE(smb_fname);
572 /****************************************************************************
573 Determine the correct cVersion associated with an architecture and driver
574 ****************************************************************************/
575 static uint32 get_correct_cversion(struct pipes_struct *p,
576 const char *architecture,
577 const char *driverpath_in,
582 struct smb_filename *smb_fname = NULL;
583 char *driverpath = NULL;
584 files_struct *fsp = NULL;
585 connection_struct *conn = NULL;
589 int printdollar_snum;
591 *perr = WERR_INVALID_PARAM;
593 /* If architecture is Windows 95/98/ME, the version is always 0. */
594 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
595 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
600 /* If architecture is Windows x64, the version is always 3. */
601 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
602 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
607 fstrcpy(printdollar, "print$");
609 printdollar_snum = find_service(printdollar);
610 if (printdollar_snum == -1) {
611 *perr = WERR_NO_SUCH_SHARE;
615 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
616 lp_pathname(printdollar_snum),
617 p->server_info, &oldcwd);
618 if (!NT_STATUS_IS_OK(nt_status)) {
619 DEBUG(0,("get_correct_cversion: create_conn_struct "
620 "returned %s\n", nt_errstr(nt_status)));
621 *perr = ntstatus_to_werror(nt_status);
625 /* Open the driver file (Portable Executable format) and determine the
626 * deriver the cversion. */
627 driverpath = talloc_asprintf(talloc_tos(),
636 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
637 if (!NT_STATUS_IS_OK(nt_status)) {
638 *perr = ntstatus_to_werror(nt_status);
642 nt_status = vfs_file_exist(conn, smb_fname);
643 if (!NT_STATUS_IS_OK(nt_status)) {
644 *perr = WERR_BADFILE;
648 status = SMB_VFS_CREATE_FILE(
651 0, /* root_dir_fid */
652 smb_fname, /* fname */
653 FILE_GENERIC_READ, /* access_mask */
654 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
655 FILE_OPEN, /* create_disposition*/
656 0, /* create_options */
657 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
658 INTERNAL_OPEN_ONLY, /* oplock_request */
659 0, /* private_flags */
660 0, /* allocation_size */
666 if (!NT_STATUS_IS_OK(status)) {
667 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
668 "%d\n", smb_fname_str_dbg(smb_fname), errno));
669 *perr = WERR_ACCESS_DENIED;
676 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
677 if (ret == -1) goto error_exit;
680 DEBUG(6,("get_correct_cversion: Version info not "
682 smb_fname_str_dbg(smb_fname)));
687 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
688 * for more details. Version in this case is not just the version of the
689 * file, but the version in the sense of kernal mode (2) vs. user mode
690 * (3) drivers. Other bits of the version fields are the version info.
693 cversion = major & 0x0000ffff;
695 case 2: /* WinNT drivers */
696 case 3: /* Win2K drivers */
700 DEBUG(6,("get_correct_cversion: cversion "
701 "invalid [%s] cversion = %d\n",
702 smb_fname_str_dbg(smb_fname),
707 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
708 " = 0x%x minor = 0x%x\n",
709 smb_fname_str_dbg(smb_fname), major, minor));
712 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
713 smb_fname_str_dbg(smb_fname), cversion));
720 TALLOC_FREE(smb_fname);
722 close_file(NULL, fsp, NORMAL_CLOSE);
725 vfs_ChDir(conn, oldcwd);
728 if (cversion != -1) {
734 /****************************************************************************
735 ****************************************************************************/
737 #define strip_driver_path(_mem_ctx, _element) do { \
738 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
739 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
740 W_ERROR_HAVE_NO_MEMORY((_element)); \
744 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
745 struct pipes_struct *rpc_pipe,
746 const char *architecture,
747 const char **driver_path,
748 const char **data_file,
749 const char **config_file,
750 const char **help_file,
751 struct spoolss_StringArray *dependent_files,
754 const char *short_architecture;
759 if (!*driver_path || !*data_file || !*config_file) {
760 return WERR_INVALID_PARAM;
763 /* clean up the driver name.
764 * we can get .\driver.dll
765 * or worse c:\windows\system\driver.dll !
767 /* using an intermediate string to not have overlaping memcpy()'s */
769 strip_driver_path(mem_ctx, *driver_path);
770 strip_driver_path(mem_ctx, *data_file);
771 strip_driver_path(mem_ctx, *config_file);
773 strip_driver_path(mem_ctx, *help_file);
776 if (dependent_files && dependent_files->string) {
777 for (i=0; dependent_files->string[i]; i++) {
778 strip_driver_path(mem_ctx, dependent_files->string[i]);
782 short_architecture = get_short_archi(architecture);
783 if (!short_architecture) {
784 return WERR_UNKNOWN_PRINTER_DRIVER;
787 /* jfm:7/16/2000 the client always sends the cversion=0.
788 * The server should check which version the driver is by reading
789 * the PE header of driver->driverpath.
791 * For Windows 95/98 the version is 0 (so the value sent is correct)
792 * For Windows NT (the architecture doesn't matter)
794 * NT 3.5/3.51: cversion=1
799 *version = get_correct_cversion(rpc_pipe, short_architecture,
801 if (*version == -1) {
808 /****************************************************************************
809 ****************************************************************************/
811 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
812 struct pipes_struct *rpc_pipe,
813 struct spoolss_AddDriverInfoCtr *r)
817 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
818 r->info.info3->architecture,
819 &r->info.info3->driver_path,
820 &r->info.info3->data_file,
821 &r->info.info3->config_file,
822 &r->info.info3->help_file,
823 r->info.info3->dependent_files,
824 &r->info.info3->version);
826 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
827 r->info.info6->architecture,
828 &r->info.info6->driver_path,
829 &r->info.info6->data_file,
830 &r->info.info6->config_file,
831 &r->info.info6->help_file,
832 r->info.info6->dependent_files,
833 &r->info.info6->version);
835 return WERR_NOT_SUPPORTED;
839 /****************************************************************************
840 This function sucks and should be replaced. JRA.
841 ****************************************************************************/
843 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
844 const struct spoolss_AddDriverInfo6 *src)
846 dst->version = src->version;
848 dst->driver_name = src->driver_name;
849 dst->architecture = src->architecture;
850 dst->driver_path = src->driver_path;
851 dst->data_file = src->data_file;
852 dst->config_file = src->config_file;
853 dst->help_file = src->help_file;
854 dst->monitor_name = src->monitor_name;
855 dst->default_datatype = src->default_datatype;
856 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
857 dst->dependent_files = src->dependent_files;
860 /****************************************************************************
861 ****************************************************************************/
863 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
864 connection_struct *conn,
865 const char *driver_file,
866 const char *short_architecture,
867 uint32_t driver_version,
870 struct smb_filename *smb_fname_old = NULL;
871 struct smb_filename *smb_fname_new = NULL;
872 char *old_name = NULL;
873 char *new_name = NULL;
877 old_name = talloc_asprintf(mem_ctx, "%s/%s",
878 short_architecture, driver_file);
879 W_ERROR_HAVE_NO_MEMORY(old_name);
881 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
882 short_architecture, driver_version, driver_file);
883 if (new_name == NULL) {
884 TALLOC_FREE(old_name);
888 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
890 status = driver_unix_convert(conn, old_name, &smb_fname_old);
891 if (!NT_STATUS_IS_OK(status)) {
896 /* Setup a synthetic smb_filename struct */
897 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
898 if (!smb_fname_new) {
903 smb_fname_new->base_name = new_name;
905 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
906 "'%s'\n", smb_fname_old->base_name,
907 smb_fname_new->base_name));
909 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
910 OPENX_FILE_EXISTS_TRUNCATE |
911 OPENX_FILE_CREATE_IF_NOT_EXIST,
914 if (!NT_STATUS_IS_OK(status)) {
915 DEBUG(0,("move_driver_file_to_download_area: Unable "
916 "to rename [%s] to [%s]: %s\n",
917 smb_fname_old->base_name, new_name,
919 ret = WERR_ACCESS_DENIED;
926 TALLOC_FREE(smb_fname_old);
927 TALLOC_FREE(smb_fname_new);
931 WERROR move_driver_to_download_area(struct pipes_struct *p,
932 struct spoolss_AddDriverInfoCtr *r,
935 struct spoolss_AddDriverInfo3 *driver;
936 struct spoolss_AddDriverInfo3 converted_driver;
937 const char *short_architecture;
938 struct smb_filename *smb_dname = NULL;
939 char *new_dir = NULL;
940 connection_struct *conn = NULL;
943 TALLOC_CTX *ctx = talloc_tos();
947 int printdollar_snum;
953 driver = r->info.info3;
956 convert_level_6_to_level3(&converted_driver, r->info.info6);
957 driver = &converted_driver;
960 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
961 return WERR_UNKNOWN_LEVEL;
964 short_architecture = get_short_archi(driver->architecture);
965 if (!short_architecture) {
966 return WERR_UNKNOWN_PRINTER_DRIVER;
969 fstrcpy(printdollar, "print$");
971 printdollar_snum = find_service(printdollar);
972 if (printdollar_snum == -1) {
973 *perr = WERR_NO_SUCH_SHARE;
974 return WERR_NO_SUCH_SHARE;
977 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
978 lp_pathname(printdollar_snum),
979 p->server_info, &oldcwd);
980 if (!NT_STATUS_IS_OK(nt_status)) {
981 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
982 "returned %s\n", nt_errstr(nt_status)));
983 *perr = ntstatus_to_werror(nt_status);
987 new_dir = talloc_asprintf(ctx,
995 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
996 if (!NT_STATUS_IS_OK(nt_status)) {
1001 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1003 create_directory(conn, NULL, smb_dname);
1005 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1006 * listed for this driver which has already been moved, skip it (note:
1007 * drivers may list the same file name several times. Then check if the
1008 * file already exists in archi\version\, if so, check that the version
1009 * info (or time stamps if version info is unavailable) is newer (or the
1010 * date is later). If it is, move it to archi\version\filexxx.yyy.
1011 * Otherwise, delete the file.
1013 * If a file is not moved to archi\version\ because of an error, all the
1014 * rest of the 'unmoved' driver files are removed from archi\. If one or
1015 * more of the driver's files was already moved to archi\version\, it
1016 * potentially leaves the driver in a partially updated state. Version
1017 * trauma will most likely occur if an client attempts to use any printer
1018 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1019 * done is appropriate... later JRR
1022 DEBUG(5,("Moving files now !\n"));
1024 if (driver->driver_path && strlen(driver->driver_path)) {
1026 *perr = move_driver_file_to_download_area(ctx,
1028 driver->driver_path,
1032 if (!W_ERROR_IS_OK(*perr)) {
1033 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1040 if (driver->data_file && strlen(driver->data_file)) {
1041 if (!strequal(driver->data_file, driver->driver_path)) {
1043 *perr = move_driver_file_to_download_area(ctx,
1049 if (!W_ERROR_IS_OK(*perr)) {
1050 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1058 if (driver->config_file && strlen(driver->config_file)) {
1059 if (!strequal(driver->config_file, driver->driver_path) &&
1060 !strequal(driver->config_file, driver->data_file)) {
1062 *perr = move_driver_file_to_download_area(ctx,
1064 driver->config_file,
1068 if (!W_ERROR_IS_OK(*perr)) {
1069 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1077 if (driver->help_file && strlen(driver->help_file)) {
1078 if (!strequal(driver->help_file, driver->driver_path) &&
1079 !strequal(driver->help_file, driver->data_file) &&
1080 !strequal(driver->help_file, driver->config_file)) {
1082 *perr = move_driver_file_to_download_area(ctx,
1088 if (!W_ERROR_IS_OK(*perr)) {
1089 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1097 if (driver->dependent_files && driver->dependent_files->string) {
1098 for (i=0; driver->dependent_files->string[i]; i++) {
1099 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1100 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1101 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1102 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1104 for (j=0; j < i; j++) {
1105 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1110 *perr = move_driver_file_to_download_area(ctx,
1112 driver->dependent_files->string[i],
1116 if (!W_ERROR_IS_OK(*perr)) {
1117 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1128 TALLOC_FREE(smb_dname);
1131 vfs_ChDir(conn, oldcwd);
1135 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1139 return WERR_UNKNOWN_PRINTER_DRIVER;
1144 /****************************************************************************
1145 Create and allocate a default devicemode.
1146 ****************************************************************************/
1148 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1149 const char *devicename,
1150 struct spoolss_DeviceMode **devmode)
1152 struct spoolss_DeviceMode *dm;
1155 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1160 dname = talloc_asprintf(dm, "%s", devicename);
1161 if (dname == NULL) {
1164 if (strlen(dname) > MAXDEVICENAME) {
1165 dname[MAXDEVICENAME] = '\0';
1167 dm->devicename = dname;
1169 dm->formname = talloc_strdup(dm, "Letter");
1170 if (dm->formname == NULL) {
1174 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1175 dm->driverversion = 0x0400;
1177 dm->__driverextra_length = 0;
1178 dm->fields = DEVMODE_FORMNAME |
1180 DEVMODE_PRINTQUALITY |
1181 DEVMODE_DEFAULTSOURCE |
1185 DEVMODE_ORIENTATION;
1186 dm->orientation = DMORIENT_PORTRAIT;
1187 dm->papersize = DMPAPER_LETTER;
1188 dm->paperlength = 0;
1192 dm->defaultsource = DMBIN_FORMSOURCE;
1193 dm->printquality = DMRES_HIGH; /* 0x0258 */
1194 dm->color = DMRES_MONOCHROME;
1195 dm->duplex = DMDUP_SIMPLEX;
1196 dm->yresolution = 0;
1197 dm->ttoption = DMTT_SUBDEV;
1198 dm->collate = DMCOLLATE_FALSE;
1208 dm->displayflags = 0;
1209 dm->displayfrequency = 0;
1212 dm->panningwidth = 0;
1213 dm->panningheight = 0;
1215 dm->driverextra_data.data = NULL;
1216 dm->driverextra_data.length = 0;
1222 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1223 struct spoolss_security_descriptor **secdesc)
1225 struct security_ace ace[7]; /* max number of ace entries */
1228 struct security_acl *psa = NULL;
1229 struct security_descriptor *psd = NULL;
1230 struct dom_sid adm_sid;
1233 /* Create an ACE where Everyone is allowed to print */
1235 sa = PRINTER_ACE_PRINT;
1236 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1237 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1239 /* Add the domain admins group if we are a DC */
1242 struct dom_sid domadmins_sid;
1244 sid_compose(&domadmins_sid, get_global_sam_sid(),
1247 sa = PRINTER_ACE_FULL_CONTROL;
1248 init_sec_ace(&ace[i++], &domadmins_sid,
1249 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1250 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1251 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1252 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1254 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1255 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1257 sa = PRINTER_ACE_FULL_CONTROL;
1258 init_sec_ace(&ace[i++], &adm_sid,
1259 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1260 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1261 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1262 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1265 /* add BUILTIN\Administrators as FULL CONTROL */
1267 sa = PRINTER_ACE_FULL_CONTROL;
1268 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1269 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1270 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1271 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1272 SEC_ACE_TYPE_ACCESS_ALLOWED,
1273 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1275 /* add BUILTIN\Print Operators as FULL CONTROL */
1277 sa = PRINTER_ACE_FULL_CONTROL;
1278 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1279 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1280 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1281 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1282 SEC_ACE_TYPE_ACCESS_ALLOWED,
1283 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1285 /* Make the security descriptor owned by the BUILTIN\Administrators */
1287 /* The ACL revision number in rpc_secdesc.h differs from the one
1288 created by NT when setting ACE entries in printer
1289 descriptors. NT4 complains about the property being edited by a
1292 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1293 psd = make_sec_desc(mem_ctx,
1295 SEC_DESC_SELF_RELATIVE,
1296 &global_sid_Builtin_Administrators,
1297 &global_sid_Builtin_Administrators,
1304 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1308 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1309 (unsigned int)sd_size));
1316 /****************************************************************************
1317 ***************************************************************************/
1319 static char *win_driver;
1320 static char *os2_driver;
1322 static const char *get_win_driver(void)
1324 if (win_driver == NULL) {
1330 static const char *get_os2_driver(void)
1332 if (os2_driver == NULL) {
1338 static bool set_driver_mapping(const char *from, const char *to)
1340 SAFE_FREE(win_driver);
1341 SAFE_FREE(os2_driver);
1343 win_driver = SMB_STRDUP(from);
1344 os2_driver = SMB_STRDUP(to);
1346 if (win_driver == NULL || os2_driver == NULL) {
1347 SAFE_FREE(win_driver);
1348 SAFE_FREE(os2_driver);
1357 * @brief Map a Windows driver to a OS/2 driver.
1359 * @param[in] mem_ctx The memory context to use.
1361 * @param[in,out] pdrivername The drivername of Windows to remap.
1363 * @return WERR_OK on success, a corresponding WERROR on failure.
1365 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1367 const char *mapfile = lp_os2_driver_map();
1368 char **lines = NULL;
1369 const char *drivername;
1373 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1374 return WERR_INVALID_PARAMETER;
1377 drivername = *pdrivername;
1379 if (mapfile[0] == '\0') {
1380 return WERR_BADFILE;
1383 if (strequal(drivername, get_win_driver())) {
1384 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1385 drivername, get_os2_driver()));
1386 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1387 if (drivername == NULL) {
1390 *pdrivername = drivername;
1394 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1395 if (numlines == 0 || lines == NULL) {
1396 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1401 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1403 for( i = 0; i < numlines; i++) {
1404 char *nt_name = lines[i];
1405 char *os2_name = strchr(nt_name, '=');
1407 if (os2_name == NULL) {
1413 while (isspace(*nt_name)) {
1417 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1422 int l = strlen(nt_name);
1423 while (l && isspace(nt_name[l - 1])) {
1429 while (isspace(*os2_name)) {
1434 int l = strlen(os2_name);
1435 while (l && isspace(os2_name[l-1])) {
1441 if (strequal(nt_name, drivername)) {
1442 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1443 set_driver_mapping(drivername, os2_name);
1444 drivername = talloc_strdup(mem_ctx, os2_name);
1446 if (drivername == NULL) {
1449 *pdrivername = drivername;
1458 /****************************************************************************
1459 ****************************************************************************/
1461 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1462 struct spoolss_DriverInfo8 *_info8)
1464 struct spoolss_DriverInfo8 info8;
1470 info8.version = r->info.info3->version;
1471 info8.driver_name = r->info.info3->driver_name;
1472 info8.architecture = r->info.info3->architecture;
1473 info8.driver_path = r->info.info3->driver_path;
1474 info8.data_file = r->info.info3->data_file;
1475 info8.config_file = r->info.info3->config_file;
1476 info8.help_file = r->info.info3->help_file;
1477 info8.monitor_name = r->info.info3->monitor_name;
1478 info8.default_datatype = r->info.info3->default_datatype;
1479 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1480 info8.dependent_files = r->info.info3->dependent_files->string;
1484 info8.version = r->info.info6->version;
1485 info8.driver_name = r->info.info6->driver_name;
1486 info8.architecture = r->info.info6->architecture;
1487 info8.driver_path = r->info.info6->driver_path;
1488 info8.data_file = r->info.info6->data_file;
1489 info8.config_file = r->info.info6->config_file;
1490 info8.help_file = r->info.info6->help_file;
1491 info8.monitor_name = r->info.info6->monitor_name;
1492 info8.default_datatype = r->info.info6->default_datatype;
1493 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1494 info8.dependent_files = r->info.info6->dependent_files->string;
1496 info8.driver_date = r->info.info6->driver_date;
1497 info8.driver_version = r->info.info6->driver_version;
1498 info8.manufacturer_name = r->info.info6->manufacturer_name;
1499 info8.manufacturer_url = r->info.info6->manufacturer_url;
1500 info8.hardware_id = r->info.info6->hardware_id;
1501 info8.provider = r->info.info6->provider;
1504 info8.version = r->info.info8->version;
1505 info8.driver_name = r->info.info8->driver_name;
1506 info8.architecture = r->info.info8->architecture;
1507 info8.driver_path = r->info.info8->driver_path;
1508 info8.data_file = r->info.info8->data_file;
1509 info8.config_file = r->info.info8->config_file;
1510 info8.help_file = r->info.info8->help_file;
1511 info8.monitor_name = r->info.info8->monitor_name;
1512 info8.default_datatype = r->info.info8->default_datatype;
1513 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1514 info8.dependent_files = r->info.info8->dependent_files->string;
1516 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1517 info8.previous_names = r->info.info8->previous_names->string;
1519 info8.driver_date = r->info.info8->driver_date;
1520 info8.driver_version = r->info.info8->driver_version;
1521 info8.manufacturer_name = r->info.info8->manufacturer_name;
1522 info8.manufacturer_url = r->info.info8->manufacturer_url;
1523 info8.hardware_id = r->info.info8->hardware_id;
1524 info8.provider = r->info.info8->provider;
1525 info8.print_processor = r->info.info8->print_processor;
1526 info8.vendor_setup = r->info.info8->vendor_setup;
1527 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1528 info8.color_profiles = r->info.info8->color_profiles->string;
1530 info8.inf_path = r->info.info8->inf_path;
1531 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1532 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1533 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1535 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1536 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1548 /****************************************************************************
1549 Determine whether or not a particular driver is currently assigned
1551 ****************************************************************************/
1553 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1554 struct auth_serversupplied_info *server_info,
1555 const struct spoolss_DriverInfo8 *r)
1558 int n_services = lp_numservices();
1559 bool in_use = False;
1560 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1567 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1569 /* loop through the printers.tdb and check for the drivername */
1571 for (snum=0; snum<n_services && !in_use; snum++) {
1572 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1576 result = winreg_get_printer(mem_ctx, server_info, NULL,
1577 lp_servicename(snum), &pinfo2);
1578 if (!W_ERROR_IS_OK(result)) {
1579 continue; /* skip */
1582 if (strequal(r->driver_name, pinfo2->drivername)) {
1586 TALLOC_FREE(pinfo2);
1589 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1592 struct spoolss_DriverInfo8 *driver;
1595 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1597 /* we can still remove the driver if there is one of
1598 "Windows NT x86" version 2 or 3 left */
1600 if (!strequal("Windows NT x86", r->architecture)) {
1601 werr = winreg_get_driver(mem_ctx, server_info,
1606 } else if (r->version == 2) {
1607 werr = winreg_get_driver(mem_ctx, server_info,
1611 } else if (r->version == 3) {
1612 werr = winreg_get_driver(mem_ctx, server_info,
1617 DEBUG(0, ("printer_driver_in_use: ERROR!"
1618 " unknown driver version (%d)\n",
1620 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1623 /* now check the error code */
1625 if ( W_ERROR_IS_OK(werr) ) {
1626 /* it's ok to remove the driver, we have other architctures left */
1628 talloc_free(driver);
1632 /* report that the driver is not in use by default */
1638 /**********************************************************************
1639 Check to see if a ogiven file is in use by *info
1640 *********************************************************************/
1642 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1649 /* mz: skip files that are in the list but already deleted */
1650 if (!file || !file[0]) {
1654 if (strequal(file, info->driver_path))
1657 if (strequal(file, info->data_file))
1660 if (strequal(file, info->config_file))
1663 if (strequal(file, info->help_file))
1666 /* see of there are any dependent files to examine */
1668 if (!info->dependent_files)
1671 while (info->dependent_files[i] && *info->dependent_files[i]) {
1672 if (strequal(file, info->dependent_files[i]))
1681 /**********************************************************************
1682 Utility function to remove the dependent file pointed to by the
1683 input parameter from the list
1684 *********************************************************************/
1686 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1689 /* bump everything down a slot */
1691 while (files && files[idx+1]) {
1692 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1701 /**********************************************************************
1702 Check if any of the files used by src are also used by drv
1703 *********************************************************************/
1705 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1706 struct spoolss_DriverInfo8 *src,
1707 const struct spoolss_DriverInfo8 *drv)
1709 bool in_use = False;
1715 /* check each file. Remove it from the src structure if it overlaps */
1717 if (drv_file_in_use(src->driver_path, drv)) {
1719 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1720 src->driver_path = talloc_strdup(mem_ctx, "");
1721 if (!src->driver_path) { return false; }
1724 if (drv_file_in_use(src->data_file, drv)) {
1726 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1727 src->data_file = talloc_strdup(mem_ctx, "");
1728 if (!src->data_file) { return false; }
1731 if (drv_file_in_use(src->config_file, drv)) {
1733 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1734 src->config_file = talloc_strdup(mem_ctx, "");
1735 if (!src->config_file) { return false; }
1738 if (drv_file_in_use(src->help_file, drv)) {
1740 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1741 src->help_file = talloc_strdup(mem_ctx, "");
1742 if (!src->help_file) { return false; }
1745 /* are there any dependentfiles to examine? */
1747 if (!src->dependent_files)
1750 while (src->dependent_files[i] && *src->dependent_files[i]) {
1751 if (drv_file_in_use(src->dependent_files[i], drv)) {
1753 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1754 trim_dependent_file(mem_ctx, src->dependent_files, i);
1762 /****************************************************************************
1763 Determine whether or not a particular driver files are currently being
1764 used by any other driver.
1766 Return value is True if any files were in use by other drivers
1767 and False otherwise.
1769 Upon return, *info has been modified to only contain the driver files
1770 which are not in use
1774 This needs to check all drivers to ensure that all files in use
1775 have been removed from *info, not just the ones in the first
1777 ****************************************************************************/
1779 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1780 struct auth_serversupplied_info *server_info,
1781 struct spoolss_DriverInfo8 *info)
1785 struct spoolss_DriverInfo8 *driver;
1786 bool in_use = false;
1787 uint32_t num_drivers;
1788 const char **drivers;
1794 version = info->version;
1796 /* loop over all driver versions */
1798 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1800 /* get the list of drivers */
1802 result = winreg_get_driver_list(mem_ctx, server_info,
1803 info->architecture, version,
1804 &num_drivers, &drivers);
1805 if (!W_ERROR_IS_OK(result)) {
1809 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1810 num_drivers, info->architecture, version));
1812 /* check each driver for overlap in files */
1814 for (i = 0; i < num_drivers; i++) {
1815 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1819 result = winreg_get_driver(mem_ctx, server_info,
1820 info->architecture, drivers[i],
1822 if (!W_ERROR_IS_OK(result)) {
1823 talloc_free(drivers);
1827 /* check if d2 uses any files from d1 */
1828 /* only if this is a different driver than the one being deleted */
1830 if (!strequal(info->driver_name, driver->driver_name)) {
1831 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1832 /* mz: Do not instantly return -
1833 * we need to ensure this file isn't
1834 * also in use by other drivers. */
1839 talloc_free(driver);
1842 talloc_free(drivers);
1844 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1849 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1852 struct smb_filename *smb_fname = NULL;
1855 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1857 if (!NT_STATUS_IS_OK(status)) {
1861 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1863 TALLOC_FREE(smb_fname);
1867 /****************************************************************************
1868 Actually delete the driver files. Make sure that
1869 printer_driver_files_in_use() return False before calling
1871 ****************************************************************************/
1873 bool delete_driver_files(struct auth_serversupplied_info *server_info,
1874 const struct spoolss_DriverInfo8 *r)
1879 connection_struct *conn;
1882 fstring printdollar;
1883 int printdollar_snum;
1890 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1891 r->driver_name, r->version));
1893 fstrcpy(printdollar, "print$");
1895 printdollar_snum = find_service(printdollar);
1896 if (printdollar_snum == -1) {
1900 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1901 lp_pathname(printdollar_snum),
1902 server_info, &oldcwd);
1903 if (!NT_STATUS_IS_OK(nt_status)) {
1904 DEBUG(0,("delete_driver_files: create_conn_struct "
1905 "returned %s\n", nt_errstr(nt_status)));
1909 if ( !CAN_WRITE(conn) ) {
1910 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1914 /* now delete the files; must strip the '\print$' string from
1917 if (r->driver_path && r->driver_path[0]) {
1918 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1920 DEBUG(10,("deleting driverfile [%s]\n", s));
1921 driver_unlink_internals(conn, file);
1925 if (r->config_file && r->config_file[0]) {
1926 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1928 DEBUG(10,("deleting configfile [%s]\n", s));
1929 driver_unlink_internals(conn, file);
1933 if (r->data_file && r->data_file[0]) {
1934 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1936 DEBUG(10,("deleting datafile [%s]\n", s));
1937 driver_unlink_internals(conn, file);
1941 if (r->help_file && r->help_file[0]) {
1942 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1944 DEBUG(10,("deleting helpfile [%s]\n", s));
1945 driver_unlink_internals(conn, file);
1949 /* check if we are done removing files */
1951 if (r->dependent_files) {
1952 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1955 /* bypass the "\print$" portion of the path */
1957 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1959 DEBUG(10,("deleting dependent file [%s]\n", file));
1960 driver_unlink_internals(conn, file);
1972 vfs_ChDir(conn, oldcwd);
1980 1: level not implemented
1981 2: file doesn't exist
1982 3: can't allocate memory
1983 4: can't free memory
1984 5: non existant struct
1988 A printer and a printer driver are 2 different things.
1989 NT manages them separatelly, Samba does the same.
1990 Why ? Simply because it's easier and it makes sense !
1992 Now explanation: You have 3 printers behind your samba server,
1993 2 of them are the same make and model (laser A and B). But laser B
1994 has an 3000 sheet feeder and laser A doesn't such an option.
1995 Your third printer is an old dot-matrix model for the accounting :-).
1997 If the /usr/local/samba/lib directory (default dir), you will have
1998 5 files to describe all of this.
2000 3 files for the printers (1 by printer):
2003 NTprinter_accounting
2004 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2005 NTdriver_printer model X
2006 NTdriver_printer model Y
2008 jfm: I should use this comment for the text file to explain
2009 same thing for the forms BTW.
2010 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2014 /* Convert generic access rights to printer object specific access rights.
2015 It turns out that NT4 security descriptors use generic access rights and
2016 NT5 the object specific ones. */
2018 void map_printer_permissions(struct security_descriptor *sd)
2022 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2023 se_map_generic(&sd->dacl->aces[i].access_mask,
2024 &printer_generic_mapping);
2028 void map_job_permissions(struct security_descriptor *sd)
2032 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2033 se_map_generic(&sd->dacl->aces[i].access_mask,
2034 &job_generic_mapping);
2039 /****************************************************************************
2040 Check a user has permissions to perform the given operation. We use the
2041 permission constants defined in include/rpc_spoolss.h to check the various
2042 actions we perform when checking printer access.
2044 PRINTER_ACCESS_ADMINISTER:
2045 print_queue_pause, print_queue_resume, update_printer_sec,
2046 update_printer, spoolss_addprinterex_level_2,
2047 _spoolss_setprinterdata
2052 JOB_ACCESS_ADMINISTER:
2053 print_job_delete, print_job_pause, print_job_resume,
2056 Try access control in the following order (for performance reasons):
2057 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2058 2) check security descriptor (bit comparisons in memory)
2059 3) "printer admins" (may result in numerous calls to winbind)
2061 ****************************************************************************/
2062 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
2065 struct spoolss_security_descriptor *secdesc = NULL;
2066 uint32 access_granted;
2071 TALLOC_CTX *mem_ctx = NULL;
2072 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2074 /* If user is NULL then use the current_user structure */
2076 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2078 if (server_info->utok.uid == sec_initial_uid()
2079 || user_has_privileges(server_info->ptok, &se_printop ) ) {
2083 /* Get printer name */
2085 pname = lp_printername(snum);
2087 if (!pname || !*pname) {
2092 /* Get printer security descriptor */
2094 if(!(mem_ctx = talloc_init("print_access_check"))) {
2099 result = winreg_get_printer_secdesc(mem_ctx,
2103 if (!W_ERROR_IS_OK(result)) {
2104 talloc_destroy(mem_ctx);
2109 if (access_type == JOB_ACCESS_ADMINISTER) {
2110 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2112 /* Create a child security descriptor to check permissions
2113 against. This is because print jobs are child objects
2114 objects of a printer. */
2115 status = se_create_child_secdesc(mem_ctx,
2119 parent_secdesc->owner_sid,
2120 parent_secdesc->group_sid,
2122 if (!NT_STATUS_IS_OK(status)) {
2123 talloc_destroy(mem_ctx);
2124 errno = map_errno_from_nt_status(status);
2128 map_job_permissions(secdesc);
2130 map_printer_permissions(secdesc);
2134 status = se_access_check(secdesc, server_info->ptok, access_type,
2137 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2139 /* see if we need to try the printer admin list */
2141 if (!NT_STATUS_IS_OK(status) &&
2142 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2143 server_info->info3->base.domain.string,
2144 NULL, server_info->ptok,
2145 lp_printer_admin(snum)))) {
2146 talloc_destroy(mem_ctx);
2150 talloc_destroy(mem_ctx);
2152 if (!NT_STATUS_IS_OK(status)) {
2156 return NT_STATUS_IS_OK(status);
2159 /****************************************************************************
2160 Check the time parameters allow a print operation.
2161 *****************************************************************************/
2163 bool print_time_access_check(struct auth_serversupplied_info *server_info,
2164 const char *servicename)
2166 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2169 time_t now = time(NULL);
2173 result = winreg_get_printer(NULL, server_info,
2174 NULL, servicename, &pinfo2);
2175 if (!W_ERROR_IS_OK(result)) {
2179 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2184 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2186 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2190 TALLOC_FREE(pinfo2);
2199 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2200 struct auth_serversupplied_info *server_info,
2201 const char *printer)
2205 result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
2206 if (!W_ERROR_IS_OK(result)) {
2207 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",