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"
38 /* Map generic permissions to printer object specific permissions */
40 const struct generic_mapping printer_generic_mapping = {
47 /* Map generic permissions to print server object specific permissions */
49 const struct generic_mapping printserver_generic_mapping = {
56 /* Map generic permissions to job object specific permissions */
58 const struct generic_mapping job_generic_mapping = {
65 static const struct print_architecture_table_node archi_table[]= {
67 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
68 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
69 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
70 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
71 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
72 {"Windows IA64", SPL_ARCH_IA64, 3 },
73 {"Windows x64", SPL_ARCH_X64, 3 },
77 /****************************************************************************
78 Open the NT printing tdbs. Done once before fork().
79 ****************************************************************************/
81 bool nt_printing_init(struct messaging_context *msg_ctx)
85 if (!nt_printing_tdb_upgrade()) {
90 * register callback to handle updating printers as new
91 * drivers are installed
93 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
94 do_drv_upgrade_printer);
96 /* of course, none of the message callbacks matter if you don't
97 tell messages.c that you interested in receiving PRINT_GENERAL
98 msgs. This is done in serverid_register() */
100 if ( lp_security() == SEC_ADS ) {
101 win_rc = check_published_printers(msg_ctx);
102 if (!W_ERROR_IS_OK(win_rc))
103 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
109 /*******************************************************************
110 Function to allow filename parsing "the old way".
111 ********************************************************************/
113 static NTSTATUS driver_unix_convert(connection_struct *conn,
114 const char *old_name,
115 struct smb_filename **smb_fname)
118 TALLOC_CTX *ctx = talloc_tos();
119 char *name = talloc_strdup(ctx, old_name);
122 return NT_STATUS_NO_MEMORY;
125 name = unix_clean_name(ctx, name);
127 return NT_STATUS_NO_MEMORY;
129 trim_string(name,"/","/");
131 status = unix_convert(ctx, conn, name, smb_fname, 0);
132 if (!NT_STATUS_IS_OK(status)) {
133 return NT_STATUS_NO_MEMORY;
139 /****************************************************************************
140 Function to do the mapping between the long architecture name and
142 ****************************************************************************/
144 const char *get_short_archi(const char *long_archi)
148 DEBUG(107,("Getting architecture dependent directory\n"));
151 } while ( (archi_table[i].long_archi!=NULL ) &&
152 StrCaseCmp(long_archi, archi_table[i].long_archi) );
154 if (archi_table[i].long_archi==NULL) {
155 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
159 /* this might be client code - but shouldn't this be an fstrcpy etc? */
161 DEBUGADD(108,("index: [%d]\n", i));
162 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
163 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
165 return archi_table[i].short_archi;
168 /****************************************************************************
169 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
170 There are two case to be covered here: PE (Portable Executable) and NE (New
171 Executable) files. Both files support the same INFO structure, but PE files
172 store the signature in unicode, and NE files store it as !unicode.
173 returns -1 on error, 1 on version info found, and 0 on no version info found.
174 ****************************************************************************/
176 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
182 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
183 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
184 fname, DOS_HEADER_SIZE));
188 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
189 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
190 fname, (unsigned long)byte_count));
191 goto no_version_info;
194 /* Is this really a DOS header? */
195 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
196 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
197 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
198 goto no_version_info;
201 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
202 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
203 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
205 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
206 goto no_version_info;
209 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
210 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
211 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
212 fname, (unsigned long)byte_count));
213 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
214 goto no_version_info;
217 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
218 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
219 unsigned int num_sections;
220 unsigned int section_table_bytes;
222 /* Just skip over optional header to get to section table */
223 if (SMB_VFS_LSEEK(fsp,
224 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
225 SEEK_CUR) == (SMB_OFF_T)-1) {
226 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
231 /* get the section table */
232 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
233 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
234 if (section_table_bytes == 0)
238 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
239 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
240 fname, section_table_bytes));
244 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
245 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
246 fname, (unsigned long)byte_count));
250 /* Iterate the section table looking for the resource section ".rsrc" */
251 for (i = 0; i < num_sections; i++) {
252 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
254 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
255 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
256 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
258 if (section_bytes == 0)
262 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
263 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
264 fname, section_bytes));
268 /* Seek to the start of the .rsrc section info */
269 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
270 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
275 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
276 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
277 fname, (unsigned long)byte_count));
281 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
284 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
285 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
286 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
287 /* Align to next long address */
288 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
290 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
291 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
292 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
294 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
295 fname, *major, *minor,
296 (*major>>16)&0xffff, *major&0xffff,
297 (*minor>>16)&0xffff, *minor&0xffff));
306 /* Version info not found, fall back to origin date/time */
307 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
311 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
312 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
313 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
314 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
315 /* At this point, we assume the file is in error. It still could be somthing
316 * else besides a NE file, but it unlikely at this point. */
320 /* Allocate a bit more space to speed up things */
322 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
323 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
324 fname, PE_HEADER_SIZE));
328 /* This is a HACK! I got tired of trying to sort through the messy
329 * 'NE' file format. If anyone wants to clean this up please have at
330 * it, but this works. 'NE' files will eventually fade away. JRR */
331 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
332 /* Cover case that should not occur in a well formed 'NE' .dll file */
333 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
335 for(i=0; i<byte_count; i++) {
336 /* Fast skip past data that can't possibly match */
337 if (buf[i] != 'V') continue;
339 /* Potential match data crosses buf boundry, move it to beginning
340 * of buf, and fill the buf with as much as it will hold. */
341 if (i>byte_count-VS_VERSION_INFO_SIZE) {
344 memcpy(buf, &buf[i], byte_count-i);
345 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
346 (byte_count-i))) < 0) {
348 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
353 byte_count = bc + (byte_count - i);
354 if (byte_count<VS_VERSION_INFO_SIZE) break;
359 /* Check that the full signature string and the magic number that
360 * follows exist (not a perfect solution, but the chances that this
361 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
362 * twice, as it is simpler to read the code. */
363 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
364 /* Compute skip alignment to next long address */
365 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
366 sizeof(VS_SIGNATURE)) & 3;
367 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
369 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
370 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
371 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
372 fname, *major, *minor,
373 (*major>>16)&0xffff, *major&0xffff,
374 (*minor>>16)&0xffff, *minor&0xffff));
381 /* Version info not found, fall back to origin date/time */
382 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
387 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
388 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
389 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
400 /****************************************************************************
401 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
402 share one or more files. During the MS installation process files are checked
403 to insure that only a newer version of a shared file is installed over an
404 older version. There are several possibilities for this comparison. If there
405 is no previous version, the new one is newer (obviously). If either file is
406 missing the version info structure, compare the creation date (on Unix use
407 the modification date). Otherwise chose the numerically larger version number.
408 ****************************************************************************/
410 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
412 bool use_version = true;
416 time_t new_create_time;
420 time_t old_create_time;
422 struct smb_filename *smb_fname = NULL;
423 files_struct *fsp = NULL;
429 SET_STAT_INVALID(st);
430 new_create_time = (time_t)0;
431 old_create_time = (time_t)0;
433 /* Get file version info (if available) for previous file (if it exists) */
434 status = driver_unix_convert(conn, old_file, &smb_fname);
435 if (!NT_STATUS_IS_OK(status)) {
439 status = SMB_VFS_CREATE_FILE(
442 0, /* root_dir_fid */
443 smb_fname, /* fname */
444 FILE_GENERIC_READ, /* access_mask */
445 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
446 FILE_OPEN, /* create_disposition*/
447 0, /* create_options */
448 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
449 INTERNAL_OPEN_ONLY, /* oplock_request */
450 0, /* allocation_size */
451 0, /* private_flags */
457 if (!NT_STATUS_IS_OK(status)) {
458 /* Old file not found, so by definition new file is in fact newer */
459 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
460 "errno = %d\n", smb_fname_str_dbg(smb_fname),
466 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
472 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
475 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
478 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
479 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
480 (long)old_create_time));
483 close_file(NULL, fsp, NORMAL_CLOSE);
486 /* Get file version info (if available) for new file */
487 status = driver_unix_convert(conn, new_file, &smb_fname);
488 if (!NT_STATUS_IS_OK(status)) {
492 status = SMB_VFS_CREATE_FILE(
495 0, /* root_dir_fid */
496 smb_fname, /* fname */
497 FILE_GENERIC_READ, /* access_mask */
498 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
499 FILE_OPEN, /* create_disposition*/
500 0, /* create_options */
501 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
502 INTERNAL_OPEN_ONLY, /* oplock_request */
503 0, /* allocation_size */
504 0, /* private_flags */
510 if (!NT_STATUS_IS_OK(status)) {
511 /* New file not found, this shouldn't occur if the caller did its job */
512 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
513 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
517 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
523 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
526 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
529 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
530 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
531 (long)new_create_time));
534 close_file(NULL, fsp, NORMAL_CLOSE);
537 if (use_version && (new_major != old_major || new_minor != old_minor)) {
538 /* Compare versions and choose the larger version number */
539 if (new_major > old_major ||
540 (new_major == old_major && new_minor > old_minor)) {
542 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
547 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
553 /* Compare modification time/dates and choose the newest time/date */
554 if (new_create_time > old_create_time) {
555 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
560 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
568 close_file(NULL, fsp, NORMAL_CLOSE);
571 TALLOC_FREE(smb_fname);
575 /****************************************************************************
576 Determine the correct cVersion associated with an architecture and driver
577 ****************************************************************************/
578 static uint32 get_correct_cversion(struct pipes_struct *p,
579 const char *architecture,
580 const char *driverpath_in,
585 struct smb_filename *smb_fname = NULL;
586 char *driverpath = NULL;
587 files_struct *fsp = NULL;
588 connection_struct *conn = NULL;
590 char *printdollar = NULL;
591 int printdollar_snum;
593 *perr = WERR_INVALID_PARAM;
595 /* If architecture is Windows 95/98/ME, the version is always 0. */
596 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
597 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
602 /* If architecture is Windows x64, the version is always 3. */
603 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
604 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
609 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
614 if (printdollar_snum == -1) {
615 *perr = WERR_NO_SUCH_SHARE;
619 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
620 lp_pathname(printdollar_snum),
621 p->session_info, &oldcwd);
622 if (!NT_STATUS_IS_OK(nt_status)) {
623 DEBUG(0,("get_correct_cversion: create_conn_struct "
624 "returned %s\n", nt_errstr(nt_status)));
625 *perr = ntstatus_to_werror(nt_status);
629 nt_status = set_conn_force_user_group(conn, printdollar_snum);
630 if (!NT_STATUS_IS_OK(nt_status)) {
631 DEBUG(0, ("failed set force user / group\n"));
632 *perr = ntstatus_to_werror(nt_status);
633 goto error_free_conn;
636 if (!become_user(conn, get_current_vuid(conn))) {
637 DEBUG(0, ("failed to become user\n"));
638 *perr = WERR_ACCESS_DENIED;
639 goto error_free_conn;
642 /* Open the driver file (Portable Executable format) and determine the
643 * deriver the cversion. */
644 driverpath = talloc_asprintf(talloc_tos(),
653 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
654 if (!NT_STATUS_IS_OK(nt_status)) {
655 *perr = ntstatus_to_werror(nt_status);
659 nt_status = vfs_file_exist(conn, smb_fname);
660 if (!NT_STATUS_IS_OK(nt_status)) {
661 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
662 *perr = WERR_BADFILE;
666 nt_status = SMB_VFS_CREATE_FILE(
669 0, /* root_dir_fid */
670 smb_fname, /* fname */
671 FILE_GENERIC_READ, /* access_mask */
672 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
673 FILE_OPEN, /* create_disposition*/
674 0, /* create_options */
675 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
676 INTERNAL_OPEN_ONLY, /* oplock_request */
677 0, /* private_flags */
678 0, /* allocation_size */
684 if (!NT_STATUS_IS_OK(nt_status)) {
685 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
686 "%d\n", smb_fname_str_dbg(smb_fname), errno));
687 *perr = WERR_ACCESS_DENIED;
694 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
696 *perr = WERR_INVALID_PARAM;
699 DEBUG(6,("get_correct_cversion: Version info not "
701 smb_fname_str_dbg(smb_fname)));
702 *perr = WERR_INVALID_PARAM;
707 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
708 * for more details. Version in this case is not just the version of the
709 * file, but the version in the sense of kernal mode (2) vs. user mode
710 * (3) drivers. Other bits of the version fields are the version info.
713 cversion = major & 0x0000ffff;
715 case 2: /* WinNT drivers */
716 case 3: /* Win2K drivers */
720 DEBUG(6,("get_correct_cversion: cversion "
721 "invalid [%s] cversion = %d\n",
722 smb_fname_str_dbg(smb_fname),
727 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
728 " = 0x%x minor = 0x%x\n",
729 smb_fname_str_dbg(smb_fname), major, minor));
732 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
733 smb_fname_str_dbg(smb_fname), cversion));
739 TALLOC_FREE(smb_fname);
741 close_file(NULL, fsp, NORMAL_CLOSE);
744 vfs_ChDir(conn, oldcwd);
745 SMB_VFS_DISCONNECT(conn);
748 if (!NT_STATUS_IS_OK(*perr)) {
755 /****************************************************************************
756 ****************************************************************************/
758 #define strip_driver_path(_mem_ctx, _element) do { \
759 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
760 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
761 W_ERROR_HAVE_NO_MEMORY((_element)); \
765 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
766 struct pipes_struct *rpc_pipe,
767 const char *architecture,
768 const char **driver_path,
769 const char **data_file,
770 const char **config_file,
771 const char **help_file,
772 struct spoolss_StringArray *dependent_files,
773 enum spoolss_DriverOSVersion *version)
775 const char *short_architecture;
780 if (!*driver_path || !*data_file) {
781 return WERR_INVALID_PARAM;
784 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
785 return WERR_INVALID_PARAM;
788 /* clean up the driver name.
789 * we can get .\driver.dll
790 * or worse c:\windows\system\driver.dll !
792 /* using an intermediate string to not have overlaping memcpy()'s */
794 strip_driver_path(mem_ctx, *driver_path);
795 strip_driver_path(mem_ctx, *data_file);
797 strip_driver_path(mem_ctx, *config_file);
800 strip_driver_path(mem_ctx, *help_file);
803 if (dependent_files && dependent_files->string) {
804 for (i=0; dependent_files->string[i]; i++) {
805 strip_driver_path(mem_ctx, dependent_files->string[i]);
809 short_architecture = get_short_archi(architecture);
810 if (!short_architecture) {
811 return WERR_UNKNOWN_PRINTER_DRIVER;
814 /* jfm:7/16/2000 the client always sends the cversion=0.
815 * The server should check which version the driver is by reading
816 * the PE header of driver->driverpath.
818 * For Windows 95/98 the version is 0 (so the value sent is correct)
819 * For Windows NT (the architecture doesn't matter)
821 * NT 3.5/3.51: cversion=1
826 *version = get_correct_cversion(rpc_pipe, short_architecture,
828 if (*version == -1) {
835 /****************************************************************************
836 ****************************************************************************/
838 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
839 struct pipes_struct *rpc_pipe,
840 struct spoolss_AddDriverInfoCtr *r)
844 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
845 r->info.info3->architecture,
846 &r->info.info3->driver_path,
847 &r->info.info3->data_file,
848 &r->info.info3->config_file,
849 &r->info.info3->help_file,
850 r->info.info3->dependent_files,
851 &r->info.info3->version);
853 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
854 r->info.info6->architecture,
855 &r->info.info6->driver_path,
856 &r->info.info6->data_file,
857 &r->info.info6->config_file,
858 &r->info.info6->help_file,
859 r->info.info6->dependent_files,
860 &r->info.info6->version);
862 return WERR_NOT_SUPPORTED;
866 /****************************************************************************
867 This function sucks and should be replaced. JRA.
868 ****************************************************************************/
870 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
871 const struct spoolss_AddDriverInfo6 *src)
873 dst->version = src->version;
875 dst->driver_name = src->driver_name;
876 dst->architecture = src->architecture;
877 dst->driver_path = src->driver_path;
878 dst->data_file = src->data_file;
879 dst->config_file = src->config_file;
880 dst->help_file = src->help_file;
881 dst->monitor_name = src->monitor_name;
882 dst->default_datatype = src->default_datatype;
883 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
884 dst->dependent_files = src->dependent_files;
887 /****************************************************************************
888 ****************************************************************************/
890 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
891 connection_struct *conn,
892 const char *driver_file,
893 const char *short_architecture,
894 uint32_t driver_version,
897 struct smb_filename *smb_fname_old = NULL;
898 struct smb_filename *smb_fname_new = NULL;
899 char *old_name = NULL;
900 char *new_name = NULL;
904 old_name = talloc_asprintf(mem_ctx, "%s/%s",
905 short_architecture, driver_file);
906 W_ERROR_HAVE_NO_MEMORY(old_name);
908 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
909 short_architecture, driver_version, driver_file);
910 if (new_name == NULL) {
911 TALLOC_FREE(old_name);
915 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
917 status = driver_unix_convert(conn, old_name, &smb_fname_old);
918 if (!NT_STATUS_IS_OK(status)) {
923 /* Setup a synthetic smb_filename struct */
924 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
925 if (!smb_fname_new) {
930 smb_fname_new->base_name = new_name;
932 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
933 "'%s'\n", smb_fname_old->base_name,
934 smb_fname_new->base_name));
936 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
937 OPENX_FILE_EXISTS_TRUNCATE |
938 OPENX_FILE_CREATE_IF_NOT_EXIST,
941 if (!NT_STATUS_IS_OK(status)) {
942 DEBUG(0,("move_driver_file_to_download_area: Unable "
943 "to rename [%s] to [%s]: %s\n",
944 smb_fname_old->base_name, new_name,
946 ret = WERR_ACCESS_DENIED;
953 TALLOC_FREE(smb_fname_old);
954 TALLOC_FREE(smb_fname_new);
958 WERROR move_driver_to_download_area(struct pipes_struct *p,
959 struct spoolss_AddDriverInfoCtr *r)
961 struct spoolss_AddDriverInfo3 *driver;
962 struct spoolss_AddDriverInfo3 converted_driver;
963 const char *short_architecture;
964 struct smb_filename *smb_dname = NULL;
965 char *new_dir = NULL;
966 connection_struct *conn = NULL;
969 TALLOC_CTX *ctx = talloc_tos();
972 char *printdollar = NULL;
973 int printdollar_snum;
974 WERROR err = WERR_OK;
978 driver = r->info.info3;
981 convert_level_6_to_level3(&converted_driver, r->info.info6);
982 driver = &converted_driver;
985 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
986 return WERR_UNKNOWN_LEVEL;
989 short_architecture = get_short_archi(driver->architecture);
990 if (!short_architecture) {
991 return WERR_UNKNOWN_PRINTER_DRIVER;
994 printdollar_snum = find_service(ctx, "print$", &printdollar);
998 if (printdollar_snum == -1) {
999 return WERR_NO_SUCH_SHARE;
1002 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1003 lp_pathname(printdollar_snum),
1004 p->session_info, &oldcwd);
1005 if (!NT_STATUS_IS_OK(nt_status)) {
1006 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1007 "returned %s\n", nt_errstr(nt_status)));
1008 err = ntstatus_to_werror(nt_status);
1012 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1013 if (!NT_STATUS_IS_OK(nt_status)) {
1014 DEBUG(0, ("failed set force user / group\n"));
1015 err = ntstatus_to_werror(nt_status);
1019 if (!become_user(conn, get_current_vuid(conn))) {
1020 DEBUG(0, ("failed to become user\n"));
1021 err = WERR_ACCESS_DENIED;
1025 new_dir = talloc_asprintf(ctx,
1033 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1034 if (!NT_STATUS_IS_OK(nt_status)) {
1039 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1041 nt_status = create_directory(conn, NULL, smb_dname);
1042 if (!NT_STATUS_IS_OK(nt_status)
1043 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1044 DEBUG(0, ("failed to create driver destination directory: %s\n",
1045 nt_errstr(nt_status)));
1046 err = ntstatus_to_werror(nt_status);
1050 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1051 * listed for this driver which has already been moved, skip it (note:
1052 * drivers may list the same file name several times. Then check if the
1053 * file already exists in archi\version\, if so, check that the version
1054 * info (or time stamps if version info is unavailable) is newer (or the
1055 * date is later). If it is, move it to archi\version\filexxx.yyy.
1056 * Otherwise, delete the file.
1058 * If a file is not moved to archi\version\ because of an error, all the
1059 * rest of the 'unmoved' driver files are removed from archi\. If one or
1060 * more of the driver's files was already moved to archi\version\, it
1061 * potentially leaves the driver in a partially updated state. Version
1062 * trauma will most likely occur if an client attempts to use any printer
1063 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1064 * done is appropriate... later JRR
1067 DEBUG(5,("Moving files now !\n"));
1069 if (driver->driver_path && strlen(driver->driver_path)) {
1071 err = move_driver_file_to_download_area(ctx,
1073 driver->driver_path,
1077 if (!W_ERROR_IS_OK(err)) {
1082 if (driver->data_file && strlen(driver->data_file)) {
1083 if (!strequal(driver->data_file, driver->driver_path)) {
1085 err = move_driver_file_to_download_area(ctx,
1091 if (!W_ERROR_IS_OK(err)) {
1097 if (driver->config_file && strlen(driver->config_file)) {
1098 if (!strequal(driver->config_file, driver->driver_path) &&
1099 !strequal(driver->config_file, driver->data_file)) {
1101 err = move_driver_file_to_download_area(ctx,
1103 driver->config_file,
1107 if (!W_ERROR_IS_OK(err)) {
1113 if (driver->help_file && strlen(driver->help_file)) {
1114 if (!strequal(driver->help_file, driver->driver_path) &&
1115 !strequal(driver->help_file, driver->data_file) &&
1116 !strequal(driver->help_file, driver->config_file)) {
1118 err = move_driver_file_to_download_area(ctx,
1124 if (!W_ERROR_IS_OK(err)) {
1130 if (driver->dependent_files && driver->dependent_files->string) {
1131 for (i=0; driver->dependent_files->string[i]; i++) {
1132 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1133 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1134 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1135 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1137 for (j=0; j < i; j++) {
1138 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1143 err = move_driver_file_to_download_area(ctx,
1145 driver->dependent_files->string[i],
1149 if (!W_ERROR_IS_OK(err)) {
1161 TALLOC_FREE(smb_dname);
1164 vfs_ChDir(conn, oldcwd);
1165 SMB_VFS_DISCONNECT(conn);
1172 /****************************************************************************
1173 Create and allocate a default devicemode.
1174 ****************************************************************************/
1176 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1177 const char *devicename,
1178 struct spoolss_DeviceMode **devmode)
1180 struct spoolss_DeviceMode *dm;
1183 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1188 dname = talloc_asprintf(dm, "%s", devicename);
1189 if (dname == NULL) {
1192 if (strlen(dname) > MAXDEVICENAME) {
1193 dname[MAXDEVICENAME] = '\0';
1195 dm->devicename = dname;
1197 dm->formname = talloc_strdup(dm, "Letter");
1198 if (dm->formname == NULL) {
1202 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1203 dm->driverversion = 0x0400;
1205 dm->__driverextra_length = 0;
1206 dm->fields = DEVMODE_FORMNAME |
1208 DEVMODE_PRINTQUALITY |
1209 DEVMODE_DEFAULTSOURCE |
1213 DEVMODE_ORIENTATION;
1214 dm->orientation = DMORIENT_PORTRAIT;
1215 dm->papersize = DMPAPER_LETTER;
1216 dm->paperlength = 0;
1220 dm->defaultsource = DMBIN_FORMSOURCE;
1221 dm->printquality = DMRES_HIGH; /* 0x0258 */
1222 dm->color = DMRES_MONOCHROME;
1223 dm->duplex = DMDUP_SIMPLEX;
1224 dm->yresolution = 0;
1225 dm->ttoption = DMTT_SUBDEV;
1226 dm->collate = DMCOLLATE_FALSE;
1236 dm->displayflags = 0;
1237 dm->displayfrequency = 0;
1240 dm->panningwidth = 0;
1241 dm->panningheight = 0;
1243 dm->driverextra_data.data = NULL;
1244 dm->driverextra_data.length = 0;
1250 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1251 struct spoolss_security_descriptor **secdesc)
1253 struct security_ace ace[7]; /* max number of ace entries */
1256 struct security_acl *psa = NULL;
1257 struct security_descriptor *psd = NULL;
1258 struct dom_sid adm_sid;
1261 /* Create an ACE where Everyone is allowed to print */
1263 sa = PRINTER_ACE_PRINT;
1264 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1265 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1267 /* Add the domain admins group if we are a DC */
1270 struct dom_sid domadmins_sid;
1272 sid_compose(&domadmins_sid, get_global_sam_sid(),
1275 sa = PRINTER_ACE_FULL_CONTROL;
1276 init_sec_ace(&ace[i++], &domadmins_sid,
1277 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1278 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1279 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1280 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1282 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1283 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1285 sa = PRINTER_ACE_FULL_CONTROL;
1286 init_sec_ace(&ace[i++], &adm_sid,
1287 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1288 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1289 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1290 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1293 /* add BUILTIN\Administrators as FULL CONTROL */
1295 sa = PRINTER_ACE_FULL_CONTROL;
1296 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1297 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1298 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1299 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1300 SEC_ACE_TYPE_ACCESS_ALLOWED,
1301 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1303 /* add BUILTIN\Print Operators as FULL CONTROL */
1305 sa = PRINTER_ACE_FULL_CONTROL;
1306 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1307 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1308 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1309 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1310 SEC_ACE_TYPE_ACCESS_ALLOWED,
1311 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1313 /* Make the security descriptor owned by the BUILTIN\Administrators */
1315 /* The ACL revision number in rpc_secdesc.h differs from the one
1316 created by NT when setting ACE entries in printer
1317 descriptors. NT4 complains about the property being edited by a
1320 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1321 psd = make_sec_desc(mem_ctx,
1323 SEC_DESC_SELF_RELATIVE,
1324 &global_sid_Builtin_Administrators,
1325 &global_sid_Builtin_Administrators,
1332 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1336 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1337 (unsigned int)sd_size));
1344 /****************************************************************************
1345 ***************************************************************************/
1347 static char *win_driver;
1348 static char *os2_driver;
1350 static const char *get_win_driver(void)
1352 if (win_driver == NULL) {
1358 static const char *get_os2_driver(void)
1360 if (os2_driver == NULL) {
1366 static bool set_driver_mapping(const char *from, const char *to)
1368 SAFE_FREE(win_driver);
1369 SAFE_FREE(os2_driver);
1371 win_driver = SMB_STRDUP(from);
1372 os2_driver = SMB_STRDUP(to);
1374 if (win_driver == NULL || os2_driver == NULL) {
1375 SAFE_FREE(win_driver);
1376 SAFE_FREE(os2_driver);
1385 * @brief Map a Windows driver to a OS/2 driver.
1387 * @param[in] mem_ctx The memory context to use.
1389 * @param[in,out] pdrivername The drivername of Windows to remap.
1391 * @return WERR_OK on success, a corresponding WERROR on failure.
1393 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1395 const char *mapfile = lp_os2_driver_map();
1396 char **lines = NULL;
1397 const char *drivername;
1401 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1402 return WERR_INVALID_PARAMETER;
1405 drivername = *pdrivername;
1407 if (mapfile[0] == '\0') {
1408 return WERR_BADFILE;
1411 if (strequal(drivername, get_win_driver())) {
1412 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1413 drivername, get_os2_driver()));
1414 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1415 if (drivername == NULL) {
1418 *pdrivername = drivername;
1422 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1423 if (numlines == 0 || lines == NULL) {
1424 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1429 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1431 for( i = 0; i < numlines; i++) {
1432 char *nt_name = lines[i];
1433 char *os2_name = strchr(nt_name, '=');
1435 if (os2_name == NULL) {
1441 while (isspace(*nt_name)) {
1445 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1450 int l = strlen(nt_name);
1451 while (l && isspace(nt_name[l - 1])) {
1457 while (isspace(*os2_name)) {
1462 int l = strlen(os2_name);
1463 while (l && isspace(os2_name[l-1])) {
1469 if (strequal(nt_name, drivername)) {
1470 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1471 set_driver_mapping(drivername, os2_name);
1472 drivername = talloc_strdup(mem_ctx, os2_name);
1474 if (drivername == NULL) {
1477 *pdrivername = drivername;
1486 /****************************************************************************
1487 ****************************************************************************/
1489 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1490 struct spoolss_DriverInfo8 *_info8)
1492 struct spoolss_DriverInfo8 info8;
1498 info8.version = r->info.info3->version;
1499 info8.driver_name = r->info.info3->driver_name;
1500 info8.architecture = r->info.info3->architecture;
1501 info8.driver_path = r->info.info3->driver_path;
1502 info8.data_file = r->info.info3->data_file;
1503 info8.config_file = r->info.info3->config_file;
1504 info8.help_file = r->info.info3->help_file;
1505 info8.monitor_name = r->info.info3->monitor_name;
1506 info8.default_datatype = r->info.info3->default_datatype;
1507 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1508 info8.dependent_files = r->info.info3->dependent_files->string;
1512 info8.version = r->info.info6->version;
1513 info8.driver_name = r->info.info6->driver_name;
1514 info8.architecture = r->info.info6->architecture;
1515 info8.driver_path = r->info.info6->driver_path;
1516 info8.data_file = r->info.info6->data_file;
1517 info8.config_file = r->info.info6->config_file;
1518 info8.help_file = r->info.info6->help_file;
1519 info8.monitor_name = r->info.info6->monitor_name;
1520 info8.default_datatype = r->info.info6->default_datatype;
1521 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1522 info8.dependent_files = r->info.info6->dependent_files->string;
1524 info8.driver_date = r->info.info6->driver_date;
1525 info8.driver_version = r->info.info6->driver_version;
1526 info8.manufacturer_name = r->info.info6->manufacturer_name;
1527 info8.manufacturer_url = r->info.info6->manufacturer_url;
1528 info8.hardware_id = r->info.info6->hardware_id;
1529 info8.provider = r->info.info6->provider;
1532 info8.version = r->info.info8->version;
1533 info8.driver_name = r->info.info8->driver_name;
1534 info8.architecture = r->info.info8->architecture;
1535 info8.driver_path = r->info.info8->driver_path;
1536 info8.data_file = r->info.info8->data_file;
1537 info8.config_file = r->info.info8->config_file;
1538 info8.help_file = r->info.info8->help_file;
1539 info8.monitor_name = r->info.info8->monitor_name;
1540 info8.default_datatype = r->info.info8->default_datatype;
1541 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1542 info8.dependent_files = r->info.info8->dependent_files->string;
1544 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1545 info8.previous_names = r->info.info8->previous_names->string;
1547 info8.driver_date = r->info.info8->driver_date;
1548 info8.driver_version = r->info.info8->driver_version;
1549 info8.manufacturer_name = r->info.info8->manufacturer_name;
1550 info8.manufacturer_url = r->info.info8->manufacturer_url;
1551 info8.hardware_id = r->info.info8->hardware_id;
1552 info8.provider = r->info.info8->provider;
1553 info8.print_processor = r->info.info8->print_processor;
1554 info8.vendor_setup = r->info.info8->vendor_setup;
1555 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1556 info8.color_profiles = r->info.info8->color_profiles->string;
1558 info8.inf_path = r->info.info8->inf_path;
1559 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1560 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1561 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1563 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1564 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1576 /****************************************************************************
1577 Determine whether or not a particular driver is currently assigned
1579 ****************************************************************************/
1581 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1582 const struct auth_serversupplied_info *session_info,
1583 struct messaging_context *msg_ctx,
1584 const struct spoolss_DriverInfo8 *r)
1587 int n_services = lp_numservices();
1588 bool in_use = False;
1589 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1596 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1598 /* loop through the printers.tdb and check for the drivername */
1600 for (snum=0; snum<n_services && !in_use; snum++) {
1601 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1605 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
1606 lp_servicename(snum),
1608 if (!W_ERROR_IS_OK(result)) {
1609 continue; /* skip */
1612 if (strequal(r->driver_name, pinfo2->drivername)) {
1616 TALLOC_FREE(pinfo2);
1619 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1622 struct spoolss_DriverInfo8 *driver;
1625 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1627 /* we can still remove the driver if there is one of
1628 "Windows NT x86" version 2 or 3 left */
1630 if (!strequal("Windows NT x86", r->architecture)) {
1631 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1636 } else if (r->version == 2) {
1637 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1641 } else if (r->version == 3) {
1642 werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1647 DEBUG(0, ("printer_driver_in_use: ERROR!"
1648 " unknown driver version (%d)\n",
1650 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1653 /* now check the error code */
1655 if ( W_ERROR_IS_OK(werr) ) {
1656 /* it's ok to remove the driver, we have other architctures left */
1658 talloc_free(driver);
1662 /* report that the driver is not in use by default */
1668 /**********************************************************************
1669 Check to see if a ogiven file is in use by *info
1670 *********************************************************************/
1672 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1679 /* mz: skip files that are in the list but already deleted */
1680 if (!file || !file[0]) {
1684 if (strequal(file, info->driver_path))
1687 if (strequal(file, info->data_file))
1690 if (strequal(file, info->config_file))
1693 if (strequal(file, info->help_file))
1696 /* see of there are any dependent files to examine */
1698 if (!info->dependent_files)
1701 while (info->dependent_files[i] && *info->dependent_files[i]) {
1702 if (strequal(file, info->dependent_files[i]))
1711 /**********************************************************************
1712 Utility function to remove the dependent file pointed to by the
1713 input parameter from the list
1714 *********************************************************************/
1716 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1719 /* bump everything down a slot */
1721 while (files && files[idx+1]) {
1722 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1731 /**********************************************************************
1732 Check if any of the files used by src are also used by drv
1733 *********************************************************************/
1735 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1736 struct spoolss_DriverInfo8 *src,
1737 const struct spoolss_DriverInfo8 *drv)
1739 bool in_use = False;
1745 /* check each file. Remove it from the src structure if it overlaps */
1747 if (drv_file_in_use(src->driver_path, drv)) {
1749 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1750 src->driver_path = talloc_strdup(mem_ctx, "");
1751 if (!src->driver_path) { return false; }
1754 if (drv_file_in_use(src->data_file, drv)) {
1756 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1757 src->data_file = talloc_strdup(mem_ctx, "");
1758 if (!src->data_file) { return false; }
1761 if (drv_file_in_use(src->config_file, drv)) {
1763 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1764 src->config_file = talloc_strdup(mem_ctx, "");
1765 if (!src->config_file) { return false; }
1768 if (drv_file_in_use(src->help_file, drv)) {
1770 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1771 src->help_file = talloc_strdup(mem_ctx, "");
1772 if (!src->help_file) { return false; }
1775 /* are there any dependentfiles to examine? */
1777 if (!src->dependent_files)
1780 while (src->dependent_files[i] && *src->dependent_files[i]) {
1781 if (drv_file_in_use(src->dependent_files[i], drv)) {
1783 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1784 trim_dependent_file(mem_ctx, src->dependent_files, i);
1792 /****************************************************************************
1793 Determine whether or not a particular driver files are currently being
1794 used by any other driver.
1796 Return value is True if any files were in use by other drivers
1797 and False otherwise.
1799 Upon return, *info has been modified to only contain the driver files
1800 which are not in use
1804 This needs to check all drivers to ensure that all files in use
1805 have been removed from *info, not just the ones in the first
1807 ****************************************************************************/
1809 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1810 const struct auth_serversupplied_info *session_info,
1811 struct messaging_context *msg_ctx,
1812 struct spoolss_DriverInfo8 *info)
1816 struct spoolss_DriverInfo8 *driver;
1817 bool in_use = false;
1818 uint32_t num_drivers;
1819 const char **drivers;
1825 version = info->version;
1827 /* loop over all driver versions */
1829 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1831 /* get the list of drivers */
1833 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
1834 info->architecture, version,
1835 &num_drivers, &drivers);
1836 if (!W_ERROR_IS_OK(result)) {
1840 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1841 num_drivers, info->architecture, version));
1843 /* check each driver for overlap in files */
1845 for (i = 0; i < num_drivers; i++) {
1846 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1850 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1851 info->architecture, drivers[i],
1853 if (!W_ERROR_IS_OK(result)) {
1854 talloc_free(drivers);
1858 /* check if d2 uses any files from d1 */
1859 /* only if this is a different driver than the one being deleted */
1861 if (!strequal(info->driver_name, driver->driver_name)) {
1862 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1863 /* mz: Do not instantly return -
1864 * we need to ensure this file isn't
1865 * also in use by other drivers. */
1870 talloc_free(driver);
1873 talloc_free(drivers);
1875 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1880 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1883 struct smb_filename *smb_fname = NULL;
1886 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1888 if (!NT_STATUS_IS_OK(status)) {
1892 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1894 TALLOC_FREE(smb_fname);
1898 /****************************************************************************
1899 Actually delete the driver files. Make sure that
1900 printer_driver_files_in_use() return False before calling
1902 ****************************************************************************/
1904 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
1905 const struct spoolss_DriverInfo8 *r)
1910 connection_struct *conn;
1913 char *printdollar = NULL;
1914 int printdollar_snum;
1921 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1922 r->driver_name, r->version));
1924 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1928 if (printdollar_snum == -1) {
1932 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1933 lp_pathname(printdollar_snum),
1934 session_info, &oldcwd);
1935 if (!NT_STATUS_IS_OK(nt_status)) {
1936 DEBUG(0,("delete_driver_files: create_conn_struct "
1937 "returned %s\n", nt_errstr(nt_status)));
1941 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1942 if (!NT_STATUS_IS_OK(nt_status)) {
1943 DEBUG(0, ("failed set force user / group\n"));
1948 if (!become_user(conn, get_current_vuid(conn))) {
1949 DEBUG(0, ("failed to become user\n"));
1954 if ( !CAN_WRITE(conn) ) {
1955 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1960 /* now delete the files; must strip the '\print$' string from
1963 if (r->driver_path && r->driver_path[0]) {
1964 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1966 DEBUG(10,("deleting driverfile [%s]\n", s));
1967 driver_unlink_internals(conn, file);
1971 if (r->config_file && r->config_file[0]) {
1972 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1974 DEBUG(10,("deleting configfile [%s]\n", s));
1975 driver_unlink_internals(conn, file);
1979 if (r->data_file && r->data_file[0]) {
1980 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1982 DEBUG(10,("deleting datafile [%s]\n", s));
1983 driver_unlink_internals(conn, file);
1987 if (r->help_file && r->help_file[0]) {
1988 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1990 DEBUG(10,("deleting helpfile [%s]\n", s));
1991 driver_unlink_internals(conn, file);
1995 /* check if we are done removing files */
1997 if (r->dependent_files) {
1998 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2001 /* bypass the "\print$" portion of the path */
2003 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2005 DEBUG(10,("deleting dependent file [%s]\n", file));
2006 driver_unlink_internals(conn, file);
2018 vfs_ChDir(conn, oldcwd);
2019 SMB_VFS_DISCONNECT(conn);
2027 1: level not implemented
2028 2: file doesn't exist
2029 3: can't allocate memory
2030 4: can't free memory
2031 5: non existant struct
2035 A printer and a printer driver are 2 different things.
2036 NT manages them separatelly, Samba does the same.
2037 Why ? Simply because it's easier and it makes sense !
2039 Now explanation: You have 3 printers behind your samba server,
2040 2 of them are the same make and model (laser A and B). But laser B
2041 has an 3000 sheet feeder and laser A doesn't such an option.
2042 Your third printer is an old dot-matrix model for the accounting :-).
2044 If the /usr/local/samba/lib directory (default dir), you will have
2045 5 files to describe all of this.
2047 3 files for the printers (1 by printer):
2050 NTprinter_accounting
2051 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2052 NTdriver_printer model X
2053 NTdriver_printer model Y
2055 jfm: I should use this comment for the text file to explain
2056 same thing for the forms BTW.
2057 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2061 /* Convert generic access rights to printer object specific access rights.
2062 It turns out that NT4 security descriptors use generic access rights and
2063 NT5 the object specific ones. */
2065 void map_printer_permissions(struct security_descriptor *sd)
2069 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2070 se_map_generic(&sd->dacl->aces[i].access_mask,
2071 &printer_generic_mapping);
2075 void map_job_permissions(struct security_descriptor *sd)
2079 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2080 se_map_generic(&sd->dacl->aces[i].access_mask,
2081 &job_generic_mapping);
2086 /****************************************************************************
2087 Check a user has permissions to perform the given operation. We use the
2088 permission constants defined in include/rpc_spoolss.h to check the various
2089 actions we perform when checking printer access.
2091 PRINTER_ACCESS_ADMINISTER:
2092 print_queue_pause, print_queue_resume, update_printer_sec,
2093 update_printer, spoolss_addprinterex_level_2,
2094 _spoolss_setprinterdata
2099 JOB_ACCESS_ADMINISTER:
2100 print_job_delete, print_job_pause, print_job_resume,
2103 Try access control in the following order (for performance reasons):
2104 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2105 2) check security descriptor (bit comparisons in memory)
2106 3) "printer admins" (may result in numerous calls to winbind)
2108 ****************************************************************************/
2109 bool print_access_check(const struct auth_serversupplied_info *session_info,
2110 struct messaging_context *msg_ctx, int snum,
2113 struct spoolss_security_descriptor *secdesc = NULL;
2114 uint32 access_granted;
2119 TALLOC_CTX *mem_ctx = NULL;
2121 /* If user is NULL then use the current_user structure */
2123 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2125 if (session_info->utok.uid == sec_initial_uid()
2126 || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
2130 /* Get printer name */
2132 pname = lp_printername(snum);
2134 if (!pname || !*pname) {
2139 /* Get printer security descriptor */
2141 if(!(mem_ctx = talloc_init("print_access_check"))) {
2146 result = winreg_get_printer_secdesc(mem_ctx,
2147 get_session_info_system(),
2151 if (!W_ERROR_IS_OK(result)) {
2152 talloc_destroy(mem_ctx);
2157 if (access_type == JOB_ACCESS_ADMINISTER) {
2158 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2160 /* Create a child security descriptor to check permissions
2161 against. This is because print jobs are child objects
2162 objects of a printer. */
2163 status = se_create_child_secdesc(mem_ctx,
2167 parent_secdesc->owner_sid,
2168 parent_secdesc->group_sid,
2170 if (!NT_STATUS_IS_OK(status)) {
2171 talloc_destroy(mem_ctx);
2172 errno = map_errno_from_nt_status(status);
2176 map_job_permissions(secdesc);
2178 map_printer_permissions(secdesc);
2182 status = se_access_check(secdesc, session_info->security_token, access_type,
2185 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2187 /* see if we need to try the printer admin list */
2189 if (!NT_STATUS_IS_OK(status) &&
2190 (token_contains_name_in_list(uidtoname(session_info->utok.uid),
2191 session_info->info3->base.domain.string,
2192 NULL, session_info->security_token,
2193 lp_printer_admin(snum)))) {
2194 talloc_destroy(mem_ctx);
2198 talloc_destroy(mem_ctx);
2200 if (!NT_STATUS_IS_OK(status)) {
2204 return NT_STATUS_IS_OK(status);
2207 /****************************************************************************
2208 Check the time parameters allow a print operation.
2209 *****************************************************************************/
2211 bool print_time_access_check(const struct auth_serversupplied_info *session_info,
2212 struct messaging_context *msg_ctx,
2213 const char *servicename)
2215 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2218 time_t now = time(NULL);
2222 result = winreg_get_printer(NULL, session_info, msg_ctx,
2223 servicename, &pinfo2);
2224 if (!W_ERROR_IS_OK(result)) {
2228 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2233 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2235 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2239 TALLOC_FREE(pinfo2);
2248 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2249 const struct auth_serversupplied_info *session_info,
2250 struct messaging_context *msg_ctx,
2251 const char *printer)
2255 result = winreg_delete_printer_key(mem_ctx, session_info, msg_ctx,
2257 if (!W_ERROR_IS_OK(result)) {
2258 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",