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 "printing/pcap.h"
24 #include "printing/nt_printing_tdb.h"
25 #include "printing/nt_printing_migrate.h"
27 #include "registry/reg_objects.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "../librpc/gen_ndr/ndr_spoolss.h"
30 #include "rpc_server/spoolss/srv_spoolss_util.h"
31 #include "nt_printing.h"
33 #include "../librpc/gen_ndr/netlogon.h"
34 #include "../libcli/security/security.h"
35 #include "passdb/machine_sid.h"
36 #include "smbd/smbd.h"
40 /* Map generic permissions to printer object specific permissions */
42 const struct generic_mapping printer_generic_mapping = {
49 /* Map generic permissions to print server object specific permissions */
51 const struct generic_mapping printserver_generic_mapping = {
58 /* Map generic permissions to job object specific permissions */
60 const struct generic_mapping job_generic_mapping = {
67 static const struct print_architecture_table_node archi_table[]= {
69 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
70 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
71 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
72 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
73 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
74 {"Windows IA64", SPL_ARCH_IA64, 3 },
75 {"Windows x64", SPL_ARCH_X64, 3 },
79 /****************************************************************************
80 Open the NT printing tdbs. Done once before fork().
81 ****************************************************************************/
83 bool nt_printing_init(struct messaging_context *msg_ctx)
87 if (!nt_printing_tdb_upgrade()) {
92 * register callback to handle updating printers as new
93 * drivers are installed
95 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
96 do_drv_upgrade_printer);
98 /* of course, none of the message callbacks matter if you don't
99 tell messages.c that you interested in receiving PRINT_GENERAL
100 msgs. This is done in serverid_register() */
102 if ( lp_security() == SEC_ADS ) {
103 win_rc = check_published_printers(msg_ctx);
104 if (!W_ERROR_IS_OK(win_rc))
105 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
111 /*******************************************************************
112 Function to allow filename parsing "the old way".
113 ********************************************************************/
115 static NTSTATUS driver_unix_convert(connection_struct *conn,
116 const char *old_name,
117 struct smb_filename **smb_fname)
120 TALLOC_CTX *ctx = talloc_tos();
121 char *name = talloc_strdup(ctx, old_name);
124 return NT_STATUS_NO_MEMORY;
127 name = unix_clean_name(ctx, name);
129 return NT_STATUS_NO_MEMORY;
131 trim_string(name,"/","/");
133 status = unix_convert(ctx, conn, name, smb_fname, 0);
134 if (!NT_STATUS_IS_OK(status)) {
135 return NT_STATUS_NO_MEMORY;
141 /****************************************************************************
142 Function to do the mapping between the long architecture name and
144 ****************************************************************************/
146 const char *get_short_archi(const char *long_archi)
150 DEBUG(107,("Getting architecture dependent directory\n"));
153 } while ( (archi_table[i].long_archi!=NULL ) &&
154 StrCaseCmp(long_archi, archi_table[i].long_archi) );
156 if (archi_table[i].long_archi==NULL) {
157 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
161 /* this might be client code - but shouldn't this be an fstrcpy etc? */
163 DEBUGADD(108,("index: [%d]\n", i));
164 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
165 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
167 return archi_table[i].short_archi;
170 /****************************************************************************
171 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
172 There are two case to be covered here: PE (Portable Executable) and NE (New
173 Executable) files. Both files support the same INFO structure, but PE files
174 store the signature in unicode, and NE files store it as !unicode.
175 returns -1 on error, 1 on version info found, and 0 on no version info found.
176 ****************************************************************************/
178 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
184 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
185 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
186 fname, DOS_HEADER_SIZE));
190 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
191 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
192 fname, (unsigned long)byte_count));
193 goto no_version_info;
196 /* Is this really a DOS header? */
197 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
198 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
199 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
200 goto no_version_info;
203 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
204 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
205 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
207 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
208 goto no_version_info;
211 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
212 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
213 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
214 fname, (unsigned long)byte_count));
215 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
216 goto no_version_info;
219 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
220 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
221 unsigned int num_sections;
222 unsigned int section_table_bytes;
224 /* Just skip over optional header to get to section table */
225 if (SMB_VFS_LSEEK(fsp,
226 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
227 SEEK_CUR) == (SMB_OFF_T)-1) {
228 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
233 /* get the section table */
234 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
235 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
236 if (section_table_bytes == 0)
240 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
241 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
242 fname, section_table_bytes));
246 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
247 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
248 fname, (unsigned long)byte_count));
252 /* Iterate the section table looking for the resource section ".rsrc" */
253 for (i = 0; i < num_sections; i++) {
254 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
256 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
257 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
258 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
260 if (section_bytes == 0)
264 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
265 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
266 fname, section_bytes));
270 /* Seek to the start of the .rsrc section info */
271 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
272 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
277 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
278 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
279 fname, (unsigned long)byte_count));
283 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
286 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
287 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
288 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
289 /* Align to next long address */
290 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
292 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
293 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
294 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
296 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
297 fname, *major, *minor,
298 (*major>>16)&0xffff, *major&0xffff,
299 (*minor>>16)&0xffff, *minor&0xffff));
308 /* Version info not found, fall back to origin date/time */
309 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
313 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
314 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
315 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
316 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
317 /* At this point, we assume the file is in error. It still could be somthing
318 * else besides a NE file, but it unlikely at this point. */
322 /* Allocate a bit more space to speed up things */
324 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
325 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
326 fname, PE_HEADER_SIZE));
330 /* This is a HACK! I got tired of trying to sort through the messy
331 * 'NE' file format. If anyone wants to clean this up please have at
332 * it, but this works. 'NE' files will eventually fade away. JRR */
333 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
334 /* Cover case that should not occur in a well formed 'NE' .dll file */
335 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
337 for(i=0; i<byte_count; i++) {
338 /* Fast skip past data that can't possibly match */
339 if (buf[i] != 'V') continue;
341 /* Potential match data crosses buf boundry, move it to beginning
342 * of buf, and fill the buf with as much as it will hold. */
343 if (i>byte_count-VS_VERSION_INFO_SIZE) {
346 memcpy(buf, &buf[i], byte_count-i);
347 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
348 (byte_count-i))) < 0) {
350 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
355 byte_count = bc + (byte_count - i);
356 if (byte_count<VS_VERSION_INFO_SIZE) break;
361 /* Check that the full signature string and the magic number that
362 * follows exist (not a perfect solution, but the chances that this
363 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
364 * twice, as it is simpler to read the code. */
365 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
366 /* Compute skip alignment to next long address */
367 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
368 sizeof(VS_SIGNATURE)) & 3;
369 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
371 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
372 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
373 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
374 fname, *major, *minor,
375 (*major>>16)&0xffff, *major&0xffff,
376 (*minor>>16)&0xffff, *minor&0xffff));
383 /* Version info not found, fall back to origin date/time */
384 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
389 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
390 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
391 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
402 /****************************************************************************
403 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
404 share one or more files. During the MS installation process files are checked
405 to insure that only a newer version of a shared file is installed over an
406 older version. There are several possibilities for this comparison. If there
407 is no previous version, the new one is newer (obviously). If either file is
408 missing the version info structure, compare the creation date (on Unix use
409 the modification date). Otherwise chose the numerically larger version number.
410 ****************************************************************************/
412 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
414 bool use_version = true;
418 time_t new_create_time;
422 time_t old_create_time;
424 struct smb_filename *smb_fname = NULL;
425 files_struct *fsp = NULL;
431 SET_STAT_INVALID(st);
432 new_create_time = (time_t)0;
433 old_create_time = (time_t)0;
435 /* Get file version info (if available) for previous file (if it exists) */
436 status = driver_unix_convert(conn, old_file, &smb_fname);
437 if (!NT_STATUS_IS_OK(status)) {
441 status = SMB_VFS_CREATE_FILE(
444 0, /* root_dir_fid */
445 smb_fname, /* fname */
446 FILE_GENERIC_READ, /* access_mask */
447 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
448 FILE_OPEN, /* create_disposition*/
449 0, /* create_options */
450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
451 INTERNAL_OPEN_ONLY, /* oplock_request */
452 0, /* allocation_size */
453 0, /* private_flags */
459 if (!NT_STATUS_IS_OK(status)) {
460 /* Old file not found, so by definition new file is in fact newer */
461 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
462 "errno = %d\n", smb_fname_str_dbg(smb_fname),
468 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
474 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
477 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
480 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
481 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
482 (long)old_create_time));
485 close_file(NULL, fsp, NORMAL_CLOSE);
488 /* Get file version info (if available) for new file */
489 status = driver_unix_convert(conn, new_file, &smb_fname);
490 if (!NT_STATUS_IS_OK(status)) {
494 status = SMB_VFS_CREATE_FILE(
497 0, /* root_dir_fid */
498 smb_fname, /* fname */
499 FILE_GENERIC_READ, /* access_mask */
500 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
501 FILE_OPEN, /* create_disposition*/
502 0, /* create_options */
503 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
504 INTERNAL_OPEN_ONLY, /* oplock_request */
505 0, /* allocation_size */
506 0, /* private_flags */
512 if (!NT_STATUS_IS_OK(status)) {
513 /* New file not found, this shouldn't occur if the caller did its job */
514 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
515 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
519 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
525 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
528 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
531 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
532 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
533 (long)new_create_time));
536 close_file(NULL, fsp, NORMAL_CLOSE);
539 if (use_version && (new_major != old_major || new_minor != old_minor)) {
540 /* Compare versions and choose the larger version number */
541 if (new_major > old_major ||
542 (new_major == old_major && new_minor > old_minor)) {
544 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
549 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
555 /* Compare modification time/dates and choose the newest time/date */
556 if (new_create_time > old_create_time) {
557 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
562 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
570 close_file(NULL, fsp, NORMAL_CLOSE);
573 TALLOC_FREE(smb_fname);
577 /****************************************************************************
578 Determine the correct cVersion associated with an architecture and driver
579 ****************************************************************************/
580 static uint32 get_correct_cversion(struct pipes_struct *p,
581 const char *architecture,
582 const char *driverpath_in,
587 struct smb_filename *smb_fname = NULL;
588 char *driverpath = NULL;
589 files_struct *fsp = NULL;
590 connection_struct *conn = NULL;
592 char *printdollar = NULL;
593 int printdollar_snum;
595 *perr = WERR_INVALID_PARAM;
597 /* If architecture is Windows 95/98/ME, the version is always 0. */
598 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
599 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
604 /* If architecture is Windows x64, the version is always 3. */
605 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
606 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
611 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
616 if (printdollar_snum == -1) {
617 *perr = WERR_NO_SUCH_SHARE;
621 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
622 lp_pathname(printdollar_snum),
623 p->session_info, &oldcwd);
624 if (!NT_STATUS_IS_OK(nt_status)) {
625 DEBUG(0,("get_correct_cversion: create_conn_struct "
626 "returned %s\n", nt_errstr(nt_status)));
627 *perr = ntstatus_to_werror(nt_status);
631 nt_status = set_conn_force_user_group(conn, printdollar_snum);
632 if (!NT_STATUS_IS_OK(nt_status)) {
633 DEBUG(0, ("failed set force user / group\n"));
634 *perr = ntstatus_to_werror(nt_status);
635 goto error_free_conn;
638 if (!become_user(conn, get_current_vuid(conn))) {
639 DEBUG(0, ("failed to become user\n"));
640 *perr = WERR_ACCESS_DENIED;
641 goto error_free_conn;
644 /* Open the driver file (Portable Executable format) and determine the
645 * deriver the cversion. */
646 driverpath = talloc_asprintf(talloc_tos(),
655 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
656 if (!NT_STATUS_IS_OK(nt_status)) {
657 *perr = ntstatus_to_werror(nt_status);
661 nt_status = vfs_file_exist(conn, smb_fname);
662 if (!NT_STATUS_IS_OK(nt_status)) {
663 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
664 *perr = WERR_BADFILE;
668 nt_status = SMB_VFS_CREATE_FILE(
671 0, /* root_dir_fid */
672 smb_fname, /* fname */
673 FILE_GENERIC_READ, /* access_mask */
674 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
675 FILE_OPEN, /* create_disposition*/
676 0, /* create_options */
677 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
678 INTERNAL_OPEN_ONLY, /* oplock_request */
679 0, /* private_flags */
680 0, /* allocation_size */
686 if (!NT_STATUS_IS_OK(nt_status)) {
687 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
688 "%d\n", smb_fname_str_dbg(smb_fname), errno));
689 *perr = WERR_ACCESS_DENIED;
696 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
698 *perr = WERR_INVALID_PARAM;
701 DEBUG(6,("get_correct_cversion: Version info not "
703 smb_fname_str_dbg(smb_fname)));
704 *perr = WERR_INVALID_PARAM;
709 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
710 * for more details. Version in this case is not just the version of the
711 * file, but the version in the sense of kernal mode (2) vs. user mode
712 * (3) drivers. Other bits of the version fields are the version info.
715 cversion = major & 0x0000ffff;
717 case 2: /* WinNT drivers */
718 case 3: /* Win2K drivers */
722 DEBUG(6,("get_correct_cversion: cversion "
723 "invalid [%s] cversion = %d\n",
724 smb_fname_str_dbg(smb_fname),
729 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
730 " = 0x%x minor = 0x%x\n",
731 smb_fname_str_dbg(smb_fname), major, minor));
734 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
735 smb_fname_str_dbg(smb_fname), cversion));
741 TALLOC_FREE(smb_fname);
743 close_file(NULL, fsp, NORMAL_CLOSE);
746 vfs_ChDir(conn, oldcwd);
747 SMB_VFS_DISCONNECT(conn);
750 if (!NT_STATUS_IS_OK(*perr)) {
757 /****************************************************************************
758 ****************************************************************************/
760 #define strip_driver_path(_mem_ctx, _element) do { \
761 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
762 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
763 W_ERROR_HAVE_NO_MEMORY((_element)); \
767 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
768 struct pipes_struct *rpc_pipe,
769 const char *architecture,
770 const char **driver_path,
771 const char **data_file,
772 const char **config_file,
773 const char **help_file,
774 struct spoolss_StringArray *dependent_files,
775 enum spoolss_DriverOSVersion *version)
777 const char *short_architecture;
782 if (!*driver_path || !*data_file) {
783 return WERR_INVALID_PARAM;
786 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
787 return WERR_INVALID_PARAM;
790 /* clean up the driver name.
791 * we can get .\driver.dll
792 * or worse c:\windows\system\driver.dll !
794 /* using an intermediate string to not have overlaping memcpy()'s */
796 strip_driver_path(mem_ctx, *driver_path);
797 strip_driver_path(mem_ctx, *data_file);
799 strip_driver_path(mem_ctx, *config_file);
802 strip_driver_path(mem_ctx, *help_file);
805 if (dependent_files && dependent_files->string) {
806 for (i=0; dependent_files->string[i]; i++) {
807 strip_driver_path(mem_ctx, dependent_files->string[i]);
811 short_architecture = get_short_archi(architecture);
812 if (!short_architecture) {
813 return WERR_UNKNOWN_PRINTER_DRIVER;
816 /* jfm:7/16/2000 the client always sends the cversion=0.
817 * The server should check which version the driver is by reading
818 * the PE header of driver->driverpath.
820 * For Windows 95/98 the version is 0 (so the value sent is correct)
821 * For Windows NT (the architecture doesn't matter)
823 * NT 3.5/3.51: cversion=1
828 *version = get_correct_cversion(rpc_pipe, short_architecture,
830 if (*version == -1) {
837 /****************************************************************************
838 ****************************************************************************/
840 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
841 struct pipes_struct *rpc_pipe,
842 struct spoolss_AddDriverInfoCtr *r)
846 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
847 r->info.info3->architecture,
848 &r->info.info3->driver_path,
849 &r->info.info3->data_file,
850 &r->info.info3->config_file,
851 &r->info.info3->help_file,
852 r->info.info3->dependent_files,
853 &r->info.info3->version);
855 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
856 r->info.info6->architecture,
857 &r->info.info6->driver_path,
858 &r->info.info6->data_file,
859 &r->info.info6->config_file,
860 &r->info.info6->help_file,
861 r->info.info6->dependent_files,
862 &r->info.info6->version);
864 return WERR_NOT_SUPPORTED;
868 /****************************************************************************
869 This function sucks and should be replaced. JRA.
870 ****************************************************************************/
872 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
873 const struct spoolss_AddDriverInfo6 *src)
875 dst->version = src->version;
877 dst->driver_name = src->driver_name;
878 dst->architecture = src->architecture;
879 dst->driver_path = src->driver_path;
880 dst->data_file = src->data_file;
881 dst->config_file = src->config_file;
882 dst->help_file = src->help_file;
883 dst->monitor_name = src->monitor_name;
884 dst->default_datatype = src->default_datatype;
885 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
886 dst->dependent_files = src->dependent_files;
889 /****************************************************************************
890 ****************************************************************************/
892 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
893 connection_struct *conn,
894 const char *driver_file,
895 const char *short_architecture,
896 uint32_t driver_version,
899 struct smb_filename *smb_fname_old = NULL;
900 struct smb_filename *smb_fname_new = NULL;
901 char *old_name = NULL;
902 char *new_name = NULL;
906 old_name = talloc_asprintf(mem_ctx, "%s/%s",
907 short_architecture, driver_file);
908 W_ERROR_HAVE_NO_MEMORY(old_name);
910 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
911 short_architecture, driver_version, driver_file);
912 if (new_name == NULL) {
913 TALLOC_FREE(old_name);
917 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
919 status = driver_unix_convert(conn, old_name, &smb_fname_old);
920 if (!NT_STATUS_IS_OK(status)) {
925 /* Setup a synthetic smb_filename struct */
926 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
927 if (!smb_fname_new) {
932 smb_fname_new->base_name = new_name;
934 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
935 "'%s'\n", smb_fname_old->base_name,
936 smb_fname_new->base_name));
938 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
939 OPENX_FILE_EXISTS_TRUNCATE |
940 OPENX_FILE_CREATE_IF_NOT_EXIST,
943 if (!NT_STATUS_IS_OK(status)) {
944 DEBUG(0,("move_driver_file_to_download_area: Unable "
945 "to rename [%s] to [%s]: %s\n",
946 smb_fname_old->base_name, new_name,
948 ret = WERR_ACCESS_DENIED;
955 TALLOC_FREE(smb_fname_old);
956 TALLOC_FREE(smb_fname_new);
960 WERROR move_driver_to_download_area(struct pipes_struct *p,
961 struct spoolss_AddDriverInfoCtr *r)
963 struct spoolss_AddDriverInfo3 *driver;
964 struct spoolss_AddDriverInfo3 converted_driver;
965 const char *short_architecture;
966 struct smb_filename *smb_dname = NULL;
967 char *new_dir = NULL;
968 connection_struct *conn = NULL;
971 TALLOC_CTX *ctx = talloc_tos();
974 char *printdollar = NULL;
975 int printdollar_snum;
976 WERROR err = WERR_OK;
980 driver = r->info.info3;
983 convert_level_6_to_level3(&converted_driver, r->info.info6);
984 driver = &converted_driver;
987 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
988 return WERR_UNKNOWN_LEVEL;
991 short_architecture = get_short_archi(driver->architecture);
992 if (!short_architecture) {
993 return WERR_UNKNOWN_PRINTER_DRIVER;
996 printdollar_snum = find_service(ctx, "print$", &printdollar);
1000 if (printdollar_snum == -1) {
1001 return WERR_NO_SUCH_SHARE;
1004 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1005 lp_pathname(printdollar_snum),
1006 p->session_info, &oldcwd);
1007 if (!NT_STATUS_IS_OK(nt_status)) {
1008 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1009 "returned %s\n", nt_errstr(nt_status)));
1010 err = ntstatus_to_werror(nt_status);
1014 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1015 if (!NT_STATUS_IS_OK(nt_status)) {
1016 DEBUG(0, ("failed set force user / group\n"));
1017 err = ntstatus_to_werror(nt_status);
1021 if (!become_user(conn, get_current_vuid(conn))) {
1022 DEBUG(0, ("failed to become user\n"));
1023 err = WERR_ACCESS_DENIED;
1027 new_dir = talloc_asprintf(ctx,
1035 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1036 if (!NT_STATUS_IS_OK(nt_status)) {
1041 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1043 nt_status = create_directory(conn, NULL, smb_dname);
1044 if (!NT_STATUS_IS_OK(nt_status)
1045 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1046 DEBUG(0, ("failed to create driver destination directory: %s\n",
1047 nt_errstr(nt_status)));
1048 err = ntstatus_to_werror(nt_status);
1052 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1053 * listed for this driver which has already been moved, skip it (note:
1054 * drivers may list the same file name several times. Then check if the
1055 * file already exists in archi\version\, if so, check that the version
1056 * info (or time stamps if version info is unavailable) is newer (or the
1057 * date is later). If it is, move it to archi\version\filexxx.yyy.
1058 * Otherwise, delete the file.
1060 * If a file is not moved to archi\version\ because of an error, all the
1061 * rest of the 'unmoved' driver files are removed from archi\. If one or
1062 * more of the driver's files was already moved to archi\version\, it
1063 * potentially leaves the driver in a partially updated state. Version
1064 * trauma will most likely occur if an client attempts to use any printer
1065 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1066 * done is appropriate... later JRR
1069 DEBUG(5,("Moving files now !\n"));
1071 if (driver->driver_path && strlen(driver->driver_path)) {
1073 err = move_driver_file_to_download_area(ctx,
1075 driver->driver_path,
1079 if (!W_ERROR_IS_OK(err)) {
1084 if (driver->data_file && strlen(driver->data_file)) {
1085 if (!strequal(driver->data_file, driver->driver_path)) {
1087 err = move_driver_file_to_download_area(ctx,
1093 if (!W_ERROR_IS_OK(err)) {
1099 if (driver->config_file && strlen(driver->config_file)) {
1100 if (!strequal(driver->config_file, driver->driver_path) &&
1101 !strequal(driver->config_file, driver->data_file)) {
1103 err = move_driver_file_to_download_area(ctx,
1105 driver->config_file,
1109 if (!W_ERROR_IS_OK(err)) {
1115 if (driver->help_file && strlen(driver->help_file)) {
1116 if (!strequal(driver->help_file, driver->driver_path) &&
1117 !strequal(driver->help_file, driver->data_file) &&
1118 !strequal(driver->help_file, driver->config_file)) {
1120 err = move_driver_file_to_download_area(ctx,
1126 if (!W_ERROR_IS_OK(err)) {
1132 if (driver->dependent_files && driver->dependent_files->string) {
1133 for (i=0; driver->dependent_files->string[i]; i++) {
1134 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1135 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1136 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1137 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1139 for (j=0; j < i; j++) {
1140 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1145 err = move_driver_file_to_download_area(ctx,
1147 driver->dependent_files->string[i],
1151 if (!W_ERROR_IS_OK(err)) {
1163 TALLOC_FREE(smb_dname);
1166 vfs_ChDir(conn, oldcwd);
1167 SMB_VFS_DISCONNECT(conn);
1174 /****************************************************************************
1175 Create and allocate a default devicemode.
1176 ****************************************************************************/
1178 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1179 const char *devicename,
1180 struct spoolss_DeviceMode **devmode)
1182 struct spoolss_DeviceMode *dm;
1185 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1190 dname = talloc_asprintf(dm, "%s", devicename);
1191 if (dname == NULL) {
1194 if (strlen(dname) > MAXDEVICENAME) {
1195 dname[MAXDEVICENAME] = '\0';
1197 dm->devicename = dname;
1199 dm->formname = talloc_strdup(dm, "Letter");
1200 if (dm->formname == NULL) {
1204 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1205 dm->driverversion = 0x0400;
1207 dm->__driverextra_length = 0;
1208 dm->fields = DEVMODE_FORMNAME |
1210 DEVMODE_PRINTQUALITY |
1211 DEVMODE_DEFAULTSOURCE |
1215 DEVMODE_ORIENTATION;
1216 dm->orientation = DMORIENT_PORTRAIT;
1217 dm->papersize = DMPAPER_LETTER;
1218 dm->paperlength = 0;
1222 dm->defaultsource = DMBIN_FORMSOURCE;
1223 dm->printquality = DMRES_HIGH; /* 0x0258 */
1224 dm->color = DMRES_MONOCHROME;
1225 dm->duplex = DMDUP_SIMPLEX;
1226 dm->yresolution = 0;
1227 dm->ttoption = DMTT_SUBDEV;
1228 dm->collate = DMCOLLATE_FALSE;
1238 dm->displayflags = 0;
1239 dm->displayfrequency = 0;
1242 dm->panningwidth = 0;
1243 dm->panningheight = 0;
1245 dm->driverextra_data.data = NULL;
1246 dm->driverextra_data.length = 0;
1252 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1253 struct spoolss_security_descriptor **secdesc)
1255 struct security_ace ace[7]; /* max number of ace entries */
1258 struct security_acl *psa = NULL;
1259 struct security_descriptor *psd = NULL;
1260 struct dom_sid adm_sid;
1263 /* Create an ACE where Everyone is allowed to print */
1265 sa = PRINTER_ACE_PRINT;
1266 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1267 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1269 /* Add the domain admins group if we are a DC */
1272 struct dom_sid domadmins_sid;
1274 sid_compose(&domadmins_sid, get_global_sam_sid(),
1277 sa = PRINTER_ACE_FULL_CONTROL;
1278 init_sec_ace(&ace[i++], &domadmins_sid,
1279 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1280 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1281 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1282 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1284 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1285 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1287 sa = PRINTER_ACE_FULL_CONTROL;
1288 init_sec_ace(&ace[i++], &adm_sid,
1289 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1290 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1291 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1292 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1295 /* add BUILTIN\Administrators as FULL CONTROL */
1297 sa = PRINTER_ACE_FULL_CONTROL;
1298 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1299 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1300 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1301 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1302 SEC_ACE_TYPE_ACCESS_ALLOWED,
1303 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1305 /* add BUILTIN\Print Operators as FULL CONTROL */
1307 sa = PRINTER_ACE_FULL_CONTROL;
1308 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1309 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1310 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1311 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1312 SEC_ACE_TYPE_ACCESS_ALLOWED,
1313 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1315 /* Make the security descriptor owned by the BUILTIN\Administrators */
1317 /* The ACL revision number in rpc_secdesc.h differs from the one
1318 created by NT when setting ACE entries in printer
1319 descriptors. NT4 complains about the property being edited by a
1322 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1323 psd = make_sec_desc(mem_ctx,
1325 SEC_DESC_SELF_RELATIVE,
1326 &global_sid_Builtin_Administrators,
1327 &global_sid_Builtin_Administrators,
1334 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1338 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1339 (unsigned int)sd_size));
1346 /****************************************************************************
1347 ***************************************************************************/
1349 static char *win_driver;
1350 static char *os2_driver;
1352 static const char *get_win_driver(void)
1354 if (win_driver == NULL) {
1360 static const char *get_os2_driver(void)
1362 if (os2_driver == NULL) {
1368 static bool set_driver_mapping(const char *from, const char *to)
1370 SAFE_FREE(win_driver);
1371 SAFE_FREE(os2_driver);
1373 win_driver = SMB_STRDUP(from);
1374 os2_driver = SMB_STRDUP(to);
1376 if (win_driver == NULL || os2_driver == NULL) {
1377 SAFE_FREE(win_driver);
1378 SAFE_FREE(os2_driver);
1387 * @brief Map a Windows driver to a OS/2 driver.
1389 * @param[in] mem_ctx The memory context to use.
1391 * @param[in,out] pdrivername The drivername of Windows to remap.
1393 * @return WERR_OK on success, a corresponding WERROR on failure.
1395 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1397 const char *mapfile = lp_os2_driver_map();
1398 char **lines = NULL;
1399 const char *drivername;
1403 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1404 return WERR_INVALID_PARAMETER;
1407 drivername = *pdrivername;
1409 if (mapfile[0] == '\0') {
1410 return WERR_BADFILE;
1413 if (strequal(drivername, get_win_driver())) {
1414 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1415 drivername, get_os2_driver()));
1416 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1417 if (drivername == NULL) {
1420 *pdrivername = drivername;
1424 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1425 if (numlines == 0 || lines == NULL) {
1426 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1431 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1433 for( i = 0; i < numlines; i++) {
1434 char *nt_name = lines[i];
1435 char *os2_name = strchr(nt_name, '=');
1437 if (os2_name == NULL) {
1443 while (isspace(*nt_name)) {
1447 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1452 int l = strlen(nt_name);
1453 while (l && isspace(nt_name[l - 1])) {
1459 while (isspace(*os2_name)) {
1464 int l = strlen(os2_name);
1465 while (l && isspace(os2_name[l-1])) {
1471 if (strequal(nt_name, drivername)) {
1472 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1473 set_driver_mapping(drivername, os2_name);
1474 drivername = talloc_strdup(mem_ctx, os2_name);
1476 if (drivername == NULL) {
1479 *pdrivername = drivername;
1488 /****************************************************************************
1489 ****************************************************************************/
1491 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1492 struct spoolss_DriverInfo8 *_info8)
1494 struct spoolss_DriverInfo8 info8;
1500 info8.version = r->info.info3->version;
1501 info8.driver_name = r->info.info3->driver_name;
1502 info8.architecture = r->info.info3->architecture;
1503 info8.driver_path = r->info.info3->driver_path;
1504 info8.data_file = r->info.info3->data_file;
1505 info8.config_file = r->info.info3->config_file;
1506 info8.help_file = r->info.info3->help_file;
1507 info8.monitor_name = r->info.info3->monitor_name;
1508 info8.default_datatype = r->info.info3->default_datatype;
1509 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1510 info8.dependent_files = r->info.info3->dependent_files->string;
1514 info8.version = r->info.info6->version;
1515 info8.driver_name = r->info.info6->driver_name;
1516 info8.architecture = r->info.info6->architecture;
1517 info8.driver_path = r->info.info6->driver_path;
1518 info8.data_file = r->info.info6->data_file;
1519 info8.config_file = r->info.info6->config_file;
1520 info8.help_file = r->info.info6->help_file;
1521 info8.monitor_name = r->info.info6->monitor_name;
1522 info8.default_datatype = r->info.info6->default_datatype;
1523 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1524 info8.dependent_files = r->info.info6->dependent_files->string;
1526 info8.driver_date = r->info.info6->driver_date;
1527 info8.driver_version = r->info.info6->driver_version;
1528 info8.manufacturer_name = r->info.info6->manufacturer_name;
1529 info8.manufacturer_url = r->info.info6->manufacturer_url;
1530 info8.hardware_id = r->info.info6->hardware_id;
1531 info8.provider = r->info.info6->provider;
1534 info8.version = r->info.info8->version;
1535 info8.driver_name = r->info.info8->driver_name;
1536 info8.architecture = r->info.info8->architecture;
1537 info8.driver_path = r->info.info8->driver_path;
1538 info8.data_file = r->info.info8->data_file;
1539 info8.config_file = r->info.info8->config_file;
1540 info8.help_file = r->info.info8->help_file;
1541 info8.monitor_name = r->info.info8->monitor_name;
1542 info8.default_datatype = r->info.info8->default_datatype;
1543 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1544 info8.dependent_files = r->info.info8->dependent_files->string;
1546 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1547 info8.previous_names = r->info.info8->previous_names->string;
1549 info8.driver_date = r->info.info8->driver_date;
1550 info8.driver_version = r->info.info8->driver_version;
1551 info8.manufacturer_name = r->info.info8->manufacturer_name;
1552 info8.manufacturer_url = r->info.info8->manufacturer_url;
1553 info8.hardware_id = r->info.info8->hardware_id;
1554 info8.provider = r->info.info8->provider;
1555 info8.print_processor = r->info.info8->print_processor;
1556 info8.vendor_setup = r->info.info8->vendor_setup;
1557 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1558 info8.color_profiles = r->info.info8->color_profiles->string;
1560 info8.inf_path = r->info.info8->inf_path;
1561 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1562 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1563 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1565 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1566 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1578 /****************************************************************************
1579 Determine whether or not a particular driver is currently assigned
1581 ****************************************************************************/
1583 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1584 const struct auth_serversupplied_info *session_info,
1585 struct messaging_context *msg_ctx,
1586 const struct spoolss_DriverInfo8 *r)
1589 int n_services = lp_numservices();
1590 bool in_use = False;
1591 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1598 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1600 /* loop through the printers.tdb and check for the drivername */
1602 for (snum=0; snum<n_services && !in_use; snum++) {
1603 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1607 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
1608 lp_servicename(snum),
1610 if (!W_ERROR_IS_OK(result)) {
1611 continue; /* skip */
1614 if (strequal(r->driver_name, pinfo2->drivername)) {
1618 TALLOC_FREE(pinfo2);
1621 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1624 struct spoolss_DriverInfo8 *driver;
1627 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1629 /* we can still remove the driver if there is one of
1630 "Windows NT x86" version 2 or 3 left */
1632 if (!strequal("Windows NT x86", r->architecture)) {
1633 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1638 } else if (r->version == 2) {
1639 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1643 } else if (r->version == 3) {
1644 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1649 DEBUG(0, ("printer_driver_in_use: ERROR!"
1650 " unknown driver version (%d)\n",
1652 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1655 /* now check the error code */
1657 if ( W_ERROR_IS_OK(werr) ) {
1658 /* it's ok to remove the driver, we have other architctures left */
1660 talloc_free(driver);
1664 /* report that the driver is not in use by default */
1670 /**********************************************************************
1671 Check to see if a ogiven file is in use by *info
1672 *********************************************************************/
1674 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1681 /* mz: skip files that are in the list but already deleted */
1682 if (!file || !file[0]) {
1686 if (strequal(file, info->driver_path))
1689 if (strequal(file, info->data_file))
1692 if (strequal(file, info->config_file))
1695 if (strequal(file, info->help_file))
1698 /* see of there are any dependent files to examine */
1700 if (!info->dependent_files)
1703 while (info->dependent_files[i] && *info->dependent_files[i]) {
1704 if (strequal(file, info->dependent_files[i]))
1713 /**********************************************************************
1714 Utility function to remove the dependent file pointed to by the
1715 input parameter from the list
1716 *********************************************************************/
1718 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1721 /* bump everything down a slot */
1723 while (files && files[idx+1]) {
1724 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1733 /**********************************************************************
1734 Check if any of the files used by src are also used by drv
1735 *********************************************************************/
1737 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1738 struct spoolss_DriverInfo8 *src,
1739 const struct spoolss_DriverInfo8 *drv)
1741 bool in_use = False;
1747 /* check each file. Remove it from the src structure if it overlaps */
1749 if (drv_file_in_use(src->driver_path, drv)) {
1751 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1752 src->driver_path = talloc_strdup(mem_ctx, "");
1753 if (!src->driver_path) { return false; }
1756 if (drv_file_in_use(src->data_file, drv)) {
1758 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1759 src->data_file = talloc_strdup(mem_ctx, "");
1760 if (!src->data_file) { return false; }
1763 if (drv_file_in_use(src->config_file, drv)) {
1765 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1766 src->config_file = talloc_strdup(mem_ctx, "");
1767 if (!src->config_file) { return false; }
1770 if (drv_file_in_use(src->help_file, drv)) {
1772 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1773 src->help_file = talloc_strdup(mem_ctx, "");
1774 if (!src->help_file) { return false; }
1777 /* are there any dependentfiles to examine? */
1779 if (!src->dependent_files)
1782 while (src->dependent_files[i] && *src->dependent_files[i]) {
1783 if (drv_file_in_use(src->dependent_files[i], drv)) {
1785 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1786 trim_dependent_file(mem_ctx, src->dependent_files, i);
1794 /****************************************************************************
1795 Determine whether or not a particular driver files are currently being
1796 used by any other driver.
1798 Return value is True if any files were in use by other drivers
1799 and False otherwise.
1801 Upon return, *info has been modified to only contain the driver files
1802 which are not in use
1806 This needs to check all drivers to ensure that all files in use
1807 have been removed from *info, not just the ones in the first
1809 ****************************************************************************/
1811 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1812 const struct auth_serversupplied_info *session_info,
1813 struct messaging_context *msg_ctx,
1814 struct spoolss_DriverInfo8 *info)
1818 struct spoolss_DriverInfo8 *driver;
1819 bool in_use = false;
1820 uint32_t num_drivers;
1821 const char **drivers;
1827 version = info->version;
1829 /* loop over all driver versions */
1831 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1833 /* get the list of drivers */
1835 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
1836 info->architecture, version,
1837 &num_drivers, &drivers);
1838 if (!W_ERROR_IS_OK(result)) {
1842 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1843 num_drivers, info->architecture, version));
1845 /* check each driver for overlap in files */
1847 for (i = 0; i < num_drivers; i++) {
1848 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1852 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1853 info->architecture, drivers[i],
1855 if (!W_ERROR_IS_OK(result)) {
1856 talloc_free(drivers);
1860 /* check if d2 uses any files from d1 */
1861 /* only if this is a different driver than the one being deleted */
1863 if (!strequal(info->driver_name, driver->driver_name)) {
1864 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1865 /* mz: Do not instantly return -
1866 * we need to ensure this file isn't
1867 * also in use by other drivers. */
1872 talloc_free(driver);
1875 talloc_free(drivers);
1877 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1882 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1885 struct smb_filename *smb_fname = NULL;
1888 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1890 if (!NT_STATUS_IS_OK(status)) {
1894 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1896 TALLOC_FREE(smb_fname);
1900 /****************************************************************************
1901 Actually delete the driver files. Make sure that
1902 printer_driver_files_in_use() return False before calling
1904 ****************************************************************************/
1906 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
1907 const struct spoolss_DriverInfo8 *r)
1912 connection_struct *conn;
1915 char *printdollar = NULL;
1916 int printdollar_snum;
1923 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1924 r->driver_name, r->version));
1926 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1930 if (printdollar_snum == -1) {
1934 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1935 lp_pathname(printdollar_snum),
1936 session_info, &oldcwd);
1937 if (!NT_STATUS_IS_OK(nt_status)) {
1938 DEBUG(0,("delete_driver_files: create_conn_struct "
1939 "returned %s\n", nt_errstr(nt_status)));
1943 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1944 if (!NT_STATUS_IS_OK(nt_status)) {
1945 DEBUG(0, ("failed set force user / group\n"));
1950 if (!become_user(conn, get_current_vuid(conn))) {
1951 DEBUG(0, ("failed to become user\n"));
1956 if ( !CAN_WRITE(conn) ) {
1957 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1962 /* now delete the files; must strip the '\print$' string from
1965 if (r->driver_path && r->driver_path[0]) {
1966 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1968 DEBUG(10,("deleting driverfile [%s]\n", s));
1969 driver_unlink_internals(conn, file);
1973 if (r->config_file && r->config_file[0]) {
1974 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1976 DEBUG(10,("deleting configfile [%s]\n", s));
1977 driver_unlink_internals(conn, file);
1981 if (r->data_file && r->data_file[0]) {
1982 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1984 DEBUG(10,("deleting datafile [%s]\n", s));
1985 driver_unlink_internals(conn, file);
1989 if (r->help_file && r->help_file[0]) {
1990 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1992 DEBUG(10,("deleting helpfile [%s]\n", s));
1993 driver_unlink_internals(conn, file);
1997 /* check if we are done removing files */
1999 if (r->dependent_files) {
2000 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2003 /* bypass the "\print$" portion of the path */
2005 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2007 DEBUG(10,("deleting dependent file [%s]\n", file));
2008 driver_unlink_internals(conn, file);
2020 vfs_ChDir(conn, oldcwd);
2021 SMB_VFS_DISCONNECT(conn);
2029 1: level not implemented
2030 2: file doesn't exist
2031 3: can't allocate memory
2032 4: can't free memory
2033 5: non existant struct
2037 A printer and a printer driver are 2 different things.
2038 NT manages them separatelly, Samba does the same.
2039 Why ? Simply because it's easier and it makes sense !
2041 Now explanation: You have 3 printers behind your samba server,
2042 2 of them are the same make and model (laser A and B). But laser B
2043 has an 3000 sheet feeder and laser A doesn't such an option.
2044 Your third printer is an old dot-matrix model for the accounting :-).
2046 If the /usr/local/samba/lib directory (default dir), you will have
2047 5 files to describe all of this.
2049 3 files for the printers (1 by printer):
2052 NTprinter_accounting
2053 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2054 NTdriver_printer model X
2055 NTdriver_printer model Y
2057 jfm: I should use this comment for the text file to explain
2058 same thing for the forms BTW.
2059 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2063 /* Convert generic access rights to printer object specific access rights.
2064 It turns out that NT4 security descriptors use generic access rights and
2065 NT5 the object specific ones. */
2067 void map_printer_permissions(struct security_descriptor *sd)
2071 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2072 se_map_generic(&sd->dacl->aces[i].access_mask,
2073 &printer_generic_mapping);
2077 void map_job_permissions(struct security_descriptor *sd)
2081 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2082 se_map_generic(&sd->dacl->aces[i].access_mask,
2083 &job_generic_mapping);
2088 /****************************************************************************
2089 Check a user has permissions to perform the given operation. We use the
2090 permission constants defined in include/rpc_spoolss.h to check the various
2091 actions we perform when checking printer access.
2093 PRINTER_ACCESS_ADMINISTER:
2094 print_queue_pause, print_queue_resume, update_printer_sec,
2095 update_printer, spoolss_addprinterex_level_2,
2096 _spoolss_setprinterdata
2101 JOB_ACCESS_ADMINISTER:
2102 print_job_delete, print_job_pause, print_job_resume,
2105 Try access control in the following order (for performance reasons):
2106 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2107 2) check security descriptor (bit comparisons in memory)
2108 3) "printer admins" (may result in numerous calls to winbind)
2110 ****************************************************************************/
2111 bool print_access_check(const struct auth_serversupplied_info *session_info,
2112 struct messaging_context *msg_ctx, int snum,
2115 struct spoolss_security_descriptor *secdesc = NULL;
2116 uint32 access_granted;
2121 TALLOC_CTX *mem_ctx = NULL;
2123 /* If user is NULL then use the current_user structure */
2125 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2127 if (session_info->utok.uid == sec_initial_uid()
2128 || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
2132 /* Get printer name */
2134 pname = lp_printername(snum);
2136 if (!pname || !*pname) {
2141 /* Get printer security descriptor */
2143 if(!(mem_ctx = talloc_init("print_access_check"))) {
2148 result = winreg_get_printer_secdesc(mem_ctx,
2149 get_session_info_system(),
2153 if (!W_ERROR_IS_OK(result)) {
2154 talloc_destroy(mem_ctx);
2159 if (access_type == JOB_ACCESS_ADMINISTER) {
2160 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2162 /* Create a child security descriptor to check permissions
2163 against. This is because print jobs are child objects
2164 objects of a printer. */
2165 status = se_create_child_secdesc(mem_ctx,
2169 parent_secdesc->owner_sid,
2170 parent_secdesc->group_sid,
2172 if (!NT_STATUS_IS_OK(status)) {
2173 talloc_destroy(mem_ctx);
2174 errno = map_errno_from_nt_status(status);
2178 map_job_permissions(secdesc);
2180 map_printer_permissions(secdesc);
2184 status = se_access_check(secdesc, session_info->security_token, access_type,
2187 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2189 /* see if we need to try the printer admin list */
2191 if (!NT_STATUS_IS_OK(status) &&
2192 (token_contains_name_in_list(uidtoname(session_info->utok.uid),
2193 session_info->info3->base.domain.string,
2194 NULL, session_info->security_token,
2195 lp_printer_admin(snum)))) {
2196 talloc_destroy(mem_ctx);
2200 talloc_destroy(mem_ctx);
2202 if (!NT_STATUS_IS_OK(status)) {
2206 return NT_STATUS_IS_OK(status);
2209 /****************************************************************************
2210 Check the time parameters allow a print operation.
2211 *****************************************************************************/
2213 bool print_time_access_check(const struct auth_serversupplied_info *session_info,
2214 struct messaging_context *msg_ctx,
2215 const char *servicename)
2217 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2220 time_t now = time(NULL);
2224 result = winreg_get_printer(NULL, session_info, msg_ctx,
2225 servicename, &pinfo2);
2226 if (!W_ERROR_IS_OK(result)) {
2230 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2235 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2237 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2241 TALLOC_FREE(pinfo2);
2250 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2251 const struct auth_serversupplied_info *session_info,
2252 struct messaging_context *msg_ctx,
2253 const char *printer)
2257 result = winreg_delete_printer_key(mem_ctx, session_info, msg_ctx,
2259 if (!W_ERROR_IS_OK(result)) {
2260 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",