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/spoolss/srv_spoolss_util.h"
32 #include "nt_printing.h"
34 #include "../librpc/gen_ndr/netlogon.h"
35 #include "../libcli/security/security.h"
36 #include "passdb/machine_sid.h"
37 #include "smbd/smbd.h"
39 /* Map generic permissions to printer object specific permissions */
41 const struct generic_mapping printer_generic_mapping = {
48 /* Map generic permissions to print server object specific permissions */
50 const struct generic_mapping printserver_generic_mapping = {
57 /* Map generic permissions to job object specific permissions */
59 const struct generic_mapping job_generic_mapping = {
66 static const struct print_architecture_table_node archi_table[]= {
68 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
69 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
70 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
71 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
72 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
73 {"Windows IA64", SPL_ARCH_IA64, 3 },
74 {"Windows x64", SPL_ARCH_X64, 3 },
78 /****************************************************************************
79 Open the NT printing tdbs. Done once before fork().
80 ****************************************************************************/
82 bool nt_printing_init(struct messaging_context *msg_ctx)
86 if (!nt_printing_tdb_upgrade()) {
91 * register callback to handle updating printers as new
92 * drivers are installed
94 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
95 do_drv_upgrade_printer);
97 /* of course, none of the message callbacks matter if you don't
98 tell messages.c that you interested in receiving PRINT_GENERAL
99 msgs. This is done in serverid_register() */
101 if ( lp_security() == SEC_ADS ) {
102 win_rc = check_published_printers(msg_ctx);
103 if (!W_ERROR_IS_OK(win_rc))
104 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
110 /*******************************************************************
111 Function to allow filename parsing "the old way".
112 ********************************************************************/
114 static NTSTATUS driver_unix_convert(connection_struct *conn,
115 const char *old_name,
116 struct smb_filename **smb_fname)
119 TALLOC_CTX *ctx = talloc_tos();
120 char *name = talloc_strdup(ctx, old_name);
123 return NT_STATUS_NO_MEMORY;
126 name = unix_clean_name(ctx, name);
128 return NT_STATUS_NO_MEMORY;
130 trim_string(name,"/","/");
132 status = unix_convert(ctx, conn, name, smb_fname, 0);
133 if (!NT_STATUS_IS_OK(status)) {
134 return NT_STATUS_NO_MEMORY;
140 /****************************************************************************
141 Function to do the mapping between the long architecture name and
143 ****************************************************************************/
145 const char *get_short_archi(const char *long_archi)
149 DEBUG(107,("Getting architecture dependent directory\n"));
152 } while ( (archi_table[i].long_archi!=NULL ) &&
153 StrCaseCmp(long_archi, archi_table[i].long_archi) );
155 if (archi_table[i].long_archi==NULL) {
156 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
160 /* this might be client code - but shouldn't this be an fstrcpy etc? */
162 DEBUGADD(108,("index: [%d]\n", i));
163 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
164 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
166 return archi_table[i].short_archi;
169 /****************************************************************************
170 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
171 There are two case to be covered here: PE (Portable Executable) and NE (New
172 Executable) files. Both files support the same INFO structure, but PE files
173 store the signature in unicode, and NE files store it as !unicode.
174 returns -1 on error, 1 on version info found, and 0 on no version info found.
175 ****************************************************************************/
177 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
183 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
184 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
185 fname, DOS_HEADER_SIZE));
189 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
190 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
191 fname, (unsigned long)byte_count));
192 goto no_version_info;
195 /* Is this really a DOS header? */
196 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
197 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
198 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
199 goto no_version_info;
202 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
203 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
204 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
206 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
207 goto no_version_info;
210 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
211 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
212 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
213 fname, (unsigned long)byte_count));
214 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
215 goto no_version_info;
218 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
219 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
220 unsigned int num_sections;
221 unsigned int section_table_bytes;
223 /* Just skip over optional header to get to section table */
224 if (SMB_VFS_LSEEK(fsp,
225 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
226 SEEK_CUR) == (SMB_OFF_T)-1) {
227 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
232 /* get the section table */
233 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
234 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
235 if (section_table_bytes == 0)
239 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
240 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
241 fname, section_table_bytes));
245 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
246 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
247 fname, (unsigned long)byte_count));
251 /* Iterate the section table looking for the resource section ".rsrc" */
252 for (i = 0; i < num_sections; i++) {
253 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
255 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
256 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
257 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
259 if (section_bytes == 0)
263 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
264 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
265 fname, section_bytes));
269 /* Seek to the start of the .rsrc section info */
270 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
271 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
276 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
277 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
278 fname, (unsigned long)byte_count));
282 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
285 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
286 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
287 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
288 /* Align to next long address */
289 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
291 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
292 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
293 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
295 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
296 fname, *major, *minor,
297 (*major>>16)&0xffff, *major&0xffff,
298 (*minor>>16)&0xffff, *minor&0xffff));
307 /* Version info not found, fall back to origin date/time */
308 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
312 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
313 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
314 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
315 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
316 /* At this point, we assume the file is in error. It still could be somthing
317 * else besides a NE file, but it unlikely at this point. */
321 /* Allocate a bit more space to speed up things */
323 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
324 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
325 fname, PE_HEADER_SIZE));
329 /* This is a HACK! I got tired of trying to sort through the messy
330 * 'NE' file format. If anyone wants to clean this up please have at
331 * it, but this works. 'NE' files will eventually fade away. JRR */
332 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
333 /* Cover case that should not occur in a well formed 'NE' .dll file */
334 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
336 for(i=0; i<byte_count; i++) {
337 /* Fast skip past data that can't possibly match */
338 if (buf[i] != 'V') continue;
340 /* Potential match data crosses buf boundry, move it to beginning
341 * of buf, and fill the buf with as much as it will hold. */
342 if (i>byte_count-VS_VERSION_INFO_SIZE) {
345 memcpy(buf, &buf[i], byte_count-i);
346 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
347 (byte_count-i))) < 0) {
349 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
354 byte_count = bc + (byte_count - i);
355 if (byte_count<VS_VERSION_INFO_SIZE) break;
360 /* Check that the full signature string and the magic number that
361 * follows exist (not a perfect solution, but the chances that this
362 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
363 * twice, as it is simpler to read the code. */
364 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
365 /* Compute skip alignment to next long address */
366 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
367 sizeof(VS_SIGNATURE)) & 3;
368 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
370 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
371 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
372 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
373 fname, *major, *minor,
374 (*major>>16)&0xffff, *major&0xffff,
375 (*minor>>16)&0xffff, *minor&0xffff));
382 /* Version info not found, fall back to origin date/time */
383 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
388 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
389 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
390 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
401 /****************************************************************************
402 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
403 share one or more files. During the MS installation process files are checked
404 to insure that only a newer version of a shared file is installed over an
405 older version. There are several possibilities for this comparison. If there
406 is no previous version, the new one is newer (obviously). If either file is
407 missing the version info structure, compare the creation date (on Unix use
408 the modification date). Otherwise chose the numerically larger version number.
409 ****************************************************************************/
411 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
413 bool use_version = true;
417 time_t new_create_time;
421 time_t old_create_time;
423 struct smb_filename *smb_fname = NULL;
424 files_struct *fsp = NULL;
430 SET_STAT_INVALID(st);
431 new_create_time = (time_t)0;
432 old_create_time = (time_t)0;
434 /* Get file version info (if available) for previous file (if it exists) */
435 status = driver_unix_convert(conn, old_file, &smb_fname);
436 if (!NT_STATUS_IS_OK(status)) {
440 status = SMB_VFS_CREATE_FILE(
443 0, /* root_dir_fid */
444 smb_fname, /* fname */
445 FILE_GENERIC_READ, /* access_mask */
446 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
447 FILE_OPEN, /* create_disposition*/
448 0, /* create_options */
449 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
450 INTERNAL_OPEN_ONLY, /* oplock_request */
451 0, /* allocation_size */
452 0, /* private_flags */
458 if (!NT_STATUS_IS_OK(status)) {
459 /* Old file not found, so by definition new file is in fact newer */
460 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
461 "errno = %d\n", smb_fname_str_dbg(smb_fname),
467 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
473 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
476 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
479 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
480 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
481 (long)old_create_time));
484 close_file(NULL, fsp, NORMAL_CLOSE);
487 /* Get file version info (if available) for new file */
488 status = driver_unix_convert(conn, new_file, &smb_fname);
489 if (!NT_STATUS_IS_OK(status)) {
493 status = SMB_VFS_CREATE_FILE(
496 0, /* root_dir_fid */
497 smb_fname, /* fname */
498 FILE_GENERIC_READ, /* access_mask */
499 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
500 FILE_OPEN, /* create_disposition*/
501 0, /* create_options */
502 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
503 INTERNAL_OPEN_ONLY, /* oplock_request */
504 0, /* allocation_size */
505 0, /* private_flags */
511 if (!NT_STATUS_IS_OK(status)) {
512 /* New file not found, this shouldn't occur if the caller did its job */
513 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
514 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
518 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
524 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
527 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
530 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
531 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
532 (long)new_create_time));
535 close_file(NULL, fsp, NORMAL_CLOSE);
538 if (use_version && (new_major != old_major || new_minor != old_minor)) {
539 /* Compare versions and choose the larger version number */
540 if (new_major > old_major ||
541 (new_major == old_major && new_minor > old_minor)) {
543 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
548 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
554 /* Compare modification time/dates and choose the newest time/date */
555 if (new_create_time > old_create_time) {
556 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
561 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
569 close_file(NULL, fsp, NORMAL_CLOSE);
572 TALLOC_FREE(smb_fname);
576 /****************************************************************************
577 Determine the correct cVersion associated with an architecture and driver
578 ****************************************************************************/
579 static uint32 get_correct_cversion(struct pipes_struct *p,
580 const char *architecture,
581 const char *driverpath_in,
586 struct smb_filename *smb_fname = NULL;
587 char *driverpath = NULL;
588 files_struct *fsp = NULL;
589 connection_struct *conn = NULL;
591 char *printdollar = NULL;
592 int printdollar_snum;
594 *perr = WERR_INVALID_PARAM;
596 /* If architecture is Windows 95/98/ME, the version is always 0. */
597 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
598 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
603 /* If architecture is Windows x64, the version is always 3. */
604 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
605 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
610 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
615 if (printdollar_snum == -1) {
616 *perr = WERR_NO_SUCH_SHARE;
620 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
621 lp_pathname(printdollar_snum),
622 p->session_info, &oldcwd);
623 if (!NT_STATUS_IS_OK(nt_status)) {
624 DEBUG(0,("get_correct_cversion: create_conn_struct "
625 "returned %s\n", nt_errstr(nt_status)));
626 *perr = ntstatus_to_werror(nt_status);
630 nt_status = set_conn_force_user_group(conn, printdollar_snum);
631 if (!NT_STATUS_IS_OK(nt_status)) {
632 DEBUG(0, ("failed set force user / group\n"));
633 *perr = ntstatus_to_werror(nt_status);
634 goto error_free_conn;
637 if (!become_user(conn, get_current_vuid(conn))) {
638 DEBUG(0, ("failed to become user\n"));
639 *perr = WERR_ACCESS_DENIED;
640 goto error_free_conn;
643 /* Open the driver file (Portable Executable format) and determine the
644 * deriver the cversion. */
645 driverpath = talloc_asprintf(talloc_tos(),
654 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
655 if (!NT_STATUS_IS_OK(nt_status)) {
656 *perr = ntstatus_to_werror(nt_status);
660 nt_status = vfs_file_exist(conn, smb_fname);
661 if (!NT_STATUS_IS_OK(nt_status)) {
662 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
663 *perr = WERR_BADFILE;
667 nt_status = SMB_VFS_CREATE_FILE(
670 0, /* root_dir_fid */
671 smb_fname, /* fname */
672 FILE_GENERIC_READ, /* access_mask */
673 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
674 FILE_OPEN, /* create_disposition*/
675 0, /* create_options */
676 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
677 INTERNAL_OPEN_ONLY, /* oplock_request */
678 0, /* private_flags */
679 0, /* allocation_size */
685 if (!NT_STATUS_IS_OK(nt_status)) {
686 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
687 "%d\n", smb_fname_str_dbg(smb_fname), errno));
688 *perr = WERR_ACCESS_DENIED;
695 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
697 *perr = WERR_INVALID_PARAM;
700 DEBUG(6,("get_correct_cversion: Version info not "
702 smb_fname_str_dbg(smb_fname)));
703 *perr = WERR_INVALID_PARAM;
708 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
709 * for more details. Version in this case is not just the version of the
710 * file, but the version in the sense of kernal mode (2) vs. user mode
711 * (3) drivers. Other bits of the version fields are the version info.
714 cversion = major & 0x0000ffff;
716 case 2: /* WinNT drivers */
717 case 3: /* Win2K drivers */
721 DEBUG(6,("get_correct_cversion: cversion "
722 "invalid [%s] cversion = %d\n",
723 smb_fname_str_dbg(smb_fname),
728 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
729 " = 0x%x minor = 0x%x\n",
730 smb_fname_str_dbg(smb_fname), major, minor));
733 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
734 smb_fname_str_dbg(smb_fname), cversion));
740 TALLOC_FREE(smb_fname);
742 close_file(NULL, fsp, NORMAL_CLOSE);
745 vfs_ChDir(conn, oldcwd);
746 SMB_VFS_DISCONNECT(conn);
749 if (!NT_STATUS_IS_OK(*perr)) {
756 /****************************************************************************
757 ****************************************************************************/
759 #define strip_driver_path(_mem_ctx, _element) do { \
760 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
761 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
762 W_ERROR_HAVE_NO_MEMORY((_element)); \
766 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
767 struct pipes_struct *rpc_pipe,
768 const char *architecture,
769 const char **driver_path,
770 const char **data_file,
771 const char **config_file,
772 const char **help_file,
773 struct spoolss_StringArray *dependent_files,
774 enum spoolss_DriverOSVersion *version)
776 const char *short_architecture;
781 if (!*driver_path || !*data_file) {
782 return WERR_INVALID_PARAM;
785 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
786 return WERR_INVALID_PARAM;
789 /* clean up the driver name.
790 * we can get .\driver.dll
791 * or worse c:\windows\system\driver.dll !
793 /* using an intermediate string to not have overlaping memcpy()'s */
795 strip_driver_path(mem_ctx, *driver_path);
796 strip_driver_path(mem_ctx, *data_file);
798 strip_driver_path(mem_ctx, *config_file);
801 strip_driver_path(mem_ctx, *help_file);
804 if (dependent_files && dependent_files->string) {
805 for (i=0; dependent_files->string[i]; i++) {
806 strip_driver_path(mem_ctx, dependent_files->string[i]);
810 short_architecture = get_short_archi(architecture);
811 if (!short_architecture) {
812 return WERR_UNKNOWN_PRINTER_DRIVER;
815 /* jfm:7/16/2000 the client always sends the cversion=0.
816 * The server should check which version the driver is by reading
817 * the PE header of driver->driverpath.
819 * For Windows 95/98 the version is 0 (so the value sent is correct)
820 * For Windows NT (the architecture doesn't matter)
822 * NT 3.5/3.51: cversion=1
827 *version = get_correct_cversion(rpc_pipe, short_architecture,
829 if (*version == -1) {
836 /****************************************************************************
837 ****************************************************************************/
839 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
840 struct pipes_struct *rpc_pipe,
841 struct spoolss_AddDriverInfoCtr *r)
845 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
846 r->info.info3->architecture,
847 &r->info.info3->driver_path,
848 &r->info.info3->data_file,
849 &r->info.info3->config_file,
850 &r->info.info3->help_file,
851 r->info.info3->dependent_files,
852 &r->info.info3->version);
854 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
855 r->info.info6->architecture,
856 &r->info.info6->driver_path,
857 &r->info.info6->data_file,
858 &r->info.info6->config_file,
859 &r->info.info6->help_file,
860 r->info.info6->dependent_files,
861 &r->info.info6->version);
863 return WERR_NOT_SUPPORTED;
867 /****************************************************************************
868 This function sucks and should be replaced. JRA.
869 ****************************************************************************/
871 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
872 const struct spoolss_AddDriverInfo6 *src)
874 dst->version = src->version;
876 dst->driver_name = src->driver_name;
877 dst->architecture = src->architecture;
878 dst->driver_path = src->driver_path;
879 dst->data_file = src->data_file;
880 dst->config_file = src->config_file;
881 dst->help_file = src->help_file;
882 dst->monitor_name = src->monitor_name;
883 dst->default_datatype = src->default_datatype;
884 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
885 dst->dependent_files = src->dependent_files;
888 /****************************************************************************
889 ****************************************************************************/
891 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
892 connection_struct *conn,
893 const char *driver_file,
894 const char *short_architecture,
895 uint32_t driver_version,
898 struct smb_filename *smb_fname_old = NULL;
899 struct smb_filename *smb_fname_new = NULL;
900 char *old_name = NULL;
901 char *new_name = NULL;
905 old_name = talloc_asprintf(mem_ctx, "%s/%s",
906 short_architecture, driver_file);
907 W_ERROR_HAVE_NO_MEMORY(old_name);
909 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
910 short_architecture, driver_version, driver_file);
911 if (new_name == NULL) {
912 TALLOC_FREE(old_name);
916 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
918 status = driver_unix_convert(conn, old_name, &smb_fname_old);
919 if (!NT_STATUS_IS_OK(status)) {
924 /* Setup a synthetic smb_filename struct */
925 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
926 if (!smb_fname_new) {
931 smb_fname_new->base_name = new_name;
933 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
934 "'%s'\n", smb_fname_old->base_name,
935 smb_fname_new->base_name));
937 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
938 OPENX_FILE_EXISTS_TRUNCATE |
939 OPENX_FILE_CREATE_IF_NOT_EXIST,
942 if (!NT_STATUS_IS_OK(status)) {
943 DEBUG(0,("move_driver_file_to_download_area: Unable "
944 "to rename [%s] to [%s]: %s\n",
945 smb_fname_old->base_name, new_name,
947 ret = WERR_ACCESS_DENIED;
954 TALLOC_FREE(smb_fname_old);
955 TALLOC_FREE(smb_fname_new);
959 WERROR move_driver_to_download_area(struct pipes_struct *p,
960 struct spoolss_AddDriverInfoCtr *r)
962 struct spoolss_AddDriverInfo3 *driver;
963 struct spoolss_AddDriverInfo3 converted_driver;
964 const char *short_architecture;
965 struct smb_filename *smb_dname = NULL;
966 char *new_dir = NULL;
967 connection_struct *conn = NULL;
970 TALLOC_CTX *ctx = talloc_tos();
973 char *printdollar = NULL;
974 int printdollar_snum;
975 WERROR err = WERR_OK;
979 driver = r->info.info3;
982 convert_level_6_to_level3(&converted_driver, r->info.info6);
983 driver = &converted_driver;
986 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
987 return WERR_UNKNOWN_LEVEL;
990 short_architecture = get_short_archi(driver->architecture);
991 if (!short_architecture) {
992 return WERR_UNKNOWN_PRINTER_DRIVER;
995 printdollar_snum = find_service(ctx, "print$", &printdollar);
999 if (printdollar_snum == -1) {
1000 return WERR_NO_SUCH_SHARE;
1003 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1004 lp_pathname(printdollar_snum),
1005 p->session_info, &oldcwd);
1006 if (!NT_STATUS_IS_OK(nt_status)) {
1007 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1008 "returned %s\n", nt_errstr(nt_status)));
1009 err = ntstatus_to_werror(nt_status);
1013 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1014 if (!NT_STATUS_IS_OK(nt_status)) {
1015 DEBUG(0, ("failed set force user / group\n"));
1016 err = ntstatus_to_werror(nt_status);
1020 if (!become_user(conn, get_current_vuid(conn))) {
1021 DEBUG(0, ("failed to become user\n"));
1022 err = WERR_ACCESS_DENIED;
1026 new_dir = talloc_asprintf(ctx,
1034 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1035 if (!NT_STATUS_IS_OK(nt_status)) {
1040 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1042 nt_status = create_directory(conn, NULL, smb_dname);
1043 if (!NT_STATUS_IS_OK(nt_status)
1044 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1045 DEBUG(0, ("failed to create driver destination directory: %s\n",
1046 nt_errstr(nt_status)));
1047 err = ntstatus_to_werror(nt_status);
1051 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1052 * listed for this driver which has already been moved, skip it (note:
1053 * drivers may list the same file name several times. Then check if the
1054 * file already exists in archi\version\, if so, check that the version
1055 * info (or time stamps if version info is unavailable) is newer (or the
1056 * date is later). If it is, move it to archi\version\filexxx.yyy.
1057 * Otherwise, delete the file.
1059 * If a file is not moved to archi\version\ because of an error, all the
1060 * rest of the 'unmoved' driver files are removed from archi\. If one or
1061 * more of the driver's files was already moved to archi\version\, it
1062 * potentially leaves the driver in a partially updated state. Version
1063 * trauma will most likely occur if an client attempts to use any printer
1064 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1065 * done is appropriate... later JRR
1068 DEBUG(5,("Moving files now !\n"));
1070 if (driver->driver_path && strlen(driver->driver_path)) {
1072 err = move_driver_file_to_download_area(ctx,
1074 driver->driver_path,
1078 if (!W_ERROR_IS_OK(err)) {
1083 if (driver->data_file && strlen(driver->data_file)) {
1084 if (!strequal(driver->data_file, driver->driver_path)) {
1086 err = move_driver_file_to_download_area(ctx,
1092 if (!W_ERROR_IS_OK(err)) {
1098 if (driver->config_file && strlen(driver->config_file)) {
1099 if (!strequal(driver->config_file, driver->driver_path) &&
1100 !strequal(driver->config_file, driver->data_file)) {
1102 err = move_driver_file_to_download_area(ctx,
1104 driver->config_file,
1108 if (!W_ERROR_IS_OK(err)) {
1114 if (driver->help_file && strlen(driver->help_file)) {
1115 if (!strequal(driver->help_file, driver->driver_path) &&
1116 !strequal(driver->help_file, driver->data_file) &&
1117 !strequal(driver->help_file, driver->config_file)) {
1119 err = move_driver_file_to_download_area(ctx,
1125 if (!W_ERROR_IS_OK(err)) {
1131 if (driver->dependent_files && driver->dependent_files->string) {
1132 for (i=0; driver->dependent_files->string[i]; i++) {
1133 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1134 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1135 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1136 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1138 for (j=0; j < i; j++) {
1139 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1144 err = move_driver_file_to_download_area(ctx,
1146 driver->dependent_files->string[i],
1150 if (!W_ERROR_IS_OK(err)) {
1162 TALLOC_FREE(smb_dname);
1165 vfs_ChDir(conn, oldcwd);
1166 SMB_VFS_DISCONNECT(conn);
1173 /****************************************************************************
1174 Create and allocate a default devicemode.
1175 ****************************************************************************/
1177 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1178 const char *devicename,
1179 struct spoolss_DeviceMode **devmode)
1181 struct spoolss_DeviceMode *dm;
1184 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1189 dname = talloc_asprintf(dm, "%s", devicename);
1190 if (dname == NULL) {
1193 if (strlen(dname) > MAXDEVICENAME) {
1194 dname[MAXDEVICENAME] = '\0';
1196 dm->devicename = dname;
1198 dm->formname = talloc_strdup(dm, "Letter");
1199 if (dm->formname == NULL) {
1203 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1204 dm->driverversion = 0x0400;
1206 dm->__driverextra_length = 0;
1207 dm->fields = DEVMODE_FORMNAME |
1209 DEVMODE_PRINTQUALITY |
1210 DEVMODE_DEFAULTSOURCE |
1214 DEVMODE_ORIENTATION;
1215 dm->orientation = DMORIENT_PORTRAIT;
1216 dm->papersize = DMPAPER_LETTER;
1217 dm->paperlength = 0;
1221 dm->defaultsource = DMBIN_FORMSOURCE;
1222 dm->printquality = DMRES_HIGH; /* 0x0258 */
1223 dm->color = DMRES_MONOCHROME;
1224 dm->duplex = DMDUP_SIMPLEX;
1225 dm->yresolution = 0;
1226 dm->ttoption = DMTT_SUBDEV;
1227 dm->collate = DMCOLLATE_FALSE;
1237 dm->displayflags = 0;
1238 dm->displayfrequency = 0;
1241 dm->panningwidth = 0;
1242 dm->panningheight = 0;
1244 dm->driverextra_data.data = NULL;
1245 dm->driverextra_data.length = 0;
1251 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1252 struct spoolss_security_descriptor **secdesc)
1254 struct security_ace ace[7]; /* max number of ace entries */
1257 struct security_acl *psa = NULL;
1258 struct security_descriptor *psd = NULL;
1259 struct dom_sid adm_sid;
1262 /* Create an ACE where Everyone is allowed to print */
1264 sa = PRINTER_ACE_PRINT;
1265 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1266 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1268 /* Add the domain admins group if we are a DC */
1271 struct dom_sid domadmins_sid;
1273 sid_compose(&domadmins_sid, get_global_sam_sid(),
1276 sa = PRINTER_ACE_FULL_CONTROL;
1277 init_sec_ace(&ace[i++], &domadmins_sid,
1278 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1279 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1280 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1281 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1283 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1284 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1286 sa = PRINTER_ACE_FULL_CONTROL;
1287 init_sec_ace(&ace[i++], &adm_sid,
1288 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1289 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1290 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1291 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1294 /* add BUILTIN\Administrators as FULL CONTROL */
1296 sa = PRINTER_ACE_FULL_CONTROL;
1297 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1298 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1299 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1300 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1301 SEC_ACE_TYPE_ACCESS_ALLOWED,
1302 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1304 /* add BUILTIN\Print Operators as FULL CONTROL */
1306 sa = PRINTER_ACE_FULL_CONTROL;
1307 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1308 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1309 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1310 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1311 SEC_ACE_TYPE_ACCESS_ALLOWED,
1312 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1314 /* Make the security descriptor owned by the BUILTIN\Administrators */
1316 /* The ACL revision number in rpc_secdesc.h differs from the one
1317 created by NT when setting ACE entries in printer
1318 descriptors. NT4 complains about the property being edited by a
1321 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1322 psd = make_sec_desc(mem_ctx,
1324 SEC_DESC_SELF_RELATIVE,
1325 &global_sid_Builtin_Administrators,
1326 &global_sid_Builtin_Administrators,
1333 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1337 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1338 (unsigned int)sd_size));
1345 /****************************************************************************
1346 ***************************************************************************/
1348 static char *win_driver;
1349 static char *os2_driver;
1351 static const char *get_win_driver(void)
1353 if (win_driver == NULL) {
1359 static const char *get_os2_driver(void)
1361 if (os2_driver == NULL) {
1367 static bool set_driver_mapping(const char *from, const char *to)
1369 SAFE_FREE(win_driver);
1370 SAFE_FREE(os2_driver);
1372 win_driver = SMB_STRDUP(from);
1373 os2_driver = SMB_STRDUP(to);
1375 if (win_driver == NULL || os2_driver == NULL) {
1376 SAFE_FREE(win_driver);
1377 SAFE_FREE(os2_driver);
1386 * @brief Map a Windows driver to a OS/2 driver.
1388 * @param[in] mem_ctx The memory context to use.
1390 * @param[in,out] pdrivername The drivername of Windows to remap.
1392 * @return WERR_OK on success, a corresponding WERROR on failure.
1394 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1396 const char *mapfile = lp_os2_driver_map();
1397 char **lines = NULL;
1398 const char *drivername;
1402 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1403 return WERR_INVALID_PARAMETER;
1406 drivername = *pdrivername;
1408 if (mapfile[0] == '\0') {
1409 return WERR_BADFILE;
1412 if (strequal(drivername, get_win_driver())) {
1413 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1414 drivername, get_os2_driver()));
1415 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1416 if (drivername == NULL) {
1419 *pdrivername = drivername;
1423 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1424 if (numlines == 0 || lines == NULL) {
1425 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1430 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1432 for( i = 0; i < numlines; i++) {
1433 char *nt_name = lines[i];
1434 char *os2_name = strchr(nt_name, '=');
1436 if (os2_name == NULL) {
1442 while (isspace(*nt_name)) {
1446 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1451 int l = strlen(nt_name);
1452 while (l && isspace(nt_name[l - 1])) {
1458 while (isspace(*os2_name)) {
1463 int l = strlen(os2_name);
1464 while (l && isspace(os2_name[l-1])) {
1470 if (strequal(nt_name, drivername)) {
1471 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1472 set_driver_mapping(drivername, os2_name);
1473 drivername = talloc_strdup(mem_ctx, os2_name);
1475 if (drivername == NULL) {
1478 *pdrivername = drivername;
1487 /****************************************************************************
1488 ****************************************************************************/
1490 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1491 struct spoolss_DriverInfo8 *_info8)
1493 struct spoolss_DriverInfo8 info8;
1499 info8.version = r->info.info3->version;
1500 info8.driver_name = r->info.info3->driver_name;
1501 info8.architecture = r->info.info3->architecture;
1502 info8.driver_path = r->info.info3->driver_path;
1503 info8.data_file = r->info.info3->data_file;
1504 info8.config_file = r->info.info3->config_file;
1505 info8.help_file = r->info.info3->help_file;
1506 info8.monitor_name = r->info.info3->monitor_name;
1507 info8.default_datatype = r->info.info3->default_datatype;
1508 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1509 info8.dependent_files = r->info.info3->dependent_files->string;
1513 info8.version = r->info.info6->version;
1514 info8.driver_name = r->info.info6->driver_name;
1515 info8.architecture = r->info.info6->architecture;
1516 info8.driver_path = r->info.info6->driver_path;
1517 info8.data_file = r->info.info6->data_file;
1518 info8.config_file = r->info.info6->config_file;
1519 info8.help_file = r->info.info6->help_file;
1520 info8.monitor_name = r->info.info6->monitor_name;
1521 info8.default_datatype = r->info.info6->default_datatype;
1522 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1523 info8.dependent_files = r->info.info6->dependent_files->string;
1525 info8.driver_date = r->info.info6->driver_date;
1526 info8.driver_version = r->info.info6->driver_version;
1527 info8.manufacturer_name = r->info.info6->manufacturer_name;
1528 info8.manufacturer_url = r->info.info6->manufacturer_url;
1529 info8.hardware_id = r->info.info6->hardware_id;
1530 info8.provider = r->info.info6->provider;
1533 info8.version = r->info.info8->version;
1534 info8.driver_name = r->info.info8->driver_name;
1535 info8.architecture = r->info.info8->architecture;
1536 info8.driver_path = r->info.info8->driver_path;
1537 info8.data_file = r->info.info8->data_file;
1538 info8.config_file = r->info.info8->config_file;
1539 info8.help_file = r->info.info8->help_file;
1540 info8.monitor_name = r->info.info8->monitor_name;
1541 info8.default_datatype = r->info.info8->default_datatype;
1542 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1543 info8.dependent_files = r->info.info8->dependent_files->string;
1545 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1546 info8.previous_names = r->info.info8->previous_names->string;
1548 info8.driver_date = r->info.info8->driver_date;
1549 info8.driver_version = r->info.info8->driver_version;
1550 info8.manufacturer_name = r->info.info8->manufacturer_name;
1551 info8.manufacturer_url = r->info.info8->manufacturer_url;
1552 info8.hardware_id = r->info.info8->hardware_id;
1553 info8.provider = r->info.info8->provider;
1554 info8.print_processor = r->info.info8->print_processor;
1555 info8.vendor_setup = r->info.info8->vendor_setup;
1556 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1557 info8.color_profiles = r->info.info8->color_profiles->string;
1559 info8.inf_path = r->info.info8->inf_path;
1560 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1561 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1562 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1564 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1565 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1577 /****************************************************************************
1578 Determine whether or not a particular driver is currently assigned
1580 ****************************************************************************/
1582 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1583 const struct auth_serversupplied_info *session_info,
1584 struct messaging_context *msg_ctx,
1585 const struct spoolss_DriverInfo8 *r)
1588 int n_services = lp_numservices();
1589 bool in_use = False;
1590 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1597 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1599 /* loop through the printers.tdb and check for the drivername */
1601 for (snum=0; snum<n_services && !in_use; snum++) {
1602 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1606 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
1607 lp_servicename(snum),
1609 if (!W_ERROR_IS_OK(result)) {
1610 continue; /* skip */
1613 if (strequal(r->driver_name, pinfo2->drivername)) {
1617 TALLOC_FREE(pinfo2);
1620 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1623 struct spoolss_DriverInfo8 *driver;
1626 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1628 /* we can still remove the driver if there is one of
1629 "Windows NT x86" version 2 or 3 left */
1631 if (!strequal("Windows NT x86", r->architecture)) {
1632 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1637 } else if (r->version == 2) {
1638 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1642 } else if (r->version == 3) {
1643 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1648 DEBUG(0, ("printer_driver_in_use: ERROR!"
1649 " unknown driver version (%d)\n",
1651 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1654 /* now check the error code */
1656 if ( W_ERROR_IS_OK(werr) ) {
1657 /* it's ok to remove the driver, we have other architctures left */
1659 talloc_free(driver);
1663 /* report that the driver is not in use by default */
1669 /**********************************************************************
1670 Check to see if a ogiven file is in use by *info
1671 *********************************************************************/
1673 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1680 /* mz: skip files that are in the list but already deleted */
1681 if (!file || !file[0]) {
1685 if (strequal(file, info->driver_path))
1688 if (strequal(file, info->data_file))
1691 if (strequal(file, info->config_file))
1694 if (strequal(file, info->help_file))
1697 /* see of there are any dependent files to examine */
1699 if (!info->dependent_files)
1702 while (info->dependent_files[i] && *info->dependent_files[i]) {
1703 if (strequal(file, info->dependent_files[i]))
1712 /**********************************************************************
1713 Utility function to remove the dependent file pointed to by the
1714 input parameter from the list
1715 *********************************************************************/
1717 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1720 /* bump everything down a slot */
1722 while (files && files[idx+1]) {
1723 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1732 /**********************************************************************
1733 Check if any of the files used by src are also used by drv
1734 *********************************************************************/
1736 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1737 struct spoolss_DriverInfo8 *src,
1738 const struct spoolss_DriverInfo8 *drv)
1740 bool in_use = False;
1746 /* check each file. Remove it from the src structure if it overlaps */
1748 if (drv_file_in_use(src->driver_path, drv)) {
1750 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1751 src->driver_path = talloc_strdup(mem_ctx, "");
1752 if (!src->driver_path) { return false; }
1755 if (drv_file_in_use(src->data_file, drv)) {
1757 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1758 src->data_file = talloc_strdup(mem_ctx, "");
1759 if (!src->data_file) { return false; }
1762 if (drv_file_in_use(src->config_file, drv)) {
1764 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1765 src->config_file = talloc_strdup(mem_ctx, "");
1766 if (!src->config_file) { return false; }
1769 if (drv_file_in_use(src->help_file, drv)) {
1771 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1772 src->help_file = talloc_strdup(mem_ctx, "");
1773 if (!src->help_file) { return false; }
1776 /* are there any dependentfiles to examine? */
1778 if (!src->dependent_files)
1781 while (src->dependent_files[i] && *src->dependent_files[i]) {
1782 if (drv_file_in_use(src->dependent_files[i], drv)) {
1784 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1785 trim_dependent_file(mem_ctx, src->dependent_files, i);
1793 /****************************************************************************
1794 Determine whether or not a particular driver files are currently being
1795 used by any other driver.
1797 Return value is True if any files were in use by other drivers
1798 and False otherwise.
1800 Upon return, *info has been modified to only contain the driver files
1801 which are not in use
1805 This needs to check all drivers to ensure that all files in use
1806 have been removed from *info, not just the ones in the first
1808 ****************************************************************************/
1810 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1811 const struct auth_serversupplied_info *session_info,
1812 struct messaging_context *msg_ctx,
1813 struct spoolss_DriverInfo8 *info)
1817 struct spoolss_DriverInfo8 *driver;
1818 bool in_use = false;
1819 uint32_t num_drivers;
1820 const char **drivers;
1826 version = info->version;
1828 /* loop over all driver versions */
1830 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1832 /* get the list of drivers */
1834 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
1835 info->architecture, version,
1836 &num_drivers, &drivers);
1837 if (!W_ERROR_IS_OK(result)) {
1841 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1842 num_drivers, info->architecture, version));
1844 /* check each driver for overlap in files */
1846 for (i = 0; i < num_drivers; i++) {
1847 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1851 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1852 info->architecture, drivers[i],
1854 if (!W_ERROR_IS_OK(result)) {
1855 talloc_free(drivers);
1859 /* check if d2 uses any files from d1 */
1860 /* only if this is a different driver than the one being deleted */
1862 if (!strequal(info->driver_name, driver->driver_name)) {
1863 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1864 /* mz: Do not instantly return -
1865 * we need to ensure this file isn't
1866 * also in use by other drivers. */
1871 talloc_free(driver);
1874 talloc_free(drivers);
1876 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1881 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1884 struct smb_filename *smb_fname = NULL;
1887 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1889 if (!NT_STATUS_IS_OK(status)) {
1893 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1895 TALLOC_FREE(smb_fname);
1899 /****************************************************************************
1900 Actually delete the driver files. Make sure that
1901 printer_driver_files_in_use() return False before calling
1903 ****************************************************************************/
1905 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
1906 const struct spoolss_DriverInfo8 *r)
1911 connection_struct *conn;
1914 char *printdollar = NULL;
1915 int printdollar_snum;
1922 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1923 r->driver_name, r->version));
1925 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1929 if (printdollar_snum == -1) {
1933 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1934 lp_pathname(printdollar_snum),
1935 session_info, &oldcwd);
1936 if (!NT_STATUS_IS_OK(nt_status)) {
1937 DEBUG(0,("delete_driver_files: create_conn_struct "
1938 "returned %s\n", nt_errstr(nt_status)));
1942 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1943 if (!NT_STATUS_IS_OK(nt_status)) {
1944 DEBUG(0, ("failed set force user / group\n"));
1949 if (!become_user(conn, get_current_vuid(conn))) {
1950 DEBUG(0, ("failed to become user\n"));
1955 if ( !CAN_WRITE(conn) ) {
1956 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1961 /* now delete the files; must strip the '\print$' string from
1964 if (r->driver_path && r->driver_path[0]) {
1965 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1967 DEBUG(10,("deleting driverfile [%s]\n", s));
1968 driver_unlink_internals(conn, file);
1972 if (r->config_file && r->config_file[0]) {
1973 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1975 DEBUG(10,("deleting configfile [%s]\n", s));
1976 driver_unlink_internals(conn, file);
1980 if (r->data_file && r->data_file[0]) {
1981 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1983 DEBUG(10,("deleting datafile [%s]\n", s));
1984 driver_unlink_internals(conn, file);
1988 if (r->help_file && r->help_file[0]) {
1989 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1991 DEBUG(10,("deleting helpfile [%s]\n", s));
1992 driver_unlink_internals(conn, file);
1996 /* check if we are done removing files */
1998 if (r->dependent_files) {
1999 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2002 /* bypass the "\print$" portion of the path */
2004 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2006 DEBUG(10,("deleting dependent file [%s]\n", file));
2007 driver_unlink_internals(conn, file);
2019 vfs_ChDir(conn, oldcwd);
2020 SMB_VFS_DISCONNECT(conn);
2028 1: level not implemented
2029 2: file doesn't exist
2030 3: can't allocate memory
2031 4: can't free memory
2032 5: non existant struct
2036 A printer and a printer driver are 2 different things.
2037 NT manages them separatelly, Samba does the same.
2038 Why ? Simply because it's easier and it makes sense !
2040 Now explanation: You have 3 printers behind your samba server,
2041 2 of them are the same make and model (laser A and B). But laser B
2042 has an 3000 sheet feeder and laser A doesn't such an option.
2043 Your third printer is an old dot-matrix model for the accounting :-).
2045 If the /usr/local/samba/lib directory (default dir), you will have
2046 5 files to describe all of this.
2048 3 files for the printers (1 by printer):
2051 NTprinter_accounting
2052 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2053 NTdriver_printer model X
2054 NTdriver_printer model Y
2056 jfm: I should use this comment for the text file to explain
2057 same thing for the forms BTW.
2058 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2062 /* Convert generic access rights to printer object specific access rights.
2063 It turns out that NT4 security descriptors use generic access rights and
2064 NT5 the object specific ones. */
2066 void map_printer_permissions(struct security_descriptor *sd)
2070 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2071 se_map_generic(&sd->dacl->aces[i].access_mask,
2072 &printer_generic_mapping);
2076 void map_job_permissions(struct security_descriptor *sd)
2080 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2081 se_map_generic(&sd->dacl->aces[i].access_mask,
2082 &job_generic_mapping);
2087 /****************************************************************************
2088 Check a user has permissions to perform the given operation. We use the
2089 permission constants defined in include/rpc_spoolss.h to check the various
2090 actions we perform when checking printer access.
2092 PRINTER_ACCESS_ADMINISTER:
2093 print_queue_pause, print_queue_resume, update_printer_sec,
2094 update_printer, spoolss_addprinterex_level_2,
2095 _spoolss_setprinterdata
2100 JOB_ACCESS_ADMINISTER:
2101 print_job_delete, print_job_pause, print_job_resume,
2104 Try access control in the following order (for performance reasons):
2105 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2106 2) check security descriptor (bit comparisons in memory)
2107 3) "printer admins" (may result in numerous calls to winbind)
2109 ****************************************************************************/
2110 bool print_access_check(const struct auth_serversupplied_info *session_info,
2111 struct messaging_context *msg_ctx, int snum,
2114 struct spoolss_security_descriptor *secdesc = NULL;
2115 uint32 access_granted;
2120 TALLOC_CTX *mem_ctx = NULL;
2122 /* If user is NULL then use the current_user structure */
2124 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2126 if (session_info->utok.uid == sec_initial_uid()
2127 || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
2131 /* Get printer name */
2133 pname = lp_printername(snum);
2135 if (!pname || !*pname) {
2140 /* Get printer security descriptor */
2142 if(!(mem_ctx = talloc_init("print_access_check"))) {
2147 result = winreg_get_printer_secdesc(mem_ctx,
2148 get_session_info_system(),
2152 if (!W_ERROR_IS_OK(result)) {
2153 talloc_destroy(mem_ctx);
2158 if (access_type == JOB_ACCESS_ADMINISTER) {
2159 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2161 /* Create a child security descriptor to check permissions
2162 against. This is because print jobs are child objects
2163 objects of a printer. */
2164 status = se_create_child_secdesc(mem_ctx,
2168 parent_secdesc->owner_sid,
2169 parent_secdesc->group_sid,
2171 if (!NT_STATUS_IS_OK(status)) {
2172 talloc_destroy(mem_ctx);
2173 errno = map_errno_from_nt_status(status);
2177 map_job_permissions(secdesc);
2179 map_printer_permissions(secdesc);
2183 status = se_access_check(secdesc, session_info->security_token, access_type,
2186 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2188 /* see if we need to try the printer admin list */
2190 if (!NT_STATUS_IS_OK(status) &&
2191 (token_contains_name_in_list(uidtoname(session_info->utok.uid),
2192 session_info->info3->base.domain.string,
2193 NULL, session_info->security_token,
2194 lp_printer_admin(snum)))) {
2195 talloc_destroy(mem_ctx);
2199 talloc_destroy(mem_ctx);
2201 if (!NT_STATUS_IS_OK(status)) {
2205 return NT_STATUS_IS_OK(status);
2208 /****************************************************************************
2209 Check the time parameters allow a print operation.
2210 *****************************************************************************/
2212 bool print_time_access_check(const struct auth_serversupplied_info *session_info,
2213 struct messaging_context *msg_ctx,
2214 const char *servicename)
2216 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2219 time_t now = time(NULL);
2223 result = winreg_get_printer(NULL, session_info, msg_ctx,
2224 servicename, &pinfo2);
2225 if (!W_ERROR_IS_OK(result)) {
2229 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2234 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2236 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2240 TALLOC_FREE(pinfo2);
2249 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2250 const struct auth_serversupplied_info *session_info,
2251 struct messaging_context *msg_ctx,
2252 const char *printer)
2256 result = winreg_delete_printer_key(mem_ctx, session_info, msg_ctx,
2258 if (!W_ERROR_IS_OK(result)) {
2259 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",