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;
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 fstrcpy(printdollar, "print$");
611 printdollar_snum = find_service(printdollar);
612 if (printdollar_snum == -1) {
613 *perr = WERR_NO_SUCH_SHARE;
617 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
618 lp_pathname(printdollar_snum),
619 p->server_info, &oldcwd);
620 if (!NT_STATUS_IS_OK(nt_status)) {
621 DEBUG(0,("get_correct_cversion: create_conn_struct "
622 "returned %s\n", nt_errstr(nt_status)));
623 *perr = ntstatus_to_werror(nt_status);
627 /* Open the driver file (Portable Executable format) and determine the
628 * deriver the cversion. */
629 driverpath = talloc_asprintf(talloc_tos(),
638 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
639 if (!NT_STATUS_IS_OK(nt_status)) {
640 *perr = ntstatus_to_werror(nt_status);
644 nt_status = vfs_file_exist(conn, smb_fname);
645 if (!NT_STATUS_IS_OK(nt_status)) {
646 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
647 *perr = WERR_BADFILE;
651 status = SMB_VFS_CREATE_FILE(
654 0, /* root_dir_fid */
655 smb_fname, /* fname */
656 FILE_GENERIC_READ, /* access_mask */
657 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
658 FILE_OPEN, /* create_disposition*/
659 0, /* create_options */
660 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
661 INTERNAL_OPEN_ONLY, /* oplock_request */
662 0, /* private_flags */
663 0, /* allocation_size */
669 if (!NT_STATUS_IS_OK(status)) {
670 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
671 "%d\n", smb_fname_str_dbg(smb_fname), errno));
672 *perr = WERR_ACCESS_DENIED;
679 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
680 if (ret == -1) goto error_exit;
683 DEBUG(6,("get_correct_cversion: Version info not "
685 smb_fname_str_dbg(smb_fname)));
690 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
691 * for more details. Version in this case is not just the version of the
692 * file, but the version in the sense of kernal mode (2) vs. user mode
693 * (3) drivers. Other bits of the version fields are the version info.
696 cversion = major & 0x0000ffff;
698 case 2: /* WinNT drivers */
699 case 3: /* Win2K drivers */
703 DEBUG(6,("get_correct_cversion: cversion "
704 "invalid [%s] cversion = %d\n",
705 smb_fname_str_dbg(smb_fname),
710 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
711 " = 0x%x minor = 0x%x\n",
712 smb_fname_str_dbg(smb_fname), major, minor));
715 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
716 smb_fname_str_dbg(smb_fname), cversion));
723 TALLOC_FREE(smb_fname);
725 close_file(NULL, fsp, NORMAL_CLOSE);
728 vfs_ChDir(conn, oldcwd);
731 if (cversion != -1) {
737 /****************************************************************************
738 ****************************************************************************/
740 #define strip_driver_path(_mem_ctx, _element) do { \
741 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
742 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
743 W_ERROR_HAVE_NO_MEMORY((_element)); \
747 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
748 struct pipes_struct *rpc_pipe,
749 const char *architecture,
750 const char **driver_path,
751 const char **data_file,
752 const char **config_file,
753 const char **help_file,
754 struct spoolss_StringArray *dependent_files,
755 enum spoolss_DriverOSVersion *version)
757 const char *short_architecture;
762 if (!*driver_path || !*data_file || !*config_file) {
763 return WERR_INVALID_PARAM;
766 /* clean up the driver name.
767 * we can get .\driver.dll
768 * or worse c:\windows\system\driver.dll !
770 /* using an intermediate string to not have overlaping memcpy()'s */
772 strip_driver_path(mem_ctx, *driver_path);
773 strip_driver_path(mem_ctx, *data_file);
774 strip_driver_path(mem_ctx, *config_file);
776 strip_driver_path(mem_ctx, *help_file);
779 if (dependent_files && dependent_files->string) {
780 for (i=0; dependent_files->string[i]; i++) {
781 strip_driver_path(mem_ctx, dependent_files->string[i]);
785 short_architecture = get_short_archi(architecture);
786 if (!short_architecture) {
787 return WERR_UNKNOWN_PRINTER_DRIVER;
790 /* jfm:7/16/2000 the client always sends the cversion=0.
791 * The server should check which version the driver is by reading
792 * the PE header of driver->driverpath.
794 * For Windows 95/98 the version is 0 (so the value sent is correct)
795 * For Windows NT (the architecture doesn't matter)
797 * NT 3.5/3.51: cversion=1
802 *version = get_correct_cversion(rpc_pipe, short_architecture,
804 if (*version == -1) {
811 /****************************************************************************
812 ****************************************************************************/
814 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
815 struct pipes_struct *rpc_pipe,
816 struct spoolss_AddDriverInfoCtr *r)
820 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
821 r->info.info3->architecture,
822 &r->info.info3->driver_path,
823 &r->info.info3->data_file,
824 &r->info.info3->config_file,
825 &r->info.info3->help_file,
826 r->info.info3->dependent_files,
827 &r->info.info3->version);
829 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
830 r->info.info6->architecture,
831 &r->info.info6->driver_path,
832 &r->info.info6->data_file,
833 &r->info.info6->config_file,
834 &r->info.info6->help_file,
835 r->info.info6->dependent_files,
836 &r->info.info6->version);
838 return WERR_NOT_SUPPORTED;
842 /****************************************************************************
843 This function sucks and should be replaced. JRA.
844 ****************************************************************************/
846 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
847 const struct spoolss_AddDriverInfo6 *src)
849 dst->version = src->version;
851 dst->driver_name = src->driver_name;
852 dst->architecture = src->architecture;
853 dst->driver_path = src->driver_path;
854 dst->data_file = src->data_file;
855 dst->config_file = src->config_file;
856 dst->help_file = src->help_file;
857 dst->monitor_name = src->monitor_name;
858 dst->default_datatype = src->default_datatype;
859 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
860 dst->dependent_files = src->dependent_files;
863 /****************************************************************************
864 ****************************************************************************/
866 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
867 connection_struct *conn,
868 const char *driver_file,
869 const char *short_architecture,
870 uint32_t driver_version,
873 struct smb_filename *smb_fname_old = NULL;
874 struct smb_filename *smb_fname_new = NULL;
875 char *old_name = NULL;
876 char *new_name = NULL;
880 old_name = talloc_asprintf(mem_ctx, "%s/%s",
881 short_architecture, driver_file);
882 W_ERROR_HAVE_NO_MEMORY(old_name);
884 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
885 short_architecture, driver_version, driver_file);
886 if (new_name == NULL) {
887 TALLOC_FREE(old_name);
891 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
893 status = driver_unix_convert(conn, old_name, &smb_fname_old);
894 if (!NT_STATUS_IS_OK(status)) {
899 /* Setup a synthetic smb_filename struct */
900 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
901 if (!smb_fname_new) {
906 smb_fname_new->base_name = new_name;
908 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
909 "'%s'\n", smb_fname_old->base_name,
910 smb_fname_new->base_name));
912 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
913 OPENX_FILE_EXISTS_TRUNCATE |
914 OPENX_FILE_CREATE_IF_NOT_EXIST,
917 if (!NT_STATUS_IS_OK(status)) {
918 DEBUG(0,("move_driver_file_to_download_area: Unable "
919 "to rename [%s] to [%s]: %s\n",
920 smb_fname_old->base_name, new_name,
922 ret = WERR_ACCESS_DENIED;
929 TALLOC_FREE(smb_fname_old);
930 TALLOC_FREE(smb_fname_new);
934 WERROR move_driver_to_download_area(struct pipes_struct *p,
935 struct spoolss_AddDriverInfoCtr *r,
938 struct spoolss_AddDriverInfo3 *driver;
939 struct spoolss_AddDriverInfo3 converted_driver;
940 const char *short_architecture;
941 struct smb_filename *smb_dname = NULL;
942 char *new_dir = NULL;
943 connection_struct *conn = NULL;
946 TALLOC_CTX *ctx = talloc_tos();
950 int printdollar_snum;
956 driver = r->info.info3;
959 convert_level_6_to_level3(&converted_driver, r->info.info6);
960 driver = &converted_driver;
963 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
964 return WERR_UNKNOWN_LEVEL;
967 short_architecture = get_short_archi(driver->architecture);
968 if (!short_architecture) {
969 return WERR_UNKNOWN_PRINTER_DRIVER;
972 fstrcpy(printdollar, "print$");
974 printdollar_snum = find_service(printdollar);
975 if (printdollar_snum == -1) {
976 *perr = WERR_NO_SUCH_SHARE;
977 return WERR_NO_SUCH_SHARE;
980 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
981 lp_pathname(printdollar_snum),
982 p->server_info, &oldcwd);
983 if (!NT_STATUS_IS_OK(nt_status)) {
984 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
985 "returned %s\n", nt_errstr(nt_status)));
986 *perr = ntstatus_to_werror(nt_status);
990 new_dir = talloc_asprintf(ctx,
998 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
999 if (!NT_STATUS_IS_OK(nt_status)) {
1004 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1006 create_directory(conn, NULL, smb_dname);
1008 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1009 * listed for this driver which has already been moved, skip it (note:
1010 * drivers may list the same file name several times. Then check if the
1011 * file already exists in archi\version\, if so, check that the version
1012 * info (or time stamps if version info is unavailable) is newer (or the
1013 * date is later). If it is, move it to archi\version\filexxx.yyy.
1014 * Otherwise, delete the file.
1016 * If a file is not moved to archi\version\ because of an error, all the
1017 * rest of the 'unmoved' driver files are removed from archi\. If one or
1018 * more of the driver's files was already moved to archi\version\, it
1019 * potentially leaves the driver in a partially updated state. Version
1020 * trauma will most likely occur if an client attempts to use any printer
1021 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1022 * done is appropriate... later JRR
1025 DEBUG(5,("Moving files now !\n"));
1027 if (driver->driver_path && strlen(driver->driver_path)) {
1029 *perr = move_driver_file_to_download_area(ctx,
1031 driver->driver_path,
1035 if (!W_ERROR_IS_OK(*perr)) {
1036 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1043 if (driver->data_file && strlen(driver->data_file)) {
1044 if (!strequal(driver->data_file, driver->driver_path)) {
1046 *perr = move_driver_file_to_download_area(ctx,
1052 if (!W_ERROR_IS_OK(*perr)) {
1053 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1061 if (driver->config_file && strlen(driver->config_file)) {
1062 if (!strequal(driver->config_file, driver->driver_path) &&
1063 !strequal(driver->config_file, driver->data_file)) {
1065 *perr = move_driver_file_to_download_area(ctx,
1067 driver->config_file,
1071 if (!W_ERROR_IS_OK(*perr)) {
1072 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1080 if (driver->help_file && strlen(driver->help_file)) {
1081 if (!strequal(driver->help_file, driver->driver_path) &&
1082 !strequal(driver->help_file, driver->data_file) &&
1083 !strequal(driver->help_file, driver->config_file)) {
1085 *perr = move_driver_file_to_download_area(ctx,
1091 if (!W_ERROR_IS_OK(*perr)) {
1092 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1100 if (driver->dependent_files && driver->dependent_files->string) {
1101 for (i=0; driver->dependent_files->string[i]; i++) {
1102 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1103 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1104 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1105 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1107 for (j=0; j < i; j++) {
1108 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1113 *perr = move_driver_file_to_download_area(ctx,
1115 driver->dependent_files->string[i],
1119 if (!W_ERROR_IS_OK(*perr)) {
1120 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1131 TALLOC_FREE(smb_dname);
1134 vfs_ChDir(conn, oldcwd);
1138 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1142 return WERR_UNKNOWN_PRINTER_DRIVER;
1147 /****************************************************************************
1148 Create and allocate a default devicemode.
1149 ****************************************************************************/
1151 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1152 const char *devicename,
1153 struct spoolss_DeviceMode **devmode)
1155 struct spoolss_DeviceMode *dm;
1158 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1163 dname = talloc_asprintf(dm, "%s", devicename);
1164 if (dname == NULL) {
1167 if (strlen(dname) > MAXDEVICENAME) {
1168 dname[MAXDEVICENAME] = '\0';
1170 dm->devicename = dname;
1172 dm->formname = talloc_strdup(dm, "Letter");
1173 if (dm->formname == NULL) {
1177 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1178 dm->driverversion = 0x0400;
1180 dm->__driverextra_length = 0;
1181 dm->fields = DEVMODE_FORMNAME |
1183 DEVMODE_PRINTQUALITY |
1184 DEVMODE_DEFAULTSOURCE |
1188 DEVMODE_ORIENTATION;
1189 dm->orientation = DMORIENT_PORTRAIT;
1190 dm->papersize = DMPAPER_LETTER;
1191 dm->paperlength = 0;
1195 dm->defaultsource = DMBIN_FORMSOURCE;
1196 dm->printquality = DMRES_HIGH; /* 0x0258 */
1197 dm->color = DMRES_MONOCHROME;
1198 dm->duplex = DMDUP_SIMPLEX;
1199 dm->yresolution = 0;
1200 dm->ttoption = DMTT_SUBDEV;
1201 dm->collate = DMCOLLATE_FALSE;
1211 dm->displayflags = 0;
1212 dm->displayfrequency = 0;
1215 dm->panningwidth = 0;
1216 dm->panningheight = 0;
1218 dm->driverextra_data.data = NULL;
1219 dm->driverextra_data.length = 0;
1225 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1226 struct spoolss_security_descriptor **secdesc)
1228 struct security_ace ace[7]; /* max number of ace entries */
1231 struct security_acl *psa = NULL;
1232 struct security_descriptor *psd = NULL;
1233 struct dom_sid adm_sid;
1236 /* Create an ACE where Everyone is allowed to print */
1238 sa = PRINTER_ACE_PRINT;
1239 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1240 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1242 /* Add the domain admins group if we are a DC */
1245 struct dom_sid domadmins_sid;
1247 sid_compose(&domadmins_sid, get_global_sam_sid(),
1250 sa = PRINTER_ACE_FULL_CONTROL;
1251 init_sec_ace(&ace[i++], &domadmins_sid,
1252 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1253 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1254 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1255 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1257 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1258 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1260 sa = PRINTER_ACE_FULL_CONTROL;
1261 init_sec_ace(&ace[i++], &adm_sid,
1262 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1263 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1264 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1265 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1268 /* add BUILTIN\Administrators as FULL CONTROL */
1270 sa = PRINTER_ACE_FULL_CONTROL;
1271 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1272 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1273 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1274 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1275 SEC_ACE_TYPE_ACCESS_ALLOWED,
1276 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1278 /* add BUILTIN\Print Operators as FULL CONTROL */
1280 sa = PRINTER_ACE_FULL_CONTROL;
1281 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1282 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1283 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1284 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1285 SEC_ACE_TYPE_ACCESS_ALLOWED,
1286 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1288 /* Make the security descriptor owned by the BUILTIN\Administrators */
1290 /* The ACL revision number in rpc_secdesc.h differs from the one
1291 created by NT when setting ACE entries in printer
1292 descriptors. NT4 complains about the property being edited by a
1295 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1296 psd = make_sec_desc(mem_ctx,
1298 SEC_DESC_SELF_RELATIVE,
1299 &global_sid_Builtin_Administrators,
1300 &global_sid_Builtin_Administrators,
1307 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1311 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1312 (unsigned int)sd_size));
1319 /****************************************************************************
1320 ***************************************************************************/
1322 static char *win_driver;
1323 static char *os2_driver;
1325 static const char *get_win_driver(void)
1327 if (win_driver == NULL) {
1333 static const char *get_os2_driver(void)
1335 if (os2_driver == NULL) {
1341 static bool set_driver_mapping(const char *from, const char *to)
1343 SAFE_FREE(win_driver);
1344 SAFE_FREE(os2_driver);
1346 win_driver = SMB_STRDUP(from);
1347 os2_driver = SMB_STRDUP(to);
1349 if (win_driver == NULL || os2_driver == NULL) {
1350 SAFE_FREE(win_driver);
1351 SAFE_FREE(os2_driver);
1360 * @brief Map a Windows driver to a OS/2 driver.
1362 * @param[in] mem_ctx The memory context to use.
1364 * @param[in,out] pdrivername The drivername of Windows to remap.
1366 * @return WERR_OK on success, a corresponding WERROR on failure.
1368 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1370 const char *mapfile = lp_os2_driver_map();
1371 char **lines = NULL;
1372 const char *drivername;
1376 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1377 return WERR_INVALID_PARAMETER;
1380 drivername = *pdrivername;
1382 if (mapfile[0] == '\0') {
1383 return WERR_BADFILE;
1386 if (strequal(drivername, get_win_driver())) {
1387 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1388 drivername, get_os2_driver()));
1389 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1390 if (drivername == NULL) {
1393 *pdrivername = drivername;
1397 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1398 if (numlines == 0 || lines == NULL) {
1399 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1404 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1406 for( i = 0; i < numlines; i++) {
1407 char *nt_name = lines[i];
1408 char *os2_name = strchr(nt_name, '=');
1410 if (os2_name == NULL) {
1416 while (isspace(*nt_name)) {
1420 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1425 int l = strlen(nt_name);
1426 while (l && isspace(nt_name[l - 1])) {
1432 while (isspace(*os2_name)) {
1437 int l = strlen(os2_name);
1438 while (l && isspace(os2_name[l-1])) {
1444 if (strequal(nt_name, drivername)) {
1445 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1446 set_driver_mapping(drivername, os2_name);
1447 drivername = talloc_strdup(mem_ctx, os2_name);
1449 if (drivername == NULL) {
1452 *pdrivername = drivername;
1461 /****************************************************************************
1462 ****************************************************************************/
1464 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1465 struct spoolss_DriverInfo8 *_info8)
1467 struct spoolss_DriverInfo8 info8;
1473 info8.version = r->info.info3->version;
1474 info8.driver_name = r->info.info3->driver_name;
1475 info8.architecture = r->info.info3->architecture;
1476 info8.driver_path = r->info.info3->driver_path;
1477 info8.data_file = r->info.info3->data_file;
1478 info8.config_file = r->info.info3->config_file;
1479 info8.help_file = r->info.info3->help_file;
1480 info8.monitor_name = r->info.info3->monitor_name;
1481 info8.default_datatype = r->info.info3->default_datatype;
1482 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1483 info8.dependent_files = r->info.info3->dependent_files->string;
1487 info8.version = r->info.info6->version;
1488 info8.driver_name = r->info.info6->driver_name;
1489 info8.architecture = r->info.info6->architecture;
1490 info8.driver_path = r->info.info6->driver_path;
1491 info8.data_file = r->info.info6->data_file;
1492 info8.config_file = r->info.info6->config_file;
1493 info8.help_file = r->info.info6->help_file;
1494 info8.monitor_name = r->info.info6->monitor_name;
1495 info8.default_datatype = r->info.info6->default_datatype;
1496 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1497 info8.dependent_files = r->info.info6->dependent_files->string;
1499 info8.driver_date = r->info.info6->driver_date;
1500 info8.driver_version = r->info.info6->driver_version;
1501 info8.manufacturer_name = r->info.info6->manufacturer_name;
1502 info8.manufacturer_url = r->info.info6->manufacturer_url;
1503 info8.hardware_id = r->info.info6->hardware_id;
1504 info8.provider = r->info.info6->provider;
1507 info8.version = r->info.info8->version;
1508 info8.driver_name = r->info.info8->driver_name;
1509 info8.architecture = r->info.info8->architecture;
1510 info8.driver_path = r->info.info8->driver_path;
1511 info8.data_file = r->info.info8->data_file;
1512 info8.config_file = r->info.info8->config_file;
1513 info8.help_file = r->info.info8->help_file;
1514 info8.monitor_name = r->info.info8->monitor_name;
1515 info8.default_datatype = r->info.info8->default_datatype;
1516 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1517 info8.dependent_files = r->info.info8->dependent_files->string;
1519 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1520 info8.previous_names = r->info.info8->previous_names->string;
1522 info8.driver_date = r->info.info8->driver_date;
1523 info8.driver_version = r->info.info8->driver_version;
1524 info8.manufacturer_name = r->info.info8->manufacturer_name;
1525 info8.manufacturer_url = r->info.info8->manufacturer_url;
1526 info8.hardware_id = r->info.info8->hardware_id;
1527 info8.provider = r->info.info8->provider;
1528 info8.print_processor = r->info.info8->print_processor;
1529 info8.vendor_setup = r->info.info8->vendor_setup;
1530 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1531 info8.color_profiles = r->info.info8->color_profiles->string;
1533 info8.inf_path = r->info.info8->inf_path;
1534 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1535 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1536 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1538 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1539 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1551 /****************************************************************************
1552 Determine whether or not a particular driver is currently assigned
1554 ****************************************************************************/
1556 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1557 const struct auth_serversupplied_info *server_info,
1558 struct messaging_context *msg_ctx,
1559 const struct spoolss_DriverInfo8 *r)
1562 int n_services = lp_numservices();
1563 bool in_use = False;
1564 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1571 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1573 /* loop through the printers.tdb and check for the drivername */
1575 for (snum=0; snum<n_services && !in_use; snum++) {
1576 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1580 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
1581 lp_servicename(snum),
1583 if (!W_ERROR_IS_OK(result)) {
1584 continue; /* skip */
1587 if (strequal(r->driver_name, pinfo2->drivername)) {
1591 TALLOC_FREE(pinfo2);
1594 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1597 struct spoolss_DriverInfo8 *driver;
1600 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1602 /* we can still remove the driver if there is one of
1603 "Windows NT x86" version 2 or 3 left */
1605 if (!strequal("Windows NT x86", r->architecture)) {
1606 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1611 } else if (r->version == 2) {
1612 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1616 } else if (r->version == 3) {
1617 werr = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1622 DEBUG(0, ("printer_driver_in_use: ERROR!"
1623 " unknown driver version (%d)\n",
1625 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1628 /* now check the error code */
1630 if ( W_ERROR_IS_OK(werr) ) {
1631 /* it's ok to remove the driver, we have other architctures left */
1633 talloc_free(driver);
1637 /* report that the driver is not in use by default */
1643 /**********************************************************************
1644 Check to see if a ogiven file is in use by *info
1645 *********************************************************************/
1647 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1654 /* mz: skip files that are in the list but already deleted */
1655 if (!file || !file[0]) {
1659 if (strequal(file, info->driver_path))
1662 if (strequal(file, info->data_file))
1665 if (strequal(file, info->config_file))
1668 if (strequal(file, info->help_file))
1671 /* see of there are any dependent files to examine */
1673 if (!info->dependent_files)
1676 while (info->dependent_files[i] && *info->dependent_files[i]) {
1677 if (strequal(file, info->dependent_files[i]))
1686 /**********************************************************************
1687 Utility function to remove the dependent file pointed to by the
1688 input parameter from the list
1689 *********************************************************************/
1691 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1694 /* bump everything down a slot */
1696 while (files && files[idx+1]) {
1697 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1706 /**********************************************************************
1707 Check if any of the files used by src are also used by drv
1708 *********************************************************************/
1710 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1711 struct spoolss_DriverInfo8 *src,
1712 const struct spoolss_DriverInfo8 *drv)
1714 bool in_use = False;
1720 /* check each file. Remove it from the src structure if it overlaps */
1722 if (drv_file_in_use(src->driver_path, drv)) {
1724 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1725 src->driver_path = talloc_strdup(mem_ctx, "");
1726 if (!src->driver_path) { return false; }
1729 if (drv_file_in_use(src->data_file, drv)) {
1731 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1732 src->data_file = talloc_strdup(mem_ctx, "");
1733 if (!src->data_file) { return false; }
1736 if (drv_file_in_use(src->config_file, drv)) {
1738 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1739 src->config_file = talloc_strdup(mem_ctx, "");
1740 if (!src->config_file) { return false; }
1743 if (drv_file_in_use(src->help_file, drv)) {
1745 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1746 src->help_file = talloc_strdup(mem_ctx, "");
1747 if (!src->help_file) { return false; }
1750 /* are there any dependentfiles to examine? */
1752 if (!src->dependent_files)
1755 while (src->dependent_files[i] && *src->dependent_files[i]) {
1756 if (drv_file_in_use(src->dependent_files[i], drv)) {
1758 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1759 trim_dependent_file(mem_ctx, src->dependent_files, i);
1767 /****************************************************************************
1768 Determine whether or not a particular driver files are currently being
1769 used by any other driver.
1771 Return value is True if any files were in use by other drivers
1772 and False otherwise.
1774 Upon return, *info has been modified to only contain the driver files
1775 which are not in use
1779 This needs to check all drivers to ensure that all files in use
1780 have been removed from *info, not just the ones in the first
1782 ****************************************************************************/
1784 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1785 const struct auth_serversupplied_info *server_info,
1786 struct messaging_context *msg_ctx,
1787 struct spoolss_DriverInfo8 *info)
1791 struct spoolss_DriverInfo8 *driver;
1792 bool in_use = false;
1793 uint32_t num_drivers;
1794 const char **drivers;
1800 version = info->version;
1802 /* loop over all driver versions */
1804 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1806 /* get the list of drivers */
1808 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
1809 info->architecture, version,
1810 &num_drivers, &drivers);
1811 if (!W_ERROR_IS_OK(result)) {
1815 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1816 num_drivers, info->architecture, version));
1818 /* check each driver for overlap in files */
1820 for (i = 0; i < num_drivers; i++) {
1821 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1825 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
1826 info->architecture, drivers[i],
1828 if (!W_ERROR_IS_OK(result)) {
1829 talloc_free(drivers);
1833 /* check if d2 uses any files from d1 */
1834 /* only if this is a different driver than the one being deleted */
1836 if (!strequal(info->driver_name, driver->driver_name)) {
1837 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1838 /* mz: Do not instantly return -
1839 * we need to ensure this file isn't
1840 * also in use by other drivers. */
1845 talloc_free(driver);
1848 talloc_free(drivers);
1850 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1855 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1858 struct smb_filename *smb_fname = NULL;
1861 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1863 if (!NT_STATUS_IS_OK(status)) {
1867 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1869 TALLOC_FREE(smb_fname);
1873 /****************************************************************************
1874 Actually delete the driver files. Make sure that
1875 printer_driver_files_in_use() return False before calling
1877 ****************************************************************************/
1879 bool delete_driver_files(const struct auth_serversupplied_info *server_info,
1880 const struct spoolss_DriverInfo8 *r)
1885 connection_struct *conn;
1888 fstring printdollar;
1889 int printdollar_snum;
1896 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1897 r->driver_name, r->version));
1899 fstrcpy(printdollar, "print$");
1901 printdollar_snum = find_service(printdollar);
1902 if (printdollar_snum == -1) {
1906 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1907 lp_pathname(printdollar_snum),
1908 server_info, &oldcwd);
1909 if (!NT_STATUS_IS_OK(nt_status)) {
1910 DEBUG(0,("delete_driver_files: create_conn_struct "
1911 "returned %s\n", nt_errstr(nt_status)));
1915 if ( !CAN_WRITE(conn) ) {
1916 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1920 /* now delete the files; must strip the '\print$' string from
1923 if (r->driver_path && r->driver_path[0]) {
1924 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1926 DEBUG(10,("deleting driverfile [%s]\n", s));
1927 driver_unlink_internals(conn, file);
1931 if (r->config_file && r->config_file[0]) {
1932 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1934 DEBUG(10,("deleting configfile [%s]\n", s));
1935 driver_unlink_internals(conn, file);
1939 if (r->data_file && r->data_file[0]) {
1940 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1942 DEBUG(10,("deleting datafile [%s]\n", s));
1943 driver_unlink_internals(conn, file);
1947 if (r->help_file && r->help_file[0]) {
1948 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1950 DEBUG(10,("deleting helpfile [%s]\n", s));
1951 driver_unlink_internals(conn, file);
1955 /* check if we are done removing files */
1957 if (r->dependent_files) {
1958 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1961 /* bypass the "\print$" portion of the path */
1963 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1965 DEBUG(10,("deleting dependent file [%s]\n", file));
1966 driver_unlink_internals(conn, file);
1978 vfs_ChDir(conn, oldcwd);
1986 1: level not implemented
1987 2: file doesn't exist
1988 3: can't allocate memory
1989 4: can't free memory
1990 5: non existant struct
1994 A printer and a printer driver are 2 different things.
1995 NT manages them separatelly, Samba does the same.
1996 Why ? Simply because it's easier and it makes sense !
1998 Now explanation: You have 3 printers behind your samba server,
1999 2 of them are the same make and model (laser A and B). But laser B
2000 has an 3000 sheet feeder and laser A doesn't such an option.
2001 Your third printer is an old dot-matrix model for the accounting :-).
2003 If the /usr/local/samba/lib directory (default dir), you will have
2004 5 files to describe all of this.
2006 3 files for the printers (1 by printer):
2009 NTprinter_accounting
2010 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2011 NTdriver_printer model X
2012 NTdriver_printer model Y
2014 jfm: I should use this comment for the text file to explain
2015 same thing for the forms BTW.
2016 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2020 /* Convert generic access rights to printer object specific access rights.
2021 It turns out that NT4 security descriptors use generic access rights and
2022 NT5 the object specific ones. */
2024 void map_printer_permissions(struct security_descriptor *sd)
2028 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2029 se_map_generic(&sd->dacl->aces[i].access_mask,
2030 &printer_generic_mapping);
2034 void map_job_permissions(struct security_descriptor *sd)
2038 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2039 se_map_generic(&sd->dacl->aces[i].access_mask,
2040 &job_generic_mapping);
2045 /****************************************************************************
2046 Check a user has permissions to perform the given operation. We use the
2047 permission constants defined in include/rpc_spoolss.h to check the various
2048 actions we perform when checking printer access.
2050 PRINTER_ACCESS_ADMINISTER:
2051 print_queue_pause, print_queue_resume, update_printer_sec,
2052 update_printer, spoolss_addprinterex_level_2,
2053 _spoolss_setprinterdata
2058 JOB_ACCESS_ADMINISTER:
2059 print_job_delete, print_job_pause, print_job_resume,
2062 Try access control in the following order (for performance reasons):
2063 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2064 2) check security descriptor (bit comparisons in memory)
2065 3) "printer admins" (may result in numerous calls to winbind)
2067 ****************************************************************************/
2068 bool print_access_check(const struct auth_serversupplied_info *server_info,
2069 struct messaging_context *msg_ctx, int snum,
2072 struct spoolss_security_descriptor *secdesc = NULL;
2073 uint32 access_granted;
2078 TALLOC_CTX *mem_ctx = NULL;
2080 /* If user is NULL then use the current_user structure */
2082 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2084 if (server_info->utok.uid == sec_initial_uid()
2085 || security_token_has_privilege(server_info->ptok, SEC_PRIV_PRINT_OPERATOR)) {
2089 /* Get printer name */
2091 pname = lp_printername(snum);
2093 if (!pname || !*pname) {
2098 /* Get printer security descriptor */
2100 if(!(mem_ctx = talloc_init("print_access_check"))) {
2105 result = winreg_get_printer_secdesc(mem_ctx,
2106 get_server_info_system(),
2110 if (!W_ERROR_IS_OK(result)) {
2111 talloc_destroy(mem_ctx);
2116 if (access_type == JOB_ACCESS_ADMINISTER) {
2117 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2119 /* Create a child security descriptor to check permissions
2120 against. This is because print jobs are child objects
2121 objects of a printer. */
2122 status = se_create_child_secdesc(mem_ctx,
2126 parent_secdesc->owner_sid,
2127 parent_secdesc->group_sid,
2129 if (!NT_STATUS_IS_OK(status)) {
2130 talloc_destroy(mem_ctx);
2131 errno = map_errno_from_nt_status(status);
2135 map_job_permissions(secdesc);
2137 map_printer_permissions(secdesc);
2141 status = se_access_check(secdesc, server_info->ptok, access_type,
2144 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2146 /* see if we need to try the printer admin list */
2148 if (!NT_STATUS_IS_OK(status) &&
2149 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2150 server_info->info3->base.domain.string,
2151 NULL, server_info->ptok,
2152 lp_printer_admin(snum)))) {
2153 talloc_destroy(mem_ctx);
2157 talloc_destroy(mem_ctx);
2159 if (!NT_STATUS_IS_OK(status)) {
2163 return NT_STATUS_IS_OK(status);
2166 /****************************************************************************
2167 Check the time parameters allow a print operation.
2168 *****************************************************************************/
2170 bool print_time_access_check(const struct auth_serversupplied_info *server_info,
2171 struct messaging_context *msg_ctx,
2172 const char *servicename)
2174 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2177 time_t now = time(NULL);
2181 result = winreg_get_printer(NULL, server_info, msg_ctx,
2182 servicename, &pinfo2);
2183 if (!W_ERROR_IS_OK(result)) {
2187 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2192 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2194 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2198 TALLOC_FREE(pinfo2);
2207 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2208 const struct auth_serversupplied_info *server_info,
2209 struct messaging_context *msg_ctx,
2210 const char *printer)
2214 result = winreg_delete_printer_key(mem_ctx, server_info, msg_ctx,
2216 if (!W_ERROR_IS_OK(result)) {
2217 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",