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"
35 #include "../libcli/security/security.h"
37 /* Map generic permissions to printer object specific permissions */
39 const struct generic_mapping printer_generic_mapping = {
46 /* Map generic permissions to print server object specific permissions */
48 const struct generic_mapping printserver_generic_mapping = {
55 /* Map generic permissions to job object specific permissions */
57 const struct generic_mapping job_generic_mapping = {
64 static const struct print_architecture_table_node archi_table[]= {
66 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
67 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
68 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
69 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
70 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
71 {"Windows IA64", SPL_ARCH_IA64, 3 },
72 {"Windows x64", SPL_ARCH_X64, 3 },
76 /****************************************************************************
77 Open the NT printing tdbs. Done once before fork().
78 ****************************************************************************/
80 bool nt_printing_init(struct messaging_context *msg_ctx)
84 if (!nt_printing_tdb_upgrade()) {
89 * register callback to handle updating printers as new
90 * drivers are installed
92 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
93 do_drv_upgrade_printer);
95 /* of course, none of the message callbacks matter if you don't
96 tell messages.c that you interested in receiving PRINT_GENERAL
97 msgs. This is done in serverid_register() */
99 if ( lp_security() == SEC_ADS ) {
100 win_rc = check_published_printers(msg_ctx);
101 if (!W_ERROR_IS_OK(win_rc))
102 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
108 /*******************************************************************
109 Function to allow filename parsing "the old way".
110 ********************************************************************/
112 static NTSTATUS driver_unix_convert(connection_struct *conn,
113 const char *old_name,
114 struct smb_filename **smb_fname)
117 TALLOC_CTX *ctx = talloc_tos();
118 char *name = talloc_strdup(ctx, old_name);
121 return NT_STATUS_NO_MEMORY;
124 name = unix_clean_name(ctx, name);
126 return NT_STATUS_NO_MEMORY;
128 trim_string(name,"/","/");
130 status = unix_convert(ctx, conn, name, smb_fname, 0);
131 if (!NT_STATUS_IS_OK(status)) {
132 return NT_STATUS_NO_MEMORY;
138 /****************************************************************************
139 Function to do the mapping between the long architecture name and
141 ****************************************************************************/
143 const char *get_short_archi(const char *long_archi)
147 DEBUG(107,("Getting architecture dependant directory\n"));
150 } while ( (archi_table[i].long_archi!=NULL ) &&
151 StrCaseCmp(long_archi, archi_table[i].long_archi) );
153 if (archi_table[i].long_archi==NULL) {
154 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
158 /* this might be client code - but shouldn't this be an fstrcpy etc? */
160 DEBUGADD(108,("index: [%d]\n", i));
161 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
162 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
164 return archi_table[i].short_archi;
167 /****************************************************************************
168 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
169 There are two case to be covered here: PE (Portable Executable) and NE (New
170 Executable) files. Both files support the same INFO structure, but PE files
171 store the signature in unicode, and NE files store it as !unicode.
172 returns -1 on error, 1 on version info found, and 0 on no version info found.
173 ****************************************************************************/
175 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
181 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
182 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
183 fname, DOS_HEADER_SIZE));
187 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
188 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
189 fname, (unsigned long)byte_count));
190 goto no_version_info;
193 /* Is this really a DOS header? */
194 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
195 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
196 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
197 goto no_version_info;
200 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
201 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
202 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
204 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
205 goto no_version_info;
208 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
209 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
210 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
211 fname, (unsigned long)byte_count));
212 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
213 goto no_version_info;
216 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
217 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
218 unsigned int num_sections;
219 unsigned int section_table_bytes;
221 /* Just skip over optional header to get to section table */
222 if (SMB_VFS_LSEEK(fsp,
223 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
224 SEEK_CUR) == (SMB_OFF_T)-1) {
225 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
230 /* get the section table */
231 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
232 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
233 if (section_table_bytes == 0)
237 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
238 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
239 fname, section_table_bytes));
243 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
244 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
245 fname, (unsigned long)byte_count));
249 /* Iterate the section table looking for the resource section ".rsrc" */
250 for (i = 0; i < num_sections; i++) {
251 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
253 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
254 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
255 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
257 if (section_bytes == 0)
261 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
262 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
263 fname, section_bytes));
267 /* Seek to the start of the .rsrc section info */
268 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
269 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
274 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
275 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
276 fname, (unsigned long)byte_count));
280 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
283 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
284 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
285 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
286 /* Align to next long address */
287 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
289 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
290 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
291 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
293 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
294 fname, *major, *minor,
295 (*major>>16)&0xffff, *major&0xffff,
296 (*minor>>16)&0xffff, *minor&0xffff));
305 /* Version info not found, fall back to origin date/time */
306 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
310 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
311 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
312 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
313 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
314 /* At this point, we assume the file is in error. It still could be somthing
315 * else besides a NE file, but it unlikely at this point. */
319 /* Allocate a bit more space to speed up things */
321 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
322 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
323 fname, PE_HEADER_SIZE));
327 /* This is a HACK! I got tired of trying to sort through the messy
328 * 'NE' file format. If anyone wants to clean this up please have at
329 * it, but this works. 'NE' files will eventually fade away. JRR */
330 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
331 /* Cover case that should not occur in a well formed 'NE' .dll file */
332 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
334 for(i=0; i<byte_count; i++) {
335 /* Fast skip past data that can't possibly match */
336 if (buf[i] != 'V') continue;
338 /* Potential match data crosses buf boundry, move it to beginning
339 * of buf, and fill the buf with as much as it will hold. */
340 if (i>byte_count-VS_VERSION_INFO_SIZE) {
343 memcpy(buf, &buf[i], byte_count-i);
344 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
345 (byte_count-i))) < 0) {
347 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
352 byte_count = bc + (byte_count - i);
353 if (byte_count<VS_VERSION_INFO_SIZE) break;
358 /* Check that the full signature string and the magic number that
359 * follows exist (not a perfect solution, but the chances that this
360 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
361 * twice, as it is simpler to read the code. */
362 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
363 /* Compute skip alignment to next long address */
364 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
365 sizeof(VS_SIGNATURE)) & 3;
366 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
368 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
369 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
370 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
371 fname, *major, *minor,
372 (*major>>16)&0xffff, *major&0xffff,
373 (*minor>>16)&0xffff, *minor&0xffff));
380 /* Version info not found, fall back to origin date/time */
381 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
386 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
387 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
388 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
399 /****************************************************************************
400 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
401 share one or more files. During the MS installation process files are checked
402 to insure that only a newer version of a shared file is installed over an
403 older version. There are several possibilities for this comparison. If there
404 is no previous version, the new one is newer (obviously). If either file is
405 missing the version info structure, compare the creation date (on Unix use
406 the modification date). Otherwise chose the numerically larger version number.
407 ****************************************************************************/
409 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
411 bool use_version = true;
415 time_t new_create_time;
419 time_t old_create_time;
421 struct smb_filename *smb_fname = NULL;
422 files_struct *fsp = NULL;
428 SET_STAT_INVALID(st);
429 new_create_time = (time_t)0;
430 old_create_time = (time_t)0;
432 /* Get file version info (if available) for previous file (if it exists) */
433 status = driver_unix_convert(conn, old_file, &smb_fname);
434 if (!NT_STATUS_IS_OK(status)) {
438 status = SMB_VFS_CREATE_FILE(
441 0, /* root_dir_fid */
442 smb_fname, /* fname */
443 FILE_GENERIC_READ, /* access_mask */
444 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
445 FILE_OPEN, /* create_disposition*/
446 0, /* create_options */
447 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
448 INTERNAL_OPEN_ONLY, /* oplock_request */
449 0, /* allocation_size */
450 0, /* private_flags */
456 if (!NT_STATUS_IS_OK(status)) {
457 /* Old file not found, so by definition new file is in fact newer */
458 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
459 "errno = %d\n", smb_fname_str_dbg(smb_fname),
465 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
471 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
474 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
477 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
478 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
479 (long)old_create_time));
482 close_file(NULL, fsp, NORMAL_CLOSE);
485 /* Get file version info (if available) for new file */
486 status = driver_unix_convert(conn, new_file, &smb_fname);
487 if (!NT_STATUS_IS_OK(status)) {
491 status = SMB_VFS_CREATE_FILE(
494 0, /* root_dir_fid */
495 smb_fname, /* fname */
496 FILE_GENERIC_READ, /* access_mask */
497 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
498 FILE_OPEN, /* create_disposition*/
499 0, /* create_options */
500 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
501 INTERNAL_OPEN_ONLY, /* oplock_request */
502 0, /* allocation_size */
503 0, /* private_flags */
509 if (!NT_STATUS_IS_OK(status)) {
510 /* New file not found, this shouldn't occur if the caller did its job */
511 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
512 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
516 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
522 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
525 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
528 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
529 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
530 (long)new_create_time));
533 close_file(NULL, fsp, NORMAL_CLOSE);
536 if (use_version && (new_major != old_major || new_minor != old_minor)) {
537 /* Compare versions and choose the larger version number */
538 if (new_major > old_major ||
539 (new_major == old_major && new_minor > old_minor)) {
541 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
546 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
552 /* Compare modification time/dates and choose the newest time/date */
553 if (new_create_time > old_create_time) {
554 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
559 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
567 close_file(NULL, fsp, NORMAL_CLOSE);
570 TALLOC_FREE(smb_fname);
574 /****************************************************************************
575 Determine the correct cVersion associated with an architecture and driver
576 ****************************************************************************/
577 static uint32 get_correct_cversion(struct pipes_struct *p,
578 const char *architecture,
579 const char *driverpath_in,
584 struct smb_filename *smb_fname = NULL;
585 char *driverpath = NULL;
586 files_struct *fsp = NULL;
587 connection_struct *conn = NULL;
590 char *printdollar = NULL;
591 int printdollar_snum;
593 *perr = WERR_INVALID_PARAM;
595 /* If architecture is Windows 95/98/ME, the version is always 0. */
596 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
597 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
602 /* If architecture is Windows x64, the version is always 3. */
603 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
604 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
609 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
614 if (printdollar_snum == -1) {
615 *perr = WERR_NO_SUCH_SHARE;
619 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
620 lp_pathname(printdollar_snum),
621 p->server_info, &oldcwd);
622 if (!NT_STATUS_IS_OK(nt_status)) {
623 DEBUG(0,("get_correct_cversion: create_conn_struct "
624 "returned %s\n", nt_errstr(nt_status)));
625 *perr = ntstatus_to_werror(nt_status);
629 /* Open the driver file (Portable Executable format) and determine the
630 * deriver the cversion. */
631 driverpath = talloc_asprintf(talloc_tos(),
640 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
641 if (!NT_STATUS_IS_OK(nt_status)) {
642 *perr = ntstatus_to_werror(nt_status);
646 nt_status = vfs_file_exist(conn, smb_fname);
647 if (!NT_STATUS_IS_OK(nt_status)) {
648 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
649 *perr = WERR_BADFILE;
653 status = SMB_VFS_CREATE_FILE(
656 0, /* root_dir_fid */
657 smb_fname, /* fname */
658 FILE_GENERIC_READ, /* access_mask */
659 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
660 FILE_OPEN, /* create_disposition*/
661 0, /* create_options */
662 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
663 INTERNAL_OPEN_ONLY, /* oplock_request */
664 0, /* private_flags */
665 0, /* allocation_size */
671 if (!NT_STATUS_IS_OK(status)) {
672 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
673 "%d\n", smb_fname_str_dbg(smb_fname), errno));
674 *perr = WERR_ACCESS_DENIED;
681 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
682 if (ret == -1) goto error_exit;
685 DEBUG(6,("get_correct_cversion: Version info not "
687 smb_fname_str_dbg(smb_fname)));
692 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
693 * for more details. Version in this case is not just the version of the
694 * file, but the version in the sense of kernal mode (2) vs. user mode
695 * (3) drivers. Other bits of the version fields are the version info.
698 cversion = major & 0x0000ffff;
700 case 2: /* WinNT drivers */
701 case 3: /* Win2K drivers */
705 DEBUG(6,("get_correct_cversion: cversion "
706 "invalid [%s] cversion = %d\n",
707 smb_fname_str_dbg(smb_fname),
712 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
713 " = 0x%x minor = 0x%x\n",
714 smb_fname_str_dbg(smb_fname), major, minor));
717 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
718 smb_fname_str_dbg(smb_fname), cversion));
725 TALLOC_FREE(smb_fname);
727 close_file(NULL, fsp, NORMAL_CLOSE);
730 vfs_ChDir(conn, oldcwd);
733 if (cversion != -1) {
739 /****************************************************************************
740 ****************************************************************************/
742 #define strip_driver_path(_mem_ctx, _element) do { \
743 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
744 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
745 W_ERROR_HAVE_NO_MEMORY((_element)); \
749 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
750 struct pipes_struct *rpc_pipe,
751 const char *architecture,
752 const char **driver_path,
753 const char **data_file,
754 const char **config_file,
755 const char **help_file,
756 struct spoolss_StringArray *dependent_files,
757 enum spoolss_DriverOSVersion *version)
759 const char *short_architecture;
764 if (!*driver_path || !*data_file || !*config_file) {
765 return WERR_INVALID_PARAM;
768 /* clean up the driver name.
769 * we can get .\driver.dll
770 * or worse c:\windows\system\driver.dll !
772 /* using an intermediate string to not have overlaping memcpy()'s */
774 strip_driver_path(mem_ctx, *driver_path);
775 strip_driver_path(mem_ctx, *data_file);
776 strip_driver_path(mem_ctx, *config_file);
778 strip_driver_path(mem_ctx, *help_file);
781 if (dependent_files && dependent_files->string) {
782 for (i=0; dependent_files->string[i]; i++) {
783 strip_driver_path(mem_ctx, dependent_files->string[i]);
787 short_architecture = get_short_archi(architecture);
788 if (!short_architecture) {
789 return WERR_UNKNOWN_PRINTER_DRIVER;
792 /* jfm:7/16/2000 the client always sends the cversion=0.
793 * The server should check which version the driver is by reading
794 * the PE header of driver->driverpath.
796 * For Windows 95/98 the version is 0 (so the value sent is correct)
797 * For Windows NT (the architecture doesn't matter)
799 * NT 3.5/3.51: cversion=1
804 *version = get_correct_cversion(rpc_pipe, short_architecture,
806 if (*version == -1) {
813 /****************************************************************************
814 ****************************************************************************/
816 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
817 struct pipes_struct *rpc_pipe,
818 struct spoolss_AddDriverInfoCtr *r)
822 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
823 r->info.info3->architecture,
824 &r->info.info3->driver_path,
825 &r->info.info3->data_file,
826 &r->info.info3->config_file,
827 &r->info.info3->help_file,
828 r->info.info3->dependent_files,
829 &r->info.info3->version);
831 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
832 r->info.info6->architecture,
833 &r->info.info6->driver_path,
834 &r->info.info6->data_file,
835 &r->info.info6->config_file,
836 &r->info.info6->help_file,
837 r->info.info6->dependent_files,
838 &r->info.info6->version);
840 return WERR_NOT_SUPPORTED;
844 /****************************************************************************
845 This function sucks and should be replaced. JRA.
846 ****************************************************************************/
848 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
849 const struct spoolss_AddDriverInfo6 *src)
851 dst->version = src->version;
853 dst->driver_name = src->driver_name;
854 dst->architecture = src->architecture;
855 dst->driver_path = src->driver_path;
856 dst->data_file = src->data_file;
857 dst->config_file = src->config_file;
858 dst->help_file = src->help_file;
859 dst->monitor_name = src->monitor_name;
860 dst->default_datatype = src->default_datatype;
861 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
862 dst->dependent_files = src->dependent_files;
865 /****************************************************************************
866 ****************************************************************************/
868 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
869 connection_struct *conn,
870 const char *driver_file,
871 const char *short_architecture,
872 uint32_t driver_version,
875 struct smb_filename *smb_fname_old = NULL;
876 struct smb_filename *smb_fname_new = NULL;
877 char *old_name = NULL;
878 char *new_name = NULL;
882 old_name = talloc_asprintf(mem_ctx, "%s/%s",
883 short_architecture, driver_file);
884 W_ERROR_HAVE_NO_MEMORY(old_name);
886 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
887 short_architecture, driver_version, driver_file);
888 if (new_name == NULL) {
889 TALLOC_FREE(old_name);
893 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
895 status = driver_unix_convert(conn, old_name, &smb_fname_old);
896 if (!NT_STATUS_IS_OK(status)) {
901 /* Setup a synthetic smb_filename struct */
902 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
903 if (!smb_fname_new) {
908 smb_fname_new->base_name = new_name;
910 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
911 "'%s'\n", smb_fname_old->base_name,
912 smb_fname_new->base_name));
914 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
915 OPENX_FILE_EXISTS_TRUNCATE |
916 OPENX_FILE_CREATE_IF_NOT_EXIST,
919 if (!NT_STATUS_IS_OK(status)) {
920 DEBUG(0,("move_driver_file_to_download_area: Unable "
921 "to rename [%s] to [%s]: %s\n",
922 smb_fname_old->base_name, new_name,
924 ret = WERR_ACCESS_DENIED;
931 TALLOC_FREE(smb_fname_old);
932 TALLOC_FREE(smb_fname_new);
936 WERROR move_driver_to_download_area(struct pipes_struct *p,
937 struct spoolss_AddDriverInfoCtr *r,
940 struct spoolss_AddDriverInfo3 *driver;
941 struct spoolss_AddDriverInfo3 converted_driver;
942 const char *short_architecture;
943 struct smb_filename *smb_dname = NULL;
944 char *new_dir = NULL;
945 connection_struct *conn = NULL;
948 TALLOC_CTX *ctx = talloc_tos();
951 char *printdollar = NULL;
952 int printdollar_snum;
958 driver = r->info.info3;
961 convert_level_6_to_level3(&converted_driver, r->info.info6);
962 driver = &converted_driver;
965 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
966 return WERR_UNKNOWN_LEVEL;
969 short_architecture = get_short_archi(driver->architecture);
970 if (!short_architecture) {
971 return WERR_UNKNOWN_PRINTER_DRIVER;
974 printdollar_snum = find_service(ctx, "print$", &printdollar);
979 if (printdollar_snum == -1) {
980 *perr = WERR_NO_SUCH_SHARE;
981 return WERR_NO_SUCH_SHARE;
984 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
985 lp_pathname(printdollar_snum),
986 p->server_info, &oldcwd);
987 if (!NT_STATUS_IS_OK(nt_status)) {
988 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
989 "returned %s\n", nt_errstr(nt_status)));
990 *perr = ntstatus_to_werror(nt_status);
994 new_dir = talloc_asprintf(ctx,
1002 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1003 if (!NT_STATUS_IS_OK(nt_status)) {
1008 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1010 create_directory(conn, NULL, smb_dname);
1012 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1013 * listed for this driver which has already been moved, skip it (note:
1014 * drivers may list the same file name several times. Then check if the
1015 * file already exists in archi\version\, if so, check that the version
1016 * info (or time stamps if version info is unavailable) is newer (or the
1017 * date is later). If it is, move it to archi\version\filexxx.yyy.
1018 * Otherwise, delete the file.
1020 * If a file is not moved to archi\version\ because of an error, all the
1021 * rest of the 'unmoved' driver files are removed from archi\. If one or
1022 * more of the driver's files was already moved to archi\version\, it
1023 * potentially leaves the driver in a partially updated state. Version
1024 * trauma will most likely occur if an client attempts to use any printer
1025 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1026 * done is appropriate... later JRR
1029 DEBUG(5,("Moving files now !\n"));
1031 if (driver->driver_path && strlen(driver->driver_path)) {
1033 *perr = move_driver_file_to_download_area(ctx,
1035 driver->driver_path,
1039 if (!W_ERROR_IS_OK(*perr)) {
1040 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1047 if (driver->data_file && strlen(driver->data_file)) {
1048 if (!strequal(driver->data_file, driver->driver_path)) {
1050 *perr = move_driver_file_to_download_area(ctx,
1056 if (!W_ERROR_IS_OK(*perr)) {
1057 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1065 if (driver->config_file && strlen(driver->config_file)) {
1066 if (!strequal(driver->config_file, driver->driver_path) &&
1067 !strequal(driver->config_file, driver->data_file)) {
1069 *perr = move_driver_file_to_download_area(ctx,
1071 driver->config_file,
1075 if (!W_ERROR_IS_OK(*perr)) {
1076 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1084 if (driver->help_file && strlen(driver->help_file)) {
1085 if (!strequal(driver->help_file, driver->driver_path) &&
1086 !strequal(driver->help_file, driver->data_file) &&
1087 !strequal(driver->help_file, driver->config_file)) {
1089 *perr = move_driver_file_to_download_area(ctx,
1095 if (!W_ERROR_IS_OK(*perr)) {
1096 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1104 if (driver->dependent_files && driver->dependent_files->string) {
1105 for (i=0; driver->dependent_files->string[i]; i++) {
1106 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1107 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1108 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1109 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1111 for (j=0; j < i; j++) {
1112 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1117 *perr = move_driver_file_to_download_area(ctx,
1119 driver->dependent_files->string[i],
1123 if (!W_ERROR_IS_OK(*perr)) {
1124 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1135 TALLOC_FREE(smb_dname);
1138 vfs_ChDir(conn, oldcwd);
1142 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1146 return WERR_UNKNOWN_PRINTER_DRIVER;
1151 /****************************************************************************
1152 Create and allocate a default devicemode.
1153 ****************************************************************************/
1155 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1156 const char *devicename,
1157 struct spoolss_DeviceMode **devmode)
1159 struct spoolss_DeviceMode *dm;
1162 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1167 dname = talloc_asprintf(dm, "%s", devicename);
1168 if (dname == NULL) {
1171 if (strlen(dname) > MAXDEVICENAME) {
1172 dname[MAXDEVICENAME] = '\0';
1174 dm->devicename = dname;
1176 dm->formname = talloc_strdup(dm, "Letter");
1177 if (dm->formname == NULL) {
1181 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1182 dm->driverversion = 0x0400;
1184 dm->__driverextra_length = 0;
1185 dm->fields = DEVMODE_FORMNAME |
1187 DEVMODE_PRINTQUALITY |
1188 DEVMODE_DEFAULTSOURCE |
1192 DEVMODE_ORIENTATION;
1193 dm->orientation = DMORIENT_PORTRAIT;
1194 dm->papersize = DMPAPER_LETTER;
1195 dm->paperlength = 0;
1199 dm->defaultsource = DMBIN_FORMSOURCE;
1200 dm->printquality = DMRES_HIGH; /* 0x0258 */
1201 dm->color = DMRES_MONOCHROME;
1202 dm->duplex = DMDUP_SIMPLEX;
1203 dm->yresolution = 0;
1204 dm->ttoption = DMTT_SUBDEV;
1205 dm->collate = DMCOLLATE_FALSE;
1215 dm->displayflags = 0;
1216 dm->displayfrequency = 0;
1219 dm->panningwidth = 0;
1220 dm->panningheight = 0;
1222 dm->driverextra_data.data = NULL;
1223 dm->driverextra_data.length = 0;
1229 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1230 struct spoolss_security_descriptor **secdesc)
1232 struct security_ace ace[7]; /* max number of ace entries */
1235 struct security_acl *psa = NULL;
1236 struct security_descriptor *psd = NULL;
1237 struct dom_sid adm_sid;
1240 /* Create an ACE where Everyone is allowed to print */
1242 sa = PRINTER_ACE_PRINT;
1243 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1244 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1246 /* Add the domain admins group if we are a DC */
1249 struct dom_sid domadmins_sid;
1251 sid_compose(&domadmins_sid, get_global_sam_sid(),
1254 sa = PRINTER_ACE_FULL_CONTROL;
1255 init_sec_ace(&ace[i++], &domadmins_sid,
1256 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1257 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1258 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1259 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1261 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1262 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1264 sa = PRINTER_ACE_FULL_CONTROL;
1265 init_sec_ace(&ace[i++], &adm_sid,
1266 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1267 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1268 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1269 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1272 /* add BUILTIN\Administrators as FULL CONTROL */
1274 sa = PRINTER_ACE_FULL_CONTROL;
1275 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1276 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1277 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1278 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1279 SEC_ACE_TYPE_ACCESS_ALLOWED,
1280 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1282 /* add BUILTIN\Print Operators as FULL CONTROL */
1284 sa = PRINTER_ACE_FULL_CONTROL;
1285 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1286 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1287 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1288 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1289 SEC_ACE_TYPE_ACCESS_ALLOWED,
1290 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1292 /* Make the security descriptor owned by the BUILTIN\Administrators */
1294 /* The ACL revision number in rpc_secdesc.h differs from the one
1295 created by NT when setting ACE entries in printer
1296 descriptors. NT4 complains about the property being edited by a
1299 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1300 psd = make_sec_desc(mem_ctx,
1302 SEC_DESC_SELF_RELATIVE,
1303 &global_sid_Builtin_Administrators,
1304 &global_sid_Builtin_Administrators,
1311 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1315 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1316 (unsigned int)sd_size));
1323 /****************************************************************************
1324 ***************************************************************************/
1326 static char *win_driver;
1327 static char *os2_driver;
1329 static const char *get_win_driver(void)
1331 if (win_driver == NULL) {
1337 static const char *get_os2_driver(void)
1339 if (os2_driver == NULL) {
1345 static bool set_driver_mapping(const char *from, const char *to)
1347 SAFE_FREE(win_driver);
1348 SAFE_FREE(os2_driver);
1350 win_driver = SMB_STRDUP(from);
1351 os2_driver = SMB_STRDUP(to);
1353 if (win_driver == NULL || os2_driver == NULL) {
1354 SAFE_FREE(win_driver);
1355 SAFE_FREE(os2_driver);
1364 * @brief Map a Windows driver to a OS/2 driver.
1366 * @param[in] mem_ctx The memory context to use.
1368 * @param[in,out] pdrivername The drivername of Windows to remap.
1370 * @return WERR_OK on success, a corresponding WERROR on failure.
1372 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1374 const char *mapfile = lp_os2_driver_map();
1375 char **lines = NULL;
1376 const char *drivername;
1380 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1381 return WERR_INVALID_PARAMETER;
1384 drivername = *pdrivername;
1386 if (mapfile[0] == '\0') {
1387 return WERR_BADFILE;
1390 if (strequal(drivername, get_win_driver())) {
1391 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1392 drivername, get_os2_driver()));
1393 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1394 if (drivername == NULL) {
1397 *pdrivername = drivername;
1401 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1402 if (numlines == 0 || lines == NULL) {
1403 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1408 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1410 for( i = 0; i < numlines; i++) {
1411 char *nt_name = lines[i];
1412 char *os2_name = strchr(nt_name, '=');
1414 if (os2_name == NULL) {
1420 while (isspace(*nt_name)) {
1424 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1429 int l = strlen(nt_name);
1430 while (l && isspace(nt_name[l - 1])) {
1436 while (isspace(*os2_name)) {
1441 int l = strlen(os2_name);
1442 while (l && isspace(os2_name[l-1])) {
1448 if (strequal(nt_name, drivername)) {
1449 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1450 set_driver_mapping(drivername, os2_name);
1451 drivername = talloc_strdup(mem_ctx, os2_name);
1453 if (drivername == NULL) {
1456 *pdrivername = drivername;
1465 /****************************************************************************
1466 ****************************************************************************/
1468 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1469 struct spoolss_DriverInfo8 *_info8)
1471 struct spoolss_DriverInfo8 info8;
1477 info8.version = r->info.info3->version;
1478 info8.driver_name = r->info.info3->driver_name;
1479 info8.architecture = r->info.info3->architecture;
1480 info8.driver_path = r->info.info3->driver_path;
1481 info8.data_file = r->info.info3->data_file;
1482 info8.config_file = r->info.info3->config_file;
1483 info8.help_file = r->info.info3->help_file;
1484 info8.monitor_name = r->info.info3->monitor_name;
1485 info8.default_datatype = r->info.info3->default_datatype;
1486 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1487 info8.dependent_files = r->info.info3->dependent_files->string;
1491 info8.version = r->info.info6->version;
1492 info8.driver_name = r->info.info6->driver_name;
1493 info8.architecture = r->info.info6->architecture;
1494 info8.driver_path = r->info.info6->driver_path;
1495 info8.data_file = r->info.info6->data_file;
1496 info8.config_file = r->info.info6->config_file;
1497 info8.help_file = r->info.info6->help_file;
1498 info8.monitor_name = r->info.info6->monitor_name;
1499 info8.default_datatype = r->info.info6->default_datatype;
1500 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1501 info8.dependent_files = r->info.info6->dependent_files->string;
1503 info8.driver_date = r->info.info6->driver_date;
1504 info8.driver_version = r->info.info6->driver_version;
1505 info8.manufacturer_name = r->info.info6->manufacturer_name;
1506 info8.manufacturer_url = r->info.info6->manufacturer_url;
1507 info8.hardware_id = r->info.info6->hardware_id;
1508 info8.provider = r->info.info6->provider;
1511 info8.version = r->info.info8->version;
1512 info8.driver_name = r->info.info8->driver_name;
1513 info8.architecture = r->info.info8->architecture;
1514 info8.driver_path = r->info.info8->driver_path;
1515 info8.data_file = r->info.info8->data_file;
1516 info8.config_file = r->info.info8->config_file;
1517 info8.help_file = r->info.info8->help_file;
1518 info8.monitor_name = r->info.info8->monitor_name;
1519 info8.default_datatype = r->info.info8->default_datatype;
1520 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1521 info8.dependent_files = r->info.info8->dependent_files->string;
1523 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1524 info8.previous_names = r->info.info8->previous_names->string;
1526 info8.driver_date = r->info.info8->driver_date;
1527 info8.driver_version = r->info.info8->driver_version;
1528 info8.manufacturer_name = r->info.info8->manufacturer_name;
1529 info8.manufacturer_url = r->info.info8->manufacturer_url;
1530 info8.hardware_id = r->info.info8->hardware_id;
1531 info8.provider = r->info.info8->provider;
1532 info8.print_processor = r->info.info8->print_processor;
1533 info8.vendor_setup = r->info.info8->vendor_setup;
1534 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1535 info8.color_profiles = r->info.info8->color_profiles->string;
1537 info8.inf_path = r->info.info8->inf_path;
1538 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1539 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1540 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1542 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1543 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1555 /****************************************************************************
1556 Determine whether or not a particular driver is currently assigned
1558 ****************************************************************************/
1560 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1561 const struct auth_serversupplied_info *server_info,
1562 struct messaging_context *msg_ctx,
1563 const struct spoolss_DriverInfo8 *r)
1566 int n_services = lp_numservices();
1567 bool in_use = False;
1568 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1575 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1577 /* loop through the printers.tdb and check for the drivername */
1579 for (snum=0; snum<n_services && !in_use; snum++) {
1580 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1584 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
1585 lp_servicename(snum),
1587 if (!W_ERROR_IS_OK(result)) {
1588 continue; /* skip */
1591 if (strequal(r->driver_name, pinfo2->drivername)) {
1595 TALLOC_FREE(pinfo2);
1598 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1601 struct spoolss_DriverInfo8 *driver;
1604 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1606 /* we can still remove the driver if there is one of
1607 "Windows NT x86" version 2 or 3 left */
1609 if (!strequal("Windows NT x86", r->architecture)) {
1610 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1615 } else if (r->version == 2) {
1616 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1620 } else if (r->version == 3) {
1621 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1626 DEBUG(0, ("printer_driver_in_use: ERROR!"
1627 " unknown driver version (%d)\n",
1629 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1632 /* now check the error code */
1634 if ( W_ERROR_IS_OK(werr) ) {
1635 /* it's ok to remove the driver, we have other architctures left */
1637 talloc_free(driver);
1641 /* report that the driver is not in use by default */
1647 /**********************************************************************
1648 Check to see if a ogiven file is in use by *info
1649 *********************************************************************/
1651 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1658 /* mz: skip files that are in the list but already deleted */
1659 if (!file || !file[0]) {
1663 if (strequal(file, info->driver_path))
1666 if (strequal(file, info->data_file))
1669 if (strequal(file, info->config_file))
1672 if (strequal(file, info->help_file))
1675 /* see of there are any dependent files to examine */
1677 if (!info->dependent_files)
1680 while (info->dependent_files[i] && *info->dependent_files[i]) {
1681 if (strequal(file, info->dependent_files[i]))
1690 /**********************************************************************
1691 Utility function to remove the dependent file pointed to by the
1692 input parameter from the list
1693 *********************************************************************/
1695 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1698 /* bump everything down a slot */
1700 while (files && files[idx+1]) {
1701 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1710 /**********************************************************************
1711 Check if any of the files used by src are also used by drv
1712 *********************************************************************/
1714 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1715 struct spoolss_DriverInfo8 *src,
1716 const struct spoolss_DriverInfo8 *drv)
1718 bool in_use = False;
1724 /* check each file. Remove it from the src structure if it overlaps */
1726 if (drv_file_in_use(src->driver_path, drv)) {
1728 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1729 src->driver_path = talloc_strdup(mem_ctx, "");
1730 if (!src->driver_path) { return false; }
1733 if (drv_file_in_use(src->data_file, drv)) {
1735 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1736 src->data_file = talloc_strdup(mem_ctx, "");
1737 if (!src->data_file) { return false; }
1740 if (drv_file_in_use(src->config_file, drv)) {
1742 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1743 src->config_file = talloc_strdup(mem_ctx, "");
1744 if (!src->config_file) { return false; }
1747 if (drv_file_in_use(src->help_file, drv)) {
1749 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1750 src->help_file = talloc_strdup(mem_ctx, "");
1751 if (!src->help_file) { return false; }
1754 /* are there any dependentfiles to examine? */
1756 if (!src->dependent_files)
1759 while (src->dependent_files[i] && *src->dependent_files[i]) {
1760 if (drv_file_in_use(src->dependent_files[i], drv)) {
1762 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1763 trim_dependent_file(mem_ctx, src->dependent_files, i);
1771 /****************************************************************************
1772 Determine whether or not a particular driver files are currently being
1773 used by any other driver.
1775 Return value is True if any files were in use by other drivers
1776 and False otherwise.
1778 Upon return, *info has been modified to only contain the driver files
1779 which are not in use
1783 This needs to check all drivers to ensure that all files in use
1784 have been removed from *info, not just the ones in the first
1786 ****************************************************************************/
1788 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1789 const struct auth_serversupplied_info *server_info,
1790 struct messaging_context *msg_ctx,
1791 struct spoolss_DriverInfo8 *info)
1795 struct spoolss_DriverInfo8 *driver;
1796 bool in_use = false;
1797 uint32_t num_drivers;
1798 const char **drivers;
1804 version = info->version;
1806 /* loop over all driver versions */
1808 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1810 /* get the list of drivers */
1812 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
1813 info->architecture, version,
1814 &num_drivers, &drivers);
1815 if (!W_ERROR_IS_OK(result)) {
1819 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1820 num_drivers, info->architecture, version));
1822 /* check each driver for overlap in files */
1824 for (i = 0; i < num_drivers; i++) {
1825 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1829 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1830 info->architecture, drivers[i],
1832 if (!W_ERROR_IS_OK(result)) {
1833 talloc_free(drivers);
1837 /* check if d2 uses any files from d1 */
1838 /* only if this is a different driver than the one being deleted */
1840 if (!strequal(info->driver_name, driver->driver_name)) {
1841 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1842 /* mz: Do not instantly return -
1843 * we need to ensure this file isn't
1844 * also in use by other drivers. */
1849 talloc_free(driver);
1852 talloc_free(drivers);
1854 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1859 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1862 struct smb_filename *smb_fname = NULL;
1865 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1867 if (!NT_STATUS_IS_OK(status)) {
1871 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1873 TALLOC_FREE(smb_fname);
1877 /****************************************************************************
1878 Actually delete the driver files. Make sure that
1879 printer_driver_files_in_use() return False before calling
1881 ****************************************************************************/
1883 bool delete_driver_files(const struct auth_serversupplied_info *server_info,
1884 const struct spoolss_DriverInfo8 *r)
1889 connection_struct *conn;
1892 char *printdollar = NULL;
1893 int printdollar_snum;
1900 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1901 r->driver_name, r->version));
1903 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1907 if (printdollar_snum == -1) {
1911 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1912 lp_pathname(printdollar_snum),
1913 server_info, &oldcwd);
1914 if (!NT_STATUS_IS_OK(nt_status)) {
1915 DEBUG(0,("delete_driver_files: create_conn_struct "
1916 "returned %s\n", nt_errstr(nt_status)));
1920 if ( !CAN_WRITE(conn) ) {
1921 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1925 /* now delete the files; must strip the '\print$' string from
1928 if (r->driver_path && r->driver_path[0]) {
1929 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1931 DEBUG(10,("deleting driverfile [%s]\n", s));
1932 driver_unlink_internals(conn, file);
1936 if (r->config_file && r->config_file[0]) {
1937 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1939 DEBUG(10,("deleting configfile [%s]\n", s));
1940 driver_unlink_internals(conn, file);
1944 if (r->data_file && r->data_file[0]) {
1945 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1947 DEBUG(10,("deleting datafile [%s]\n", s));
1948 driver_unlink_internals(conn, file);
1952 if (r->help_file && r->help_file[0]) {
1953 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1955 DEBUG(10,("deleting helpfile [%s]\n", s));
1956 driver_unlink_internals(conn, file);
1960 /* check if we are done removing files */
1962 if (r->dependent_files) {
1963 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1966 /* bypass the "\print$" portion of the path */
1968 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1970 DEBUG(10,("deleting dependent file [%s]\n", file));
1971 driver_unlink_internals(conn, file);
1983 vfs_ChDir(conn, oldcwd);
1991 1: level not implemented
1992 2: file doesn't exist
1993 3: can't allocate memory
1994 4: can't free memory
1995 5: non existant struct
1999 A printer and a printer driver are 2 different things.
2000 NT manages them separatelly, Samba does the same.
2001 Why ? Simply because it's easier and it makes sense !
2003 Now explanation: You have 3 printers behind your samba server,
2004 2 of them are the same make and model (laser A and B). But laser B
2005 has an 3000 sheet feeder and laser A doesn't such an option.
2006 Your third printer is an old dot-matrix model for the accounting :-).
2008 If the /usr/local/samba/lib directory (default dir), you will have
2009 5 files to describe all of this.
2011 3 files for the printers (1 by printer):
2014 NTprinter_accounting
2015 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2016 NTdriver_printer model X
2017 NTdriver_printer model Y
2019 jfm: I should use this comment for the text file to explain
2020 same thing for the forms BTW.
2021 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2025 /* Convert generic access rights to printer object specific access rights.
2026 It turns out that NT4 security descriptors use generic access rights and
2027 NT5 the object specific ones. */
2029 void map_printer_permissions(struct security_descriptor *sd)
2033 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2034 se_map_generic(&sd->dacl->aces[i].access_mask,
2035 &printer_generic_mapping);
2039 void map_job_permissions(struct security_descriptor *sd)
2043 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2044 se_map_generic(&sd->dacl->aces[i].access_mask,
2045 &job_generic_mapping);
2050 /****************************************************************************
2051 Check a user has permissions to perform the given operation. We use the
2052 permission constants defined in include/rpc_spoolss.h to check the various
2053 actions we perform when checking printer access.
2055 PRINTER_ACCESS_ADMINISTER:
2056 print_queue_pause, print_queue_resume, update_printer_sec,
2057 update_printer, spoolss_addprinterex_level_2,
2058 _spoolss_setprinterdata
2063 JOB_ACCESS_ADMINISTER:
2064 print_job_delete, print_job_pause, print_job_resume,
2067 Try access control in the following order (for performance reasons):
2068 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2069 2) check security descriptor (bit comparisons in memory)
2070 3) "printer admins" (may result in numerous calls to winbind)
2072 ****************************************************************************/
2073 bool print_access_check(const struct auth_serversupplied_info *server_info,
2074 struct messaging_context *msg_ctx, int snum,
2077 struct spoolss_security_descriptor *secdesc = NULL;
2078 uint32 access_granted;
2083 TALLOC_CTX *mem_ctx = NULL;
2085 /* If user is NULL then use the current_user structure */
2087 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2089 if (server_info->utok.uid == sec_initial_uid()
2090 || security_token_has_privilege(server_info->ptok, SEC_PRIV_PRINT_OPERATOR)) {
2094 /* Get printer name */
2096 pname = lp_printername(snum);
2098 if (!pname || !*pname) {
2103 /* Get printer security descriptor */
2105 if(!(mem_ctx = talloc_init("print_access_check"))) {
2110 result = winreg_get_printer_secdesc(mem_ctx,
2111 get_server_info_system(),
2115 if (!W_ERROR_IS_OK(result)) {
2116 talloc_destroy(mem_ctx);
2121 if (access_type == JOB_ACCESS_ADMINISTER) {
2122 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2124 /* Create a child security descriptor to check permissions
2125 against. This is because print jobs are child objects
2126 objects of a printer. */
2127 status = se_create_child_secdesc(mem_ctx,
2131 parent_secdesc->owner_sid,
2132 parent_secdesc->group_sid,
2134 if (!NT_STATUS_IS_OK(status)) {
2135 talloc_destroy(mem_ctx);
2136 errno = map_errno_from_nt_status(status);
2140 map_job_permissions(secdesc);
2142 map_printer_permissions(secdesc);
2146 status = se_access_check(secdesc, server_info->ptok, access_type,
2149 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2151 /* see if we need to try the printer admin list */
2153 if (!NT_STATUS_IS_OK(status) &&
2154 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2155 server_info->info3->base.domain.string,
2156 NULL, server_info->ptok,
2157 lp_printer_admin(snum)))) {
2158 talloc_destroy(mem_ctx);
2162 talloc_destroy(mem_ctx);
2164 if (!NT_STATUS_IS_OK(status)) {
2168 return NT_STATUS_IS_OK(status);
2171 /****************************************************************************
2172 Check the time parameters allow a print operation.
2173 *****************************************************************************/
2175 bool print_time_access_check(const struct auth_serversupplied_info *server_info,
2176 struct messaging_context *msg_ctx,
2177 const char *servicename)
2179 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2182 time_t now = time(NULL);
2186 result = winreg_get_printer(NULL, server_info, msg_ctx,
2187 servicename, &pinfo2);
2188 if (!W_ERROR_IS_OK(result)) {
2192 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2197 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2199 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2203 TALLOC_FREE(pinfo2);
2212 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2213 const struct auth_serversupplied_info *server_info,
2214 struct messaging_context *msg_ctx,
2215 const char *printer)
2219 result = winreg_delete_printer_key(mem_ctx, server_info, msg_ctx,
2221 if (!W_ERROR_IS_OK(result)) {
2222 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",