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/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.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 static bool print_driver_directories_init(void)
82 TALLOC_CTX *mem_ctx = talloc_stackframe();
83 const char *dir_list[] = {
89 service = lp_servicenumber("print$");
91 /* We don't have a print$ share */
92 DEBUG(5, ("No print$ share has been configured.\n"));
97 driver_path = lp_path(mem_ctx, service);
98 if (driver_path == NULL) {
103 ok = directory_create_or_exist(driver_path, 0755);
105 DEBUG(1, ("Failed to create printer driver directory %s\n",
107 talloc_free(mem_ctx);
111 for (i = 0; archi_table[i].long_archi != NULL; i++) {
112 const char *arch_path;
114 arch_path = talloc_asprintf(mem_ctx,
117 archi_table[i].short_archi);
118 if (arch_path == NULL) {
119 talloc_free(mem_ctx);
123 ok = directory_create_or_exist(arch_path, 0755);
125 DEBUG(1, ("Failed to create printer driver "
126 "architecture directory %s\n",
128 talloc_free(mem_ctx);
133 for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
136 path = talloc_asprintf(mem_ctx,
141 talloc_free(mem_ctx);
145 ok = directory_create_or_exist(path, 0755);
147 DEBUG(1, ("Failed to create printer driver "
148 "architecture directory %s\n",
150 talloc_free(mem_ctx);
155 driver_path = state_path("DriverStore");
156 if (driver_path == NULL) {
157 talloc_free(mem_ctx);
161 ok = directory_create_or_exist(driver_path, 0755);
163 DEBUG(1,("failed to create path %s\n", driver_path));
164 talloc_free(mem_ctx);
168 driver_path = state_path("DriverStore/FileRepository");
169 if (driver_path == NULL) {
170 talloc_free(mem_ctx);
174 ok = directory_create_or_exist(driver_path, 0755);
176 DEBUG(1,("failed to create path %s\n", driver_path));
177 talloc_free(mem_ctx);
181 driver_path = state_path("DriverStore/Temp");
182 if (driver_path == NULL) {
183 talloc_free(mem_ctx);
187 ok = directory_create_or_exist(driver_path, 0755);
189 DEBUG(1,("failed to create path %s\n", driver_path));
190 talloc_free(mem_ctx);
194 talloc_free(mem_ctx);
198 /****************************************************************************
199 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
200 background lpq updater.
201 ****************************************************************************/
203 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
206 struct server_id server_id,
209 extern pid_t background_lpq_updater_pid;
211 if (background_lpq_updater_pid == -1) {
212 DEBUG(3,("no background lpq queue updater\n"));
216 messaging_send_buf(msg,
217 pid_to_procid(background_lpq_updater_pid),
218 MSG_PRINTER_DRVUPGRADE,
223 /****************************************************************************
224 Open the NT printing tdbs. Done once before fork().
225 ****************************************************************************/
227 bool nt_printing_init(struct messaging_context *msg_ctx)
231 if (!print_driver_directories_init()) {
235 if (!nt_printing_tdb_upgrade()) {
240 * register callback to handle updating printers as new
241 * drivers are installed. Forwards to background lpq updater.
243 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
244 forward_drv_upgrade_printer_msg);
246 if ( lp_security() == SEC_ADS ) {
247 win_rc = check_published_printers(msg_ctx);
248 if (!W_ERROR_IS_OK(win_rc))
249 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
255 /*******************************************************************
256 Function to allow filename parsing "the old way".
257 ********************************************************************/
259 static NTSTATUS driver_unix_convert(connection_struct *conn,
260 const char *old_name,
261 struct smb_filename **smb_fname)
264 TALLOC_CTX *ctx = talloc_tos();
265 char *name = talloc_strdup(ctx, old_name);
268 return NT_STATUS_NO_MEMORY;
271 name = unix_clean_name(ctx, name);
273 return NT_STATUS_NO_MEMORY;
275 trim_string(name,"/","/");
277 status = unix_convert(ctx, conn, name, smb_fname, 0);
278 if (!NT_STATUS_IS_OK(status)) {
279 return NT_STATUS_NO_MEMORY;
285 /****************************************************************************
286 Function to do the mapping between the long architecture name and
288 ****************************************************************************/
290 const char *get_short_archi(const char *long_archi)
294 DEBUG(107,("Getting architecture dependent directory\n"));
297 } while ( (archi_table[i].long_archi!=NULL ) &&
298 strcasecmp_m(long_archi, archi_table[i].long_archi) );
300 if (archi_table[i].long_archi==NULL) {
301 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
305 /* this might be client code - but shouldn't this be an fstrcpy etc? */
307 DEBUGADD(108,("index: [%d]\n", i));
308 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
309 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
311 return archi_table[i].short_archi;
314 /****************************************************************************
315 Read data from fsp on the vfs.
316 (note: EINTR re-read differs from vfs_write_data)
317 ****************************************************************************/
319 static ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
323 while (total < byte_count) {
324 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
331 if (errno == EINTR) {
339 return (ssize_t)total;
342 /****************************************************************************
343 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
344 There are two case to be covered here: PE (Portable Executable) and NE (New
345 Executable) files. Both files support the same INFO structure, but PE files
346 store the signature in unicode, and NE files store it as !unicode.
347 returns -1 on error, 1 on version info found, and 0 on no version info found.
348 ****************************************************************************/
350 static int get_file_version(files_struct *fsp, char *fname,uint32_t *major, uint32_t *minor)
356 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
357 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
358 fname, DOS_HEADER_SIZE));
362 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
363 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
364 fname, (unsigned long)byte_count));
365 goto no_version_info;
368 /* Is this really a DOS header? */
369 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
370 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
371 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
372 goto no_version_info;
375 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
376 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (off_t)-1) {
377 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
379 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
380 goto no_version_info;
383 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
384 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
385 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
386 fname, (unsigned long)byte_count));
387 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
388 goto no_version_info;
391 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
392 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
393 unsigned int num_sections;
394 unsigned int section_table_bytes;
396 /* Just skip over optional header to get to section table */
397 if (SMB_VFS_LSEEK(fsp,
398 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
399 SEEK_CUR) == (off_t)-1) {
400 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
405 /* get the section table */
406 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
407 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
408 if (section_table_bytes == 0)
412 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
413 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
414 fname, section_table_bytes));
418 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
419 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
420 fname, (unsigned long)byte_count));
424 /* Iterate the section table looking for the resource section ".rsrc" */
425 for (i = 0; i < num_sections; i++) {
426 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
428 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
429 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
430 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
432 if (section_bytes == 0)
436 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
437 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
438 fname, section_bytes));
442 /* Seek to the start of the .rsrc section info */
443 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (off_t)-1) {
444 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
449 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
450 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
451 fname, (unsigned long)byte_count));
455 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
458 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
459 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
460 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
461 /* Align to next long address */
462 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
464 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
465 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
466 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
468 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
469 fname, *major, *minor,
470 (*major>>16)&0xffff, *major&0xffff,
471 (*minor>>16)&0xffff, *minor&0xffff));
480 /* Version info not found, fall back to origin date/time */
481 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
485 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
486 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
487 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
488 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
489 /* At this point, we assume the file is in error. It still could be something
490 * else besides a NE file, but it unlikely at this point. */
494 /* Allocate a bit more space to speed up things */
496 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
497 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
498 fname, PE_HEADER_SIZE));
502 /* This is a HACK! I got tired of trying to sort through the messy
503 * 'NE' file format. If anyone wants to clean this up please have at
504 * it, but this works. 'NE' files will eventually fade away. JRR */
505 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
506 /* Cover case that should not occur in a well formed 'NE' .dll file */
507 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
509 for(i=0; i<byte_count; i++) {
510 /* Fast skip past data that can't possibly match */
511 if (buf[i] != 'V') continue;
513 /* Potential match data crosses buf boundry, move it to beginning
514 * of buf, and fill the buf with as much as it will hold. */
515 if (i>byte_count-VS_VERSION_INFO_SIZE) {
517 ssize_t amount_unused = byte_count-i;
519 memmove(buf, &buf[i], amount_unused);
520 amount_read = vfs_read_data(fsp,
522 VS_NE_BUF_SIZE- amount_unused);
523 if (amount_read < 0) {
525 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
530 if (amount_read + amount_unused <
532 /* Check for integer wrap. */
536 byte_count = amount_read +
538 if (byte_count < VS_VERSION_INFO_SIZE) {
545 /* Check that the full signature string and the magic number that
546 * follows exist (not a perfect solution, but the chances that this
547 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
548 * twice, as it is simpler to read the code. */
549 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
550 /* Compute skip alignment to next long address */
551 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
552 sizeof(VS_SIGNATURE)) & 3;
553 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
555 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
556 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
557 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
558 fname, *major, *minor,
559 (*major>>16)&0xffff, *major&0xffff,
560 (*minor>>16)&0xffff, *minor&0xffff));
567 /* Version info not found, fall back to origin date/time */
568 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
573 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
574 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
575 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
586 /****************************************************************************
587 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
588 share one or more files. During the MS installation process files are checked
589 to insure that only a newer version of a shared file is installed over an
590 older version. There are several possibilities for this comparison. If there
591 is no previous version, the new one is newer (obviously). If either file is
592 missing the version info structure, compare the creation date (on Unix use
593 the modification date). Otherwise chose the numerically larger version number.
594 ****************************************************************************/
596 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
598 bool use_version = true;
602 time_t new_create_time;
606 time_t old_create_time;
608 struct smb_filename *smb_fname = NULL;
609 files_struct *fsp = NULL;
615 SET_STAT_INVALID(st);
616 new_create_time = (time_t)0;
617 old_create_time = (time_t)0;
619 /* Get file version info (if available) for previous file (if it exists) */
620 status = driver_unix_convert(conn, old_file, &smb_fname);
621 if (!NT_STATUS_IS_OK(status)) {
625 status = SMB_VFS_CREATE_FILE(
628 0, /* root_dir_fid */
629 smb_fname, /* fname */
630 FILE_GENERIC_READ, /* access_mask */
631 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
632 FILE_OPEN, /* create_disposition*/
633 0, /* create_options */
634 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
635 INTERNAL_OPEN_ONLY, /* oplock_request */
637 0, /* allocation_size */
638 0, /* private_flags */
643 NULL, NULL); /* create context */
645 if (!NT_STATUS_IS_OK(status)) {
646 /* Old file not found, so by definition new file is in fact newer */
647 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
648 "errno = %d\n", smb_fname_str_dbg(smb_fname),
654 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
660 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
663 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
666 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
667 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
668 (long)old_create_time));
671 close_file(NULL, fsp, NORMAL_CLOSE);
674 /* Get file version info (if available) for new file */
675 status = driver_unix_convert(conn, new_file, &smb_fname);
676 if (!NT_STATUS_IS_OK(status)) {
680 status = SMB_VFS_CREATE_FILE(
683 0, /* root_dir_fid */
684 smb_fname, /* fname */
685 FILE_GENERIC_READ, /* access_mask */
686 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
687 FILE_OPEN, /* create_disposition*/
688 0, /* create_options */
689 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
690 INTERNAL_OPEN_ONLY, /* oplock_request */
692 0, /* allocation_size */
693 0, /* private_flags */
698 NULL, NULL); /* create context */
700 if (!NT_STATUS_IS_OK(status)) {
701 /* New file not found, this shouldn't occur if the caller did its job */
702 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
703 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
707 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
713 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
716 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
719 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
720 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
721 (long)new_create_time));
724 close_file(NULL, fsp, NORMAL_CLOSE);
727 if (use_version && (new_major != old_major || new_minor != old_minor)) {
728 /* Compare versions and choose the larger version number */
729 if (new_major > old_major ||
730 (new_major == old_major && new_minor > old_minor)) {
732 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
737 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
743 /* Compare modification time/dates and choose the newest time/date */
744 if (new_create_time > old_create_time) {
745 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
750 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
758 close_file(NULL, fsp, NORMAL_CLOSE);
761 TALLOC_FREE(smb_fname);
765 /****************************************************************************
766 Determine the correct cVersion associated with an architecture and driver
767 ****************************************************************************/
768 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
769 const char *architecture,
770 const char *driverpath_in,
771 const char *driver_directory,
776 struct smb_filename *smb_fname = NULL;
777 files_struct *fsp = NULL;
778 connection_struct *conn = NULL;
779 struct smb_filename *oldcwd_fname = NULL;
780 char *printdollar = NULL;
781 char *printdollar_path = NULL;
782 char *working_dir = NULL;
783 int printdollar_snum;
785 *perr = WERR_INVALID_PARAMETER;
787 /* If architecture is Windows 95/98/ME, the version is always 0. */
788 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
789 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
794 /* If architecture is Windows x64, the version is always 3. */
795 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
796 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
801 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
803 *perr = WERR_NOT_ENOUGH_MEMORY;
806 if (printdollar_snum == -1) {
807 *perr = WERR_BAD_NET_NAME;
811 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
812 if (printdollar_path == NULL) {
813 *perr = WERR_NOT_ENOUGH_MEMORY;
817 working_dir = talloc_asprintf(talloc_tos(),
822 * If the driver has been uploaded into a temorpary driver
823 * directory, switch to the driver directory.
825 if (driver_directory != NULL) {
826 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
832 nt_status = create_conn_struct_cwd(talloc_tos(),
833 server_event_context(),
834 server_messaging_context(),
838 session_info, &oldcwd_fname);
839 if (!NT_STATUS_IS_OK(nt_status)) {
840 DEBUG(0,("get_correct_cversion: create_conn_struct "
841 "returned %s\n", nt_errstr(nt_status)));
842 *perr = ntstatus_to_werror(nt_status);
846 nt_status = set_conn_force_user_group(conn, printdollar_snum);
847 if (!NT_STATUS_IS_OK(nt_status)) {
848 DEBUG(0, ("failed set force user / group\n"));
849 *perr = ntstatus_to_werror(nt_status);
850 goto error_free_conn;
853 if (!become_user_by_session(conn, session_info)) {
854 DEBUG(0, ("failed to become user\n"));
855 *perr = WERR_ACCESS_DENIED;
856 goto error_free_conn;
860 * We switch to the directory where the driver files are located,
861 * so only work on the file names
863 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
864 if (!NT_STATUS_IS_OK(nt_status)) {
865 *perr = ntstatus_to_werror(nt_status);
869 nt_status = vfs_file_exist(conn, smb_fname);
870 if (!NT_STATUS_IS_OK(nt_status)) {
871 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
872 *perr = WERR_FILE_NOT_FOUND;
876 nt_status = SMB_VFS_CREATE_FILE(
879 0, /* root_dir_fid */
880 smb_fname, /* fname */
881 FILE_GENERIC_READ, /* access_mask */
882 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
883 FILE_OPEN, /* create_disposition*/
884 0, /* create_options */
885 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
886 INTERNAL_OPEN_ONLY, /* oplock_request */
888 0, /* private_flags */
889 0, /* allocation_size */
894 NULL, NULL); /* create context */
896 if (!NT_STATUS_IS_OK(nt_status)) {
897 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
898 "%d\n", smb_fname_str_dbg(smb_fname), errno));
899 *perr = WERR_ACCESS_DENIED;
906 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
908 *perr = WERR_INVALID_PARAMETER;
911 DEBUG(6,("get_correct_cversion: Version info not "
913 smb_fname_str_dbg(smb_fname)));
914 *perr = WERR_INVALID_PARAMETER;
919 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
920 * for more details. Version in this case is not just the version of the
921 * file, but the version in the sense of kernal mode (2) vs. user mode
922 * (3) drivers. Other bits of the version fields are the version info.
925 cversion = major & 0x0000ffff;
927 case 2: /* WinNT drivers */
928 case 3: /* Win2K drivers */
932 DEBUG(6,("get_correct_cversion: cversion "
933 "invalid [%s] cversion = %d\n",
934 smb_fname_str_dbg(smb_fname),
939 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
940 " = 0x%x minor = 0x%x\n",
941 smb_fname_str_dbg(smb_fname), major, minor));
944 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
945 smb_fname_str_dbg(smb_fname), cversion));
951 TALLOC_FREE(smb_fname);
953 close_file(NULL, fsp, NORMAL_CLOSE);
956 vfs_ChDir(conn, oldcwd_fname);
957 TALLOC_FREE(oldcwd_fname);
958 SMB_VFS_DISCONNECT(conn);
961 if (!W_ERROR_IS_OK(*perr)) {
968 /****************************************************************************
969 ****************************************************************************/
971 #define strip_driver_path(_mem_ctx, _element) do { \
972 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
973 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
974 W_ERROR_HAVE_NO_MEMORY((_element)); \
978 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
979 struct auth_session_info *session_info,
980 const char *architecture,
981 const char **driver_path,
982 const char **data_file,
983 const char **config_file,
984 const char **help_file,
985 struct spoolss_StringArray *dependent_files,
986 enum spoolss_DriverOSVersion *version,
988 const char **driver_directory)
990 const char *short_architecture;
995 if (!*driver_path || !*data_file) {
996 return WERR_INVALID_PARAMETER;
999 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1000 return WERR_INVALID_PARAMETER;
1003 if (flags & APD_COPY_FROM_DIRECTORY) {
1008 * driver_path is set to:
1010 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1012 path = talloc_strdup(mem_ctx, *driver_path);
1014 return WERR_NOT_ENOUGH_MEMORY;
1017 /* Remove pscript5.dll */
1018 q = strrchr_m(path, '\\');
1020 return WERR_INVALID_PARAMETER;
1024 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1025 q = strrchr_m(path, '\\');
1027 return WERR_INVALID_PARAMETER;
1031 * Set driver_directory to:
1033 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1035 * This is the directory where all the files have been uploaded
1037 *driver_directory = q + 1;
1040 /* clean up the driver name.
1041 * we can get .\driver.dll
1042 * or worse c:\windows\system\driver.dll !
1044 /* using an intermediate string to not have overlaping memcpy()'s */
1046 strip_driver_path(mem_ctx, *driver_path);
1047 strip_driver_path(mem_ctx, *data_file);
1049 strip_driver_path(mem_ctx, *config_file);
1052 strip_driver_path(mem_ctx, *help_file);
1055 if (dependent_files && dependent_files->string) {
1056 for (i=0; dependent_files->string[i]; i++) {
1057 strip_driver_path(mem_ctx, dependent_files->string[i]);
1061 short_architecture = get_short_archi(architecture);
1062 if (!short_architecture) {
1063 return WERR_UNKNOWN_PRINTER_DRIVER;
1066 /* jfm:7/16/2000 the client always sends the cversion=0.
1067 * The server should check which version the driver is by reading
1068 * the PE header of driver->driverpath.
1070 * For Windows 95/98 the version is 0 (so the value sent is correct)
1071 * For Windows NT (the architecture doesn't matter)
1072 * NT 3.1: cversion=0
1073 * NT 3.5/3.51: cversion=1
1078 *version = get_correct_cversion(session_info,
1083 if (*version == -1) {
1090 /****************************************************************************
1091 ****************************************************************************/
1093 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1094 struct auth_session_info *session_info,
1095 struct spoolss_AddDriverInfoCtr *r,
1097 const char **driver_directory)
1101 return clean_up_driver_struct_level(mem_ctx, session_info,
1102 r->info.info3->architecture,
1103 &r->info.info3->driver_path,
1104 &r->info.info3->data_file,
1105 &r->info.info3->config_file,
1106 &r->info.info3->help_file,
1107 r->info.info3->dependent_files,
1108 &r->info.info3->version,
1112 return clean_up_driver_struct_level(mem_ctx, session_info,
1113 r->info.info6->architecture,
1114 &r->info.info6->driver_path,
1115 &r->info.info6->data_file,
1116 &r->info.info6->config_file,
1117 &r->info.info6->help_file,
1118 r->info.info6->dependent_files,
1119 &r->info.info6->version,
1123 return clean_up_driver_struct_level(mem_ctx, session_info,
1124 r->info.info8->architecture,
1125 &r->info.info8->driver_path,
1126 &r->info.info8->data_file,
1127 &r->info.info8->config_file,
1128 &r->info.info8->help_file,
1129 r->info.info8->dependent_files,
1130 &r->info.info8->version,
1134 return WERR_NOT_SUPPORTED;
1138 /****************************************************************************
1139 This function sucks and should be replaced. JRA.
1140 ****************************************************************************/
1142 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1143 const struct spoolss_AddDriverInfo6 *src)
1145 dst->version = src->version;
1147 dst->driver_name = src->driver_name;
1148 dst->architecture = src->architecture;
1149 dst->driver_path = src->driver_path;
1150 dst->data_file = src->data_file;
1151 dst->config_file = src->config_file;
1152 dst->help_file = src->help_file;
1153 dst->monitor_name = src->monitor_name;
1154 dst->default_datatype = src->default_datatype;
1155 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1156 dst->dependent_files = src->dependent_files;
1159 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1160 const struct spoolss_AddDriverInfo8 *src)
1162 dst->version = src->version;
1164 dst->driver_name = src->driver_name;
1165 dst->architecture = src->architecture;
1166 dst->driver_path = src->driver_path;
1167 dst->data_file = src->data_file;
1168 dst->config_file = src->config_file;
1169 dst->help_file = src->help_file;
1170 dst->monitor_name = src->monitor_name;
1171 dst->default_datatype = src->default_datatype;
1172 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1173 dst->dependent_files = src->dependent_files;
1176 /****************************************************************************
1177 ****************************************************************************/
1179 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1180 connection_struct *conn,
1181 const char *driver_file,
1182 const char *short_architecture,
1183 uint32_t driver_version,
1185 const char *driver_directory)
1187 struct smb_filename *smb_fname_old = NULL;
1188 struct smb_filename *smb_fname_new = NULL;
1189 char *old_name = NULL;
1190 char *new_name = NULL;
1194 if (driver_directory != NULL) {
1195 old_name = talloc_asprintf(mem_ctx,
1201 old_name = talloc_asprintf(mem_ctx,
1206 if (old_name == NULL) {
1207 return WERR_NOT_ENOUGH_MEMORY;
1210 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1211 short_architecture, driver_version, driver_file);
1212 if (new_name == NULL) {
1213 TALLOC_FREE(old_name);
1214 return WERR_NOT_ENOUGH_MEMORY;
1217 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1219 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 ret = WERR_NOT_ENOUGH_MEMORY;
1225 /* Setup a synthetic smb_filename struct */
1226 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1227 if (!smb_fname_new) {
1228 ret = WERR_NOT_ENOUGH_MEMORY;
1232 smb_fname_new->base_name = new_name;
1234 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1235 "'%s'\n", smb_fname_old->base_name,
1236 smb_fname_new->base_name));
1238 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1239 OPENX_FILE_EXISTS_TRUNCATE |
1240 OPENX_FILE_CREATE_IF_NOT_EXIST,
1243 if (!NT_STATUS_IS_OK(status)) {
1244 DEBUG(0,("move_driver_file_to_download_area: Unable "
1245 "to rename [%s] to [%s]: %s\n",
1246 smb_fname_old->base_name, new_name,
1247 nt_errstr(status)));
1248 ret = WERR_APP_INIT_FAILURE;
1255 TALLOC_FREE(smb_fname_old);
1256 TALLOC_FREE(smb_fname_new);
1260 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1261 struct spoolss_AddDriverInfoCtr *r,
1262 const char *driver_directory)
1264 struct spoolss_AddDriverInfo3 *driver;
1265 struct spoolss_AddDriverInfo3 converted_driver;
1266 const char *short_architecture;
1267 struct smb_filename *smb_dname = NULL;
1268 char *new_dir = NULL;
1269 connection_struct *conn = NULL;
1272 TALLOC_CTX *ctx = talloc_tos();
1274 struct smb_filename *oldcwd_fname = NULL;
1275 char *printdollar = NULL;
1276 int printdollar_snum;
1277 WERROR err = WERR_OK;
1281 driver = r->info.info3;
1284 convert_level_6_to_level3(&converted_driver, r->info.info6);
1285 driver = &converted_driver;
1288 convert_level_8_to_level3(&converted_driver, r->info.info8);
1289 driver = &converted_driver;
1292 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1293 return WERR_INVALID_LEVEL;
1296 short_architecture = get_short_archi(driver->architecture);
1297 if (!short_architecture) {
1298 return WERR_UNKNOWN_PRINTER_DRIVER;
1301 printdollar_snum = find_service(ctx, "print$", &printdollar);
1303 return WERR_NOT_ENOUGH_MEMORY;
1305 if (printdollar_snum == -1) {
1306 return WERR_BAD_NET_NAME;
1309 nt_status = create_conn_struct_cwd(talloc_tos(),
1310 server_event_context(),
1311 server_messaging_context(),
1314 lp_path(talloc_tos(), printdollar_snum),
1315 session_info, &oldcwd_fname);
1316 if (!NT_STATUS_IS_OK(nt_status)) {
1317 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1318 "returned %s\n", nt_errstr(nt_status)));
1319 err = ntstatus_to_werror(nt_status);
1323 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1324 if (!NT_STATUS_IS_OK(nt_status)) {
1325 DEBUG(0, ("failed set force user / group\n"));
1326 err = ntstatus_to_werror(nt_status);
1330 if (!become_user_by_session(conn, session_info)) {
1331 DEBUG(0, ("failed to become user\n"));
1332 err = WERR_ACCESS_DENIED;
1336 new_dir = talloc_asprintf(ctx,
1341 err = WERR_NOT_ENOUGH_MEMORY;
1344 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1345 if (!NT_STATUS_IS_OK(nt_status)) {
1346 err = WERR_NOT_ENOUGH_MEMORY;
1350 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1352 nt_status = create_directory(conn, NULL, smb_dname);
1353 if (!NT_STATUS_IS_OK(nt_status)
1354 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1355 DEBUG(0, ("failed to create driver destination directory: %s\n",
1356 nt_errstr(nt_status)));
1357 err = ntstatus_to_werror(nt_status);
1361 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1362 * listed for this driver which has already been moved, skip it (note:
1363 * drivers may list the same file name several times. Then check if the
1364 * file already exists in archi\version\, if so, check that the version
1365 * info (or time stamps if version info is unavailable) is newer (or the
1366 * date is later). If it is, move it to archi\version\filexxx.yyy.
1367 * Otherwise, delete the file.
1369 * If a file is not moved to archi\version\ because of an error, all the
1370 * rest of the 'unmoved' driver files are removed from archi\. If one or
1371 * more of the driver's files was already moved to archi\version\, it
1372 * potentially leaves the driver in a partially updated state. Version
1373 * trauma will most likely occur if an client attempts to use any printer
1374 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1375 * done is appropriate... later JRR
1378 DEBUG(5,("Moving files now !\n"));
1380 if (driver->driver_path && strlen(driver->driver_path)) {
1382 err = move_driver_file_to_download_area(ctx,
1384 driver->driver_path,
1389 if (!W_ERROR_IS_OK(err)) {
1394 if (driver->data_file && strlen(driver->data_file)) {
1395 if (!strequal(driver->data_file, driver->driver_path)) {
1397 err = move_driver_file_to_download_area(ctx,
1404 if (!W_ERROR_IS_OK(err)) {
1410 if (driver->config_file && strlen(driver->config_file)) {
1411 if (!strequal(driver->config_file, driver->driver_path) &&
1412 !strequal(driver->config_file, driver->data_file)) {
1414 err = move_driver_file_to_download_area(ctx,
1416 driver->config_file,
1421 if (!W_ERROR_IS_OK(err)) {
1427 if (driver->help_file && strlen(driver->help_file)) {
1428 if (!strequal(driver->help_file, driver->driver_path) &&
1429 !strequal(driver->help_file, driver->data_file) &&
1430 !strequal(driver->help_file, driver->config_file)) {
1432 err = move_driver_file_to_download_area(ctx,
1439 if (!W_ERROR_IS_OK(err)) {
1445 if (driver->dependent_files && driver->dependent_files->string) {
1446 for (i=0; driver->dependent_files->string[i]; i++) {
1447 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1448 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1449 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1450 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1452 for (j=0; j < i; j++) {
1453 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1458 err = move_driver_file_to_download_area(ctx,
1460 driver->dependent_files->string[i],
1465 if (!W_ERROR_IS_OK(err)) {
1477 TALLOC_FREE(smb_dname);
1480 vfs_ChDir(conn, oldcwd_fname);
1481 TALLOC_FREE(oldcwd_fname);
1482 SMB_VFS_DISCONNECT(conn);
1489 /****************************************************************************
1490 Determine whether or not a particular driver is currently assigned
1492 ****************************************************************************/
1494 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1495 struct dcerpc_binding_handle *b,
1496 const struct spoolss_DriverInfo8 *r)
1499 int n_services = lp_numservices();
1500 bool in_use = false;
1501 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1508 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1510 /* loop through the printers.tdb and check for the drivername */
1512 for (snum=0; snum<n_services && !in_use; snum++) {
1513 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1517 result = winreg_get_printer(mem_ctx, b,
1518 lp_servicename(talloc_tos(), snum),
1520 if (!W_ERROR_IS_OK(result)) {
1521 continue; /* skip */
1524 if (strequal(r->driver_name, pinfo2->drivername)) {
1528 TALLOC_FREE(pinfo2);
1531 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1534 struct spoolss_DriverInfo8 *driver = NULL;
1537 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1539 /* we can still remove the driver if there is one of
1540 "Windows NT x86" version 2 or 3 left */
1542 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1543 if (r->version == 2) {
1544 werr = winreg_get_driver(mem_ctx, b,
1548 } else if (r->version == 3) {
1549 werr = winreg_get_driver(mem_ctx, b,
1554 DBG_ERR("Unknown driver version (%d)\n",
1556 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1558 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1559 werr = winreg_get_driver(mem_ctx, b,
1560 SPOOLSS_ARCHITECTURE_NT_X86,
1565 DBG_ERR("Unknown driver architecture: %s\n",
1567 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1570 /* now check the error code */
1572 if ( W_ERROR_IS_OK(werr) ) {
1573 /* it's ok to remove the driver, we have other architctures left */
1575 talloc_free(driver);
1579 /* report that the driver is not in use by default */
1585 /**********************************************************************
1586 Check to see if a ogiven file is in use by *info
1587 *********************************************************************/
1589 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1596 /* mz: skip files that are in the list but already deleted */
1597 if (!file || !file[0]) {
1601 if (strequal(file, info->driver_path))
1604 if (strequal(file, info->data_file))
1607 if (strequal(file, info->config_file))
1610 if (strequal(file, info->help_file))
1613 /* see of there are any dependent files to examine */
1615 if (!info->dependent_files)
1618 while (info->dependent_files[i] && *info->dependent_files[i]) {
1619 if (strequal(file, info->dependent_files[i]))
1628 /**********************************************************************
1629 Utility function to remove the dependent file pointed to by the
1630 input parameter from the list
1631 *********************************************************************/
1633 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1636 /* bump everything down a slot */
1638 while (files && files[idx+1]) {
1639 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1648 /**********************************************************************
1649 Check if any of the files used by src are also used by drv
1650 *********************************************************************/
1652 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1653 struct spoolss_DriverInfo8 *src,
1654 const struct spoolss_DriverInfo8 *drv)
1656 bool in_use = False;
1662 /* check each file. Remove it from the src structure if it overlaps */
1664 if (drv_file_in_use(src->driver_path, drv)) {
1666 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1667 src->driver_path = talloc_strdup(mem_ctx, "");
1668 if (!src->driver_path) { return false; }
1671 if (drv_file_in_use(src->data_file, drv)) {
1673 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1674 src->data_file = talloc_strdup(mem_ctx, "");
1675 if (!src->data_file) { return false; }
1678 if (drv_file_in_use(src->config_file, drv)) {
1680 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1681 src->config_file = talloc_strdup(mem_ctx, "");
1682 if (!src->config_file) { return false; }
1685 if (drv_file_in_use(src->help_file, drv)) {
1687 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1688 src->help_file = talloc_strdup(mem_ctx, "");
1689 if (!src->help_file) { return false; }
1692 /* are there any dependentfiles to examine? */
1694 if (!src->dependent_files)
1697 while (src->dependent_files[i] && *src->dependent_files[i]) {
1698 if (drv_file_in_use(src->dependent_files[i], drv)) {
1700 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1701 trim_dependent_file(mem_ctx, src->dependent_files, i);
1709 /****************************************************************************
1710 Determine whether or not a particular driver files are currently being
1711 used by any other driver.
1713 Return value is True if any files were in use by other drivers
1714 and False otherwise.
1716 Upon return, *info has been modified to only contain the driver files
1717 which are not in use
1721 This needs to check all drivers to ensure that all files in use
1722 have been removed from *info, not just the ones in the first
1724 ****************************************************************************/
1726 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1727 struct dcerpc_binding_handle *b,
1728 struct spoolss_DriverInfo8 *info)
1732 struct spoolss_DriverInfo8 *driver;
1733 bool in_use = false;
1734 uint32_t num_drivers;
1735 const char **drivers;
1741 version = info->version;
1743 /* loop over all driver versions */
1745 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1747 /* get the list of drivers */
1749 result = winreg_get_driver_list(mem_ctx, b,
1750 info->architecture, version,
1751 &num_drivers, &drivers);
1752 if (!W_ERROR_IS_OK(result)) {
1756 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1757 num_drivers, info->architecture, version));
1759 /* check each driver for overlap in files */
1761 for (i = 0; i < num_drivers; i++) {
1762 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1766 result = winreg_get_driver(mem_ctx, b,
1767 info->architecture, drivers[i],
1769 if (!W_ERROR_IS_OK(result)) {
1770 talloc_free(drivers);
1774 /* check if d2 uses any files from d1 */
1775 /* only if this is a different driver than the one being deleted */
1777 if (!strequal(info->driver_name, driver->driver_name)) {
1778 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1779 /* mz: Do not instantly return -
1780 * we need to ensure this file isn't
1781 * also in use by other drivers. */
1786 talloc_free(driver);
1789 talloc_free(drivers);
1791 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1796 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1797 const char *short_arch,
1801 TALLOC_CTX *tmp_ctx = talloc_new(conn);
1802 struct smb_filename *smb_fname = NULL;
1803 char *print_dlr_path;
1804 NTSTATUS status = NT_STATUS_NO_MEMORY;
1806 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
1807 short_arch, vers, fname);
1808 if (print_dlr_path == NULL) {
1812 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
1813 if (smb_fname == NULL) {
1817 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1819 talloc_free(tmp_ctx);
1823 /****************************************************************************
1824 Actually delete the driver files. Make sure that
1825 printer_driver_files_in_use() return False before calling
1827 ****************************************************************************/
1829 bool delete_driver_files(const struct auth_session_info *session_info,
1830 const struct spoolss_DriverInfo8 *r)
1832 const char *short_arch;
1833 connection_struct *conn;
1835 struct smb_filename *oldcwd_fname = NULL;
1836 char *printdollar = NULL;
1837 int printdollar_snum;
1844 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1845 r->driver_name, r->version));
1847 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1851 if (printdollar_snum == -1) {
1855 nt_status = create_conn_struct_cwd(talloc_tos(),
1856 server_event_context(),
1857 server_messaging_context(),
1860 lp_path(talloc_tos(), printdollar_snum),
1861 session_info, &oldcwd_fname);
1862 if (!NT_STATUS_IS_OK(nt_status)) {
1863 DEBUG(0,("delete_driver_files: create_conn_struct "
1864 "returned %s\n", nt_errstr(nt_status)));
1868 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1869 if (!NT_STATUS_IS_OK(nt_status)) {
1870 DEBUG(0, ("failed set force user / group\n"));
1875 if (!become_user_by_session(conn, session_info)) {
1876 DEBUG(0, ("failed to become user\n"));
1881 if ( !CAN_WRITE(conn) ) {
1882 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1887 short_arch = get_short_archi(r->architecture);
1888 if (short_arch == NULL) {
1889 DEBUG(0, ("bad architecture %s\n", r->architecture));
1894 /* now delete the files */
1896 if (r->driver_path && r->driver_path[0]) {
1897 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
1898 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
1901 if (r->config_file && r->config_file[0]) {
1902 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
1903 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
1906 if (r->data_file && r->data_file[0]) {
1907 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
1908 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
1911 if (r->help_file && r->help_file[0]) {
1912 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
1913 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
1916 if (r->dependent_files) {
1918 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1919 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
1920 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
1930 vfs_ChDir(conn, oldcwd_fname);
1931 TALLOC_FREE(oldcwd_fname);
1932 SMB_VFS_DISCONNECT(conn);
1940 1: level not implemented
1941 2: file doesn't exist
1942 3: can't allocate memory
1943 4: can't free memory
1944 5: non existent struct
1948 A printer and a printer driver are 2 different things.
1949 NT manages them separatelly, Samba does the same.
1950 Why ? Simply because it's easier and it makes sense !
1952 Now explanation: You have 3 printers behind your samba server,
1953 2 of them are the same make and model (laser A and B). But laser B
1954 has an 3000 sheet feeder and laser A doesn't such an option.
1955 Your third printer is an old dot-matrix model for the accounting :-).
1957 If the /usr/local/samba/lib directory (default dir), you will have
1958 5 files to describe all of this.
1960 3 files for the printers (1 by printer):
1963 NTprinter_accounting
1964 2 files for the drivers (1 for the laser and 1 for the dot matrix)
1965 NTdriver_printer model X
1966 NTdriver_printer model Y
1968 jfm: I should use this comment for the text file to explain
1969 same thing for the forms BTW.
1970 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1974 /* Convert generic access rights to printer object specific access rights.
1975 It turns out that NT4 security descriptors use generic access rights and
1976 NT5 the object specific ones. */
1978 void map_printer_permissions(struct security_descriptor *sd)
1982 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1983 se_map_generic(&sd->dacl->aces[i].access_mask,
1984 &printer_generic_mapping);
1988 void map_job_permissions(struct security_descriptor *sd)
1992 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1993 se_map_generic(&sd->dacl->aces[i].access_mask,
1994 &job_generic_mapping);
1999 /****************************************************************************
2000 Check a user has permissions to perform the given operation. We use the
2001 permission constants defined in include/rpc_spoolss.h to check the various
2002 actions we perform when checking printer access.
2004 PRINTER_ACCESS_ADMINISTER:
2005 print_queue_pause, print_queue_resume, update_printer_sec,
2006 update_printer, spoolss_addprinterex_level_2,
2007 _spoolss_setprinterdata
2012 JOB_ACCESS_ADMINISTER:
2013 print_job_delete, print_job_pause, print_job_resume,
2016 Try access control in the following order (for performance reasons):
2017 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2018 2) check security descriptor (bit comparisons in memory)
2019 3) "printer admins" (may result in numerous calls to winbind)
2021 ****************************************************************************/
2022 WERROR print_access_check(const struct auth_session_info *session_info,
2023 struct messaging_context *msg_ctx, int snum,
2026 struct spoolss_security_descriptor *secdesc = NULL;
2027 uint32_t access_granted;
2032 TALLOC_CTX *mem_ctx = NULL;
2034 /* If user is NULL then use the current_user structure */
2036 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2038 if ((session_info->unix_token->uid == sec_initial_uid())
2039 || security_token_has_privilege(session_info->security_token,
2040 SEC_PRIV_PRINT_OPERATOR)) {
2044 /* Get printer name */
2046 pname = lp_printername(talloc_tos(), snum);
2048 if (!pname || !*pname) {
2049 return WERR_ACCESS_DENIED;
2052 /* Get printer security descriptor */
2054 if(!(mem_ctx = talloc_init("print_access_check"))) {
2055 return WERR_NOT_ENOUGH_MEMORY;
2058 result = winreg_get_printer_secdesc_internal(mem_ctx,
2059 get_session_info_system(),
2063 if (!W_ERROR_IS_OK(result)) {
2064 talloc_destroy(mem_ctx);
2065 return WERR_NOT_ENOUGH_MEMORY;
2068 if (access_type == JOB_ACCESS_ADMINISTER) {
2069 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2071 /* Create a child security descriptor to check permissions
2072 against. This is because print jobs are child objects
2073 objects of a printer. */
2074 status = se_create_child_secdesc(mem_ctx,
2078 parent_secdesc->owner_sid,
2079 parent_secdesc->group_sid,
2081 if (!NT_STATUS_IS_OK(status)) {
2082 talloc_destroy(mem_ctx);
2083 return ntstatus_to_werror(status);
2086 map_job_permissions(secdesc);
2088 map_printer_permissions(secdesc);
2092 status = se_access_check(secdesc, session_info->security_token, access_type,
2095 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2097 talloc_destroy(mem_ctx);
2099 return ntstatus_to_werror(status);
2102 /****************************************************************************
2103 Check the time parameters allow a print operation.
2104 *****************************************************************************/
2106 bool print_time_access_check(const struct auth_session_info *session_info,
2107 struct messaging_context *msg_ctx,
2108 const char *servicename)
2110 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2113 time_t now = time(NULL);
2117 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2118 servicename, &pinfo2);
2119 if (!W_ERROR_IS_OK(result)) {
2123 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2128 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2130 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2134 TALLOC_FREE(pinfo2);
2143 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2144 const struct auth_session_info *session_info,
2145 struct messaging_context *msg_ctx,
2146 const char *printer)
2150 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2152 if (!W_ERROR_IS_OK(result)) {
2153 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2154 "%s\n", printer, win_errstr(result)));
2158 void nt_printer_add(TALLOC_CTX *mem_ctx,
2159 const struct auth_session_info *session_info,
2160 struct messaging_context *msg_ctx,
2161 const char *printer)
2165 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2167 if (!W_ERROR_IS_OK(result)) {
2168 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2169 printer, win_errstr(result)));