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 printing_pread_data(files_struct *fsp,
325 off_t in_pos = *poff;
327 if (in_pos != (off_t)-1) {
328 in_pos = SMB_VFS_LSEEK(fsp, in_pos, SEEK_SET);
329 if (in_pos == (off_t)-1) {
332 /* Don't allow integer wrap on read. */
333 if (in_pos + byte_count < in_pos) {
338 while (total < byte_count) {
339 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
343 if (*poff != (off_t)-1) {
349 if (errno == EINTR) {
358 if (*poff != (off_t)-1) {
361 return (ssize_t)total;
364 /****************************************************************************
365 Detect the major and minor version of a PE file.
368 1 if file is a PE file and we got version numbers,
369 0 if this file is a PE file and we couldn't get the version numbers,
372 NB. buf is passed into and freed inside this function. This is a
373 bad API design, but fixing this is a task for another day.
374 ****************************************************************************/
376 static int handle_pe_file(files_struct *fsp,
384 unsigned int num_sections;
385 unsigned int section_table_bytes;
390 /* Just skip over optional header to get to section table */
391 rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
392 (NE_HEADER_SIZE-PE_HEADER_SIZE);
394 if (in_pos + rel_pos < in_pos) {
398 in_pos = rel_pos + in_pos;
400 /* get the section table */
401 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
402 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
403 if (section_table_bytes == 0) {
408 buf = (char *)SMB_MALLOC(section_table_bytes);
410 DBG_ERR("PE file [%s] section table malloc "
411 "failed bytes = %d\n",
413 section_table_bytes);
417 byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
418 if (byte_count < section_table_bytes) {
419 DBG_NOTICE("PE file [%s] Section header too short, "
420 "bytes read = %lu\n",
422 (unsigned long)byte_count);
427 * Iterate the section table looking for
428 * the resource section ".rsrc"
430 for (i = 0; i < num_sections; i++) {
431 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
434 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
435 unsigned int section_pos = IVAL(buf,
437 PE_HEADER_SECT_PTR_DATA_OFFSET);
438 unsigned int section_bytes = IVAL(buf,
440 PE_HEADER_SECT_SIZE_DATA_OFFSET);
442 if (section_bytes == 0) {
447 buf=(char *)SMB_MALLOC(section_bytes);
449 DBG_ERR("PE file [%s] version malloc "
450 "failed bytes = %d\n",
457 * Read from the start of the .rsrc
460 in_pos = section_pos;
462 byte_count = printing_pread_data(fsp,
466 if (byte_count < section_bytes) {
467 DBG_NOTICE("PE file "
468 "[%s] .rsrc section too short, "
469 "bytes read = %lu\n",
471 (unsigned long)byte_count);
475 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
480 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
483 * Scan for 1st 3 unicoded bytes
484 * followed by word aligned magic
488 bool magic_match = false;
496 if (magic_match == false) {
500 /* Align to next long address */
501 mpos = (i + sizeof(VS_SIGNATURE)*2 +
504 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
506 mpos+ VS_MAJOR_OFFSET);
508 mpos+ VS_MINOR_OFFSET);
510 DBG_INFO("PE file [%s] Version = "
511 "%08x:%08x (%d.%d.%d.%d)\n",
526 /* Version info not found, fall back to origin date/time */
527 DBG_DEBUG("PE file [%s] has no version info\n", fname);
536 /****************************************************************************
537 Detect the major and minor version of an NE file.
540 1 if file is an NE file and we got version numbers,
541 0 if this file is an NE file and we couldn't get the version numbers,
544 NB. buf is passed into and freed inside this function. This is a
545 bad API design, but fixing this is a task for another day.
546 ****************************************************************************/
548 static int handle_ne_file(files_struct *fsp,
559 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
560 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
562 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
564 * At this point, we assume the file is in error.
565 * It still could be something else besides a NE file,
566 * but it unlikely at this point.
571 /* Allocate a bit more space to speed up things */
573 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
575 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
582 * This is a HACK! I got tired of trying to sort through the
583 * messy 'NE' file format. If anyone wants to clean this up
584 * please have at it, but this works. 'NE' files will
585 * eventually fade away. JRR
587 byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
588 while (byte_count > 0) {
590 * Cover case that should not occur in a well
591 * formed 'NE' .dll file
593 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
597 for(i=0; i<byte_count; i++) {
599 * Fast skip past data that can't
603 byte_count = printing_pread_data(fsp,
611 * Potential match data crosses buf boundry,
612 * move it to beginning of buf, and fill the
613 * buf with as much as it will hold.
615 if (i>byte_count-VS_VERSION_INFO_SIZE) {
617 ssize_t amount_unused = byte_count-i;
619 memmove(buf, &buf[i], amount_unused);
620 amount_read = printing_pread_data(fsp,
623 VS_NE_BUF_SIZE- amount_unused);
624 if (amount_read < 0) {
625 DBG_ERR("NE file [%s] Read "
632 if (amount_read + amount_unused <
634 /* Check for integer wrap. */
638 byte_count = amount_read +
640 if (byte_count < VS_VERSION_INFO_SIZE) {
648 * Check that the full signature string and
649 * the magic number that follows exist (not
650 * a perfect solution, but the chances that this
651 * occurs in code is, well, remote. Yes I know
652 * I'm comparing the 'V' twice, as it is
653 * simpler to read the code.
655 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
657 * Compute skip alignment to next
661 int skip = -(cpos - (byte_count - i) +
662 sizeof(VS_SIGNATURE)) & 3;
664 i+sizeof(VS_SIGNATURE)+skip)
666 byte_count = printing_pread_data(fsp,
674 i+sizeof(VS_SIGNATURE)+
675 skip+VS_MAJOR_OFFSET);
677 i+sizeof(VS_SIGNATURE)+
678 skip+VS_MINOR_OFFSET);
679 DBG_INFO("NE file [%s] Version "
680 "= %08x:%08x (%d.%d.%d.%d)\n",
694 /* Version info not found, fall back to origin date/time */
695 DBG_ERR("NE file [%s] Version info not found\n", fname);
704 /****************************************************************************
705 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
706 There are two case to be covered here: PE (Portable Executable) and NE (New
707 Executable) files. Both files support the same INFO structure, but PE files
708 store the signature in unicode, and NE files store it as !unicode.
709 returns -1 on error, 1 on version info found, and 0 on no version info found.
710 ****************************************************************************/
712 static int get_file_version(files_struct *fsp,
719 off_t in_pos = fsp->fh->pos;
721 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
723 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
729 byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
730 if (byte_count < DOS_HEADER_SIZE) {
731 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
733 (unsigned long)byte_count);
734 goto no_version_info;
737 /* Is this really a DOS header? */
738 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
739 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
741 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
742 goto no_version_info;
746 * Skip OEM header (if any) and the
747 * DOS stub to start of Windows header.
749 in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
751 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
752 byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
753 if (byte_count < NE_HEADER_SIZE) {
754 DBG_NOTICE("File [%s] Windows header too short, "
755 "bytes read = %lu\n",
757 (unsigned long)byte_count);
759 * Assume this isn't an error...
760 * the file just looks sort of like a PE/NE file
762 goto no_version_info;
766 * The header may be a PE (Portable Executable)
767 * or an NE (New Executable).
769 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
770 return handle_pe_file(fsp,
776 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
777 NE_HEADER_SIGNATURE) {
778 return handle_ne_file(fsp,
786 * Assume this isn't an error... the file just
787 * looks sort of like a PE/NE file.
789 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
791 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
792 /* Fallthrough into no_version_info: */
804 /****************************************************************************
805 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
806 share one or more files. During the MS installation process files are checked
807 to insure that only a newer version of a shared file is installed over an
808 older version. There are several possibilities for this comparison. If there
809 is no previous version, the new one is newer (obviously). If either file is
810 missing the version info structure, compare the creation date (on Unix use
811 the modification date). Otherwise chose the numerically larger version number.
812 ****************************************************************************/
814 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
816 bool use_version = true;
820 time_t new_create_time;
824 time_t old_create_time;
826 struct smb_filename *smb_fname = NULL;
827 files_struct *fsp = NULL;
833 SET_STAT_INVALID(st);
834 new_create_time = (time_t)0;
835 old_create_time = (time_t)0;
837 /* Get file version info (if available) for previous file (if it exists) */
838 status = driver_unix_convert(conn, old_file, &smb_fname);
839 if (!NT_STATUS_IS_OK(status)) {
843 status = SMB_VFS_CREATE_FILE(
846 0, /* root_dir_fid */
847 smb_fname, /* fname */
848 FILE_GENERIC_READ, /* access_mask */
849 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
850 FILE_OPEN, /* create_disposition*/
851 0, /* create_options */
852 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
853 INTERNAL_OPEN_ONLY, /* oplock_request */
855 0, /* allocation_size */
856 0, /* private_flags */
861 NULL, NULL); /* create context */
863 if (!NT_STATUS_IS_OK(status)) {
864 /* Old file not found, so by definition new file is in fact newer */
865 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
866 "errno = %d\n", smb_fname_str_dbg(smb_fname),
872 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
878 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
881 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
884 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
885 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
886 (long)old_create_time));
889 close_file(NULL, fsp, NORMAL_CLOSE);
892 /* Get file version info (if available) for new file */
893 status = driver_unix_convert(conn, new_file, &smb_fname);
894 if (!NT_STATUS_IS_OK(status)) {
898 status = SMB_VFS_CREATE_FILE(
901 0, /* root_dir_fid */
902 smb_fname, /* fname */
903 FILE_GENERIC_READ, /* access_mask */
904 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
905 FILE_OPEN, /* create_disposition*/
906 0, /* create_options */
907 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
908 INTERNAL_OPEN_ONLY, /* oplock_request */
910 0, /* allocation_size */
911 0, /* private_flags */
916 NULL, NULL); /* create context */
918 if (!NT_STATUS_IS_OK(status)) {
919 /* New file not found, this shouldn't occur if the caller did its job */
920 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
921 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
925 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
931 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
934 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
937 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
938 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
939 (long)new_create_time));
942 close_file(NULL, fsp, NORMAL_CLOSE);
945 if (use_version && (new_major != old_major || new_minor != old_minor)) {
946 /* Compare versions and choose the larger version number */
947 if (new_major > old_major ||
948 (new_major == old_major && new_minor > old_minor)) {
950 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
955 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
961 /* Compare modification time/dates and choose the newest time/date */
962 if (new_create_time > old_create_time) {
963 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
968 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
976 close_file(NULL, fsp, NORMAL_CLOSE);
979 TALLOC_FREE(smb_fname);
983 /****************************************************************************
984 Determine the correct cVersion associated with an architecture and driver
985 ****************************************************************************/
986 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
987 const char *architecture,
988 const char *driverpath_in,
989 const char *driver_directory,
994 struct smb_filename *smb_fname = NULL;
995 files_struct *fsp = NULL;
996 connection_struct *conn = NULL;
997 struct smb_filename *oldcwd_fname = NULL;
998 char *printdollar = NULL;
999 char *printdollar_path = NULL;
1000 char *working_dir = NULL;
1001 int printdollar_snum;
1003 *perr = WERR_INVALID_PARAMETER;
1005 /* If architecture is Windows 95/98/ME, the version is always 0. */
1006 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1007 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1012 /* If architecture is Windows x64, the version is always 3. */
1013 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1014 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1019 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1021 *perr = WERR_NOT_ENOUGH_MEMORY;
1024 if (printdollar_snum == -1) {
1025 *perr = WERR_BAD_NET_NAME;
1029 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
1030 if (printdollar_path == NULL) {
1031 *perr = WERR_NOT_ENOUGH_MEMORY;
1035 working_dir = talloc_asprintf(talloc_tos(),
1040 * If the driver has been uploaded into a temorpary driver
1041 * directory, switch to the driver directory.
1043 if (driver_directory != NULL) {
1044 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
1050 nt_status = create_conn_struct_cwd(talloc_tos(),
1051 server_event_context(),
1052 server_messaging_context(),
1056 session_info, &oldcwd_fname);
1057 if (!NT_STATUS_IS_OK(nt_status)) {
1058 DEBUG(0,("get_correct_cversion: create_conn_struct "
1059 "returned %s\n", nt_errstr(nt_status)));
1060 *perr = ntstatus_to_werror(nt_status);
1064 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1065 if (!NT_STATUS_IS_OK(nt_status)) {
1066 DEBUG(0, ("failed set force user / group\n"));
1067 *perr = ntstatus_to_werror(nt_status);
1068 goto error_free_conn;
1071 if (!become_user_by_session(conn, session_info)) {
1072 DEBUG(0, ("failed to become user\n"));
1073 *perr = WERR_ACCESS_DENIED;
1074 goto error_free_conn;
1078 * We switch to the directory where the driver files are located,
1079 * so only work on the file names
1081 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1082 if (!NT_STATUS_IS_OK(nt_status)) {
1083 *perr = ntstatus_to_werror(nt_status);
1087 nt_status = vfs_file_exist(conn, smb_fname);
1088 if (!NT_STATUS_IS_OK(nt_status)) {
1089 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1090 *perr = WERR_FILE_NOT_FOUND;
1094 nt_status = SMB_VFS_CREATE_FILE(
1097 0, /* root_dir_fid */
1098 smb_fname, /* fname */
1099 FILE_GENERIC_READ, /* access_mask */
1100 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1101 FILE_OPEN, /* create_disposition*/
1102 0, /* create_options */
1103 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1104 INTERNAL_OPEN_ONLY, /* oplock_request */
1106 0, /* private_flags */
1107 0, /* allocation_size */
1112 NULL, NULL); /* create context */
1114 if (!NT_STATUS_IS_OK(nt_status)) {
1115 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1116 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1117 *perr = WERR_ACCESS_DENIED;
1124 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1126 *perr = WERR_INVALID_PARAMETER;
1129 DEBUG(6,("get_correct_cversion: Version info not "
1131 smb_fname_str_dbg(smb_fname)));
1132 *perr = WERR_INVALID_PARAMETER;
1137 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1138 * for more details. Version in this case is not just the version of the
1139 * file, but the version in the sense of kernal mode (2) vs. user mode
1140 * (3) drivers. Other bits of the version fields are the version info.
1143 cversion = major & 0x0000ffff;
1145 case 2: /* WinNT drivers */
1146 case 3: /* Win2K drivers */
1150 DEBUG(6,("get_correct_cversion: cversion "
1151 "invalid [%s] cversion = %d\n",
1152 smb_fname_str_dbg(smb_fname),
1157 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1158 " = 0x%x minor = 0x%x\n",
1159 smb_fname_str_dbg(smb_fname), major, minor));
1162 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1163 smb_fname_str_dbg(smb_fname), cversion));
1169 TALLOC_FREE(smb_fname);
1171 close_file(NULL, fsp, NORMAL_CLOSE);
1174 vfs_ChDir(conn, oldcwd_fname);
1175 TALLOC_FREE(oldcwd_fname);
1176 SMB_VFS_DISCONNECT(conn);
1179 if (!W_ERROR_IS_OK(*perr)) {
1186 /****************************************************************************
1187 ****************************************************************************/
1189 #define strip_driver_path(_mem_ctx, _element) do { \
1190 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1191 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1192 W_ERROR_HAVE_NO_MEMORY((_element)); \
1196 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1197 struct auth_session_info *session_info,
1198 const char *architecture,
1199 const char **driver_path,
1200 const char **data_file,
1201 const char **config_file,
1202 const char **help_file,
1203 struct spoolss_StringArray *dependent_files,
1204 enum spoolss_DriverOSVersion *version,
1206 const char **driver_directory)
1208 const char *short_architecture;
1213 if (!*driver_path || !*data_file) {
1214 return WERR_INVALID_PARAMETER;
1217 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1218 return WERR_INVALID_PARAMETER;
1221 if (flags & APD_COPY_FROM_DIRECTORY) {
1226 * driver_path is set to:
1228 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1230 path = talloc_strdup(mem_ctx, *driver_path);
1232 return WERR_NOT_ENOUGH_MEMORY;
1235 /* Remove pscript5.dll */
1236 q = strrchr_m(path, '\\');
1238 return WERR_INVALID_PARAMETER;
1242 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1243 q = strrchr_m(path, '\\');
1245 return WERR_INVALID_PARAMETER;
1249 * Set driver_directory to:
1251 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1253 * This is the directory where all the files have been uploaded
1255 *driver_directory = q + 1;
1258 /* clean up the driver name.
1259 * we can get .\driver.dll
1260 * or worse c:\windows\system\driver.dll !
1262 /* using an intermediate string to not have overlaping memcpy()'s */
1264 strip_driver_path(mem_ctx, *driver_path);
1265 strip_driver_path(mem_ctx, *data_file);
1267 strip_driver_path(mem_ctx, *config_file);
1270 strip_driver_path(mem_ctx, *help_file);
1273 if (dependent_files && dependent_files->string) {
1274 for (i=0; dependent_files->string[i]; i++) {
1275 strip_driver_path(mem_ctx, dependent_files->string[i]);
1279 short_architecture = get_short_archi(architecture);
1280 if (!short_architecture) {
1281 return WERR_UNKNOWN_PRINTER_DRIVER;
1284 /* jfm:7/16/2000 the client always sends the cversion=0.
1285 * The server should check which version the driver is by reading
1286 * the PE header of driver->driverpath.
1288 * For Windows 95/98 the version is 0 (so the value sent is correct)
1289 * For Windows NT (the architecture doesn't matter)
1290 * NT 3.1: cversion=0
1291 * NT 3.5/3.51: cversion=1
1296 *version = get_correct_cversion(session_info,
1301 if (*version == -1) {
1308 /****************************************************************************
1309 ****************************************************************************/
1311 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1312 struct auth_session_info *session_info,
1313 struct spoolss_AddDriverInfoCtr *r,
1315 const char **driver_directory)
1319 return clean_up_driver_struct_level(mem_ctx, session_info,
1320 r->info.info3->architecture,
1321 &r->info.info3->driver_path,
1322 &r->info.info3->data_file,
1323 &r->info.info3->config_file,
1324 &r->info.info3->help_file,
1325 r->info.info3->dependent_files,
1326 &r->info.info3->version,
1330 return clean_up_driver_struct_level(mem_ctx, session_info,
1331 r->info.info6->architecture,
1332 &r->info.info6->driver_path,
1333 &r->info.info6->data_file,
1334 &r->info.info6->config_file,
1335 &r->info.info6->help_file,
1336 r->info.info6->dependent_files,
1337 &r->info.info6->version,
1341 return clean_up_driver_struct_level(mem_ctx, session_info,
1342 r->info.info8->architecture,
1343 &r->info.info8->driver_path,
1344 &r->info.info8->data_file,
1345 &r->info.info8->config_file,
1346 &r->info.info8->help_file,
1347 r->info.info8->dependent_files,
1348 &r->info.info8->version,
1352 return WERR_NOT_SUPPORTED;
1356 /****************************************************************************
1357 This function sucks and should be replaced. JRA.
1358 ****************************************************************************/
1360 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1361 const struct spoolss_AddDriverInfo6 *src)
1363 dst->version = src->version;
1365 dst->driver_name = src->driver_name;
1366 dst->architecture = src->architecture;
1367 dst->driver_path = src->driver_path;
1368 dst->data_file = src->data_file;
1369 dst->config_file = src->config_file;
1370 dst->help_file = src->help_file;
1371 dst->monitor_name = src->monitor_name;
1372 dst->default_datatype = src->default_datatype;
1373 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1374 dst->dependent_files = src->dependent_files;
1377 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1378 const struct spoolss_AddDriverInfo8 *src)
1380 dst->version = src->version;
1382 dst->driver_name = src->driver_name;
1383 dst->architecture = src->architecture;
1384 dst->driver_path = src->driver_path;
1385 dst->data_file = src->data_file;
1386 dst->config_file = src->config_file;
1387 dst->help_file = src->help_file;
1388 dst->monitor_name = src->monitor_name;
1389 dst->default_datatype = src->default_datatype;
1390 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1391 dst->dependent_files = src->dependent_files;
1394 /****************************************************************************
1395 ****************************************************************************/
1397 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1398 connection_struct *conn,
1399 const char *driver_file,
1400 const char *short_architecture,
1401 uint32_t driver_version,
1403 const char *driver_directory)
1405 struct smb_filename *smb_fname_old = NULL;
1406 struct smb_filename *smb_fname_new = NULL;
1407 char *old_name = NULL;
1408 char *new_name = NULL;
1412 if (driver_directory != NULL) {
1413 old_name = talloc_asprintf(mem_ctx,
1419 old_name = talloc_asprintf(mem_ctx,
1424 if (old_name == NULL) {
1425 return WERR_NOT_ENOUGH_MEMORY;
1428 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1429 short_architecture, driver_version, driver_file);
1430 if (new_name == NULL) {
1431 TALLOC_FREE(old_name);
1432 return WERR_NOT_ENOUGH_MEMORY;
1435 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1437 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 ret = WERR_NOT_ENOUGH_MEMORY;
1443 /* Setup a synthetic smb_filename struct */
1444 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1445 if (!smb_fname_new) {
1446 ret = WERR_NOT_ENOUGH_MEMORY;
1450 smb_fname_new->base_name = new_name;
1452 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1453 "'%s'\n", smb_fname_old->base_name,
1454 smb_fname_new->base_name));
1456 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1457 OPENX_FILE_EXISTS_TRUNCATE |
1458 OPENX_FILE_CREATE_IF_NOT_EXIST,
1461 if (!NT_STATUS_IS_OK(status)) {
1462 DEBUG(0,("move_driver_file_to_download_area: Unable "
1463 "to rename [%s] to [%s]: %s\n",
1464 smb_fname_old->base_name, new_name,
1465 nt_errstr(status)));
1466 ret = WERR_APP_INIT_FAILURE;
1473 TALLOC_FREE(smb_fname_old);
1474 TALLOC_FREE(smb_fname_new);
1478 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1479 struct spoolss_AddDriverInfoCtr *r,
1480 const char *driver_directory)
1482 struct spoolss_AddDriverInfo3 *driver;
1483 struct spoolss_AddDriverInfo3 converted_driver;
1484 const char *short_architecture;
1485 struct smb_filename *smb_dname = NULL;
1486 char *new_dir = NULL;
1487 connection_struct *conn = NULL;
1490 TALLOC_CTX *ctx = talloc_tos();
1492 struct smb_filename *oldcwd_fname = NULL;
1493 char *printdollar = NULL;
1494 int printdollar_snum;
1495 WERROR err = WERR_OK;
1499 driver = r->info.info3;
1502 convert_level_6_to_level3(&converted_driver, r->info.info6);
1503 driver = &converted_driver;
1506 convert_level_8_to_level3(&converted_driver, r->info.info8);
1507 driver = &converted_driver;
1510 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1511 return WERR_INVALID_LEVEL;
1514 short_architecture = get_short_archi(driver->architecture);
1515 if (!short_architecture) {
1516 return WERR_UNKNOWN_PRINTER_DRIVER;
1519 printdollar_snum = find_service(ctx, "print$", &printdollar);
1521 return WERR_NOT_ENOUGH_MEMORY;
1523 if (printdollar_snum == -1) {
1524 return WERR_BAD_NET_NAME;
1527 nt_status = create_conn_struct_cwd(talloc_tos(),
1528 server_event_context(),
1529 server_messaging_context(),
1532 lp_path(talloc_tos(), printdollar_snum),
1533 session_info, &oldcwd_fname);
1534 if (!NT_STATUS_IS_OK(nt_status)) {
1535 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1536 "returned %s\n", nt_errstr(nt_status)));
1537 err = ntstatus_to_werror(nt_status);
1541 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1542 if (!NT_STATUS_IS_OK(nt_status)) {
1543 DEBUG(0, ("failed set force user / group\n"));
1544 err = ntstatus_to_werror(nt_status);
1548 if (!become_user_by_session(conn, session_info)) {
1549 DEBUG(0, ("failed to become user\n"));
1550 err = WERR_ACCESS_DENIED;
1554 new_dir = talloc_asprintf(ctx,
1559 err = WERR_NOT_ENOUGH_MEMORY;
1562 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1563 if (!NT_STATUS_IS_OK(nt_status)) {
1564 err = WERR_NOT_ENOUGH_MEMORY;
1568 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1570 nt_status = create_directory(conn, NULL, smb_dname);
1571 if (!NT_STATUS_IS_OK(nt_status)
1572 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1573 DEBUG(0, ("failed to create driver destination directory: %s\n",
1574 nt_errstr(nt_status)));
1575 err = ntstatus_to_werror(nt_status);
1579 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1580 * listed for this driver which has already been moved, skip it (note:
1581 * drivers may list the same file name several times. Then check if the
1582 * file already exists in archi\version\, if so, check that the version
1583 * info (or time stamps if version info is unavailable) is newer (or the
1584 * date is later). If it is, move it to archi\version\filexxx.yyy.
1585 * Otherwise, delete the file.
1587 * If a file is not moved to archi\version\ because of an error, all the
1588 * rest of the 'unmoved' driver files are removed from archi\. If one or
1589 * more of the driver's files was already moved to archi\version\, it
1590 * potentially leaves the driver in a partially updated state. Version
1591 * trauma will most likely occur if an client attempts to use any printer
1592 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1593 * done is appropriate... later JRR
1596 DEBUG(5,("Moving files now !\n"));
1598 if (driver->driver_path && strlen(driver->driver_path)) {
1600 err = move_driver_file_to_download_area(ctx,
1602 driver->driver_path,
1607 if (!W_ERROR_IS_OK(err)) {
1612 if (driver->data_file && strlen(driver->data_file)) {
1613 if (!strequal(driver->data_file, driver->driver_path)) {
1615 err = move_driver_file_to_download_area(ctx,
1622 if (!W_ERROR_IS_OK(err)) {
1628 if (driver->config_file && strlen(driver->config_file)) {
1629 if (!strequal(driver->config_file, driver->driver_path) &&
1630 !strequal(driver->config_file, driver->data_file)) {
1632 err = move_driver_file_to_download_area(ctx,
1634 driver->config_file,
1639 if (!W_ERROR_IS_OK(err)) {
1645 if (driver->help_file && strlen(driver->help_file)) {
1646 if (!strequal(driver->help_file, driver->driver_path) &&
1647 !strequal(driver->help_file, driver->data_file) &&
1648 !strequal(driver->help_file, driver->config_file)) {
1650 err = move_driver_file_to_download_area(ctx,
1657 if (!W_ERROR_IS_OK(err)) {
1663 if (driver->dependent_files && driver->dependent_files->string) {
1664 for (i=0; driver->dependent_files->string[i]; i++) {
1665 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1666 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1667 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1668 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1670 for (j=0; j < i; j++) {
1671 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1676 err = move_driver_file_to_download_area(ctx,
1678 driver->dependent_files->string[i],
1683 if (!W_ERROR_IS_OK(err)) {
1695 TALLOC_FREE(smb_dname);
1698 vfs_ChDir(conn, oldcwd_fname);
1699 TALLOC_FREE(oldcwd_fname);
1700 SMB_VFS_DISCONNECT(conn);
1707 /****************************************************************************
1708 Determine whether or not a particular driver is currently assigned
1710 ****************************************************************************/
1712 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1713 struct dcerpc_binding_handle *b,
1714 const struct spoolss_DriverInfo8 *r)
1717 int n_services = lp_numservices();
1718 bool in_use = false;
1719 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1726 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1728 /* loop through the printers.tdb and check for the drivername */
1730 for (snum=0; snum<n_services && !in_use; snum++) {
1731 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1735 result = winreg_get_printer(mem_ctx, b,
1736 lp_servicename(talloc_tos(), snum),
1738 if (!W_ERROR_IS_OK(result)) {
1739 continue; /* skip */
1742 if (strequal(r->driver_name, pinfo2->drivername)) {
1746 TALLOC_FREE(pinfo2);
1749 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1752 struct spoolss_DriverInfo8 *driver = NULL;
1755 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1757 /* we can still remove the driver if there is one of
1758 "Windows NT x86" version 2 or 3 left */
1760 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1761 if (r->version == 2) {
1762 werr = winreg_get_driver(mem_ctx, b,
1766 } else if (r->version == 3) {
1767 werr = winreg_get_driver(mem_ctx, b,
1772 DBG_ERR("Unknown driver version (%d)\n",
1774 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1776 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1777 werr = winreg_get_driver(mem_ctx, b,
1778 SPOOLSS_ARCHITECTURE_NT_X86,
1783 DBG_ERR("Unknown driver architecture: %s\n",
1785 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1788 /* now check the error code */
1790 if ( W_ERROR_IS_OK(werr) ) {
1791 /* it's ok to remove the driver, we have other architctures left */
1793 talloc_free(driver);
1797 /* report that the driver is not in use by default */
1803 /**********************************************************************
1804 Check to see if a ogiven file is in use by *info
1805 *********************************************************************/
1807 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1814 /* mz: skip files that are in the list but already deleted */
1815 if (!file || !file[0]) {
1819 if (strequal(file, info->driver_path))
1822 if (strequal(file, info->data_file))
1825 if (strequal(file, info->config_file))
1828 if (strequal(file, info->help_file))
1831 /* see of there are any dependent files to examine */
1833 if (!info->dependent_files)
1836 while (info->dependent_files[i] && *info->dependent_files[i]) {
1837 if (strequal(file, info->dependent_files[i]))
1846 /**********************************************************************
1847 Utility function to remove the dependent file pointed to by the
1848 input parameter from the list
1849 *********************************************************************/
1851 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1854 /* bump everything down a slot */
1856 while (files && files[idx+1]) {
1857 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1866 /**********************************************************************
1867 Check if any of the files used by src are also used by drv
1868 *********************************************************************/
1870 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1871 struct spoolss_DriverInfo8 *src,
1872 const struct spoolss_DriverInfo8 *drv)
1874 bool in_use = False;
1880 /* check each file. Remove it from the src structure if it overlaps */
1882 if (drv_file_in_use(src->driver_path, drv)) {
1884 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1885 src->driver_path = talloc_strdup(mem_ctx, "");
1886 if (!src->driver_path) { return false; }
1889 if (drv_file_in_use(src->data_file, drv)) {
1891 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1892 src->data_file = talloc_strdup(mem_ctx, "");
1893 if (!src->data_file) { return false; }
1896 if (drv_file_in_use(src->config_file, drv)) {
1898 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1899 src->config_file = talloc_strdup(mem_ctx, "");
1900 if (!src->config_file) { return false; }
1903 if (drv_file_in_use(src->help_file, drv)) {
1905 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1906 src->help_file = talloc_strdup(mem_ctx, "");
1907 if (!src->help_file) { return false; }
1910 /* are there any dependentfiles to examine? */
1912 if (!src->dependent_files)
1915 while (src->dependent_files[i] && *src->dependent_files[i]) {
1916 if (drv_file_in_use(src->dependent_files[i], drv)) {
1918 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1919 trim_dependent_file(mem_ctx, src->dependent_files, i);
1927 /****************************************************************************
1928 Determine whether or not a particular driver files are currently being
1929 used by any other driver.
1931 Return value is True if any files were in use by other drivers
1932 and False otherwise.
1934 Upon return, *info has been modified to only contain the driver files
1935 which are not in use
1939 This needs to check all drivers to ensure that all files in use
1940 have been removed from *info, not just the ones in the first
1942 ****************************************************************************/
1944 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1945 struct dcerpc_binding_handle *b,
1946 struct spoolss_DriverInfo8 *info)
1950 struct spoolss_DriverInfo8 *driver;
1951 bool in_use = false;
1952 uint32_t num_drivers;
1953 const char **drivers;
1959 version = info->version;
1961 /* loop over all driver versions */
1963 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1965 /* get the list of drivers */
1967 result = winreg_get_driver_list(mem_ctx, b,
1968 info->architecture, version,
1969 &num_drivers, &drivers);
1970 if (!W_ERROR_IS_OK(result)) {
1974 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1975 num_drivers, info->architecture, version));
1977 /* check each driver for overlap in files */
1979 for (i = 0; i < num_drivers; i++) {
1980 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1984 result = winreg_get_driver(mem_ctx, b,
1985 info->architecture, drivers[i],
1987 if (!W_ERROR_IS_OK(result)) {
1988 talloc_free(drivers);
1992 /* check if d2 uses any files from d1 */
1993 /* only if this is a different driver than the one being deleted */
1995 if (!strequal(info->driver_name, driver->driver_name)) {
1996 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1997 /* mz: Do not instantly return -
1998 * we need to ensure this file isn't
1999 * also in use by other drivers. */
2004 talloc_free(driver);
2007 talloc_free(drivers);
2009 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2014 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2015 const char *short_arch,
2019 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2020 struct smb_filename *smb_fname = NULL;
2021 char *print_dlr_path;
2022 NTSTATUS status = NT_STATUS_NO_MEMORY;
2024 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2025 short_arch, vers, fname);
2026 if (print_dlr_path == NULL) {
2030 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2031 if (smb_fname == NULL) {
2035 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2037 talloc_free(tmp_ctx);
2041 /****************************************************************************
2042 Actually delete the driver files. Make sure that
2043 printer_driver_files_in_use() return False before calling
2045 ****************************************************************************/
2047 bool delete_driver_files(const struct auth_session_info *session_info,
2048 const struct spoolss_DriverInfo8 *r)
2050 const char *short_arch;
2051 connection_struct *conn;
2053 struct smb_filename *oldcwd_fname = NULL;
2054 char *printdollar = NULL;
2055 int printdollar_snum;
2062 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2063 r->driver_name, r->version));
2065 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2069 if (printdollar_snum == -1) {
2073 nt_status = create_conn_struct_cwd(talloc_tos(),
2074 server_event_context(),
2075 server_messaging_context(),
2078 lp_path(talloc_tos(), printdollar_snum),
2079 session_info, &oldcwd_fname);
2080 if (!NT_STATUS_IS_OK(nt_status)) {
2081 DEBUG(0,("delete_driver_files: create_conn_struct "
2082 "returned %s\n", nt_errstr(nt_status)));
2086 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2087 if (!NT_STATUS_IS_OK(nt_status)) {
2088 DEBUG(0, ("failed set force user / group\n"));
2093 if (!become_user_by_session(conn, session_info)) {
2094 DEBUG(0, ("failed to become user\n"));
2099 if ( !CAN_WRITE(conn) ) {
2100 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2105 short_arch = get_short_archi(r->architecture);
2106 if (short_arch == NULL) {
2107 DEBUG(0, ("bad architecture %s\n", r->architecture));
2112 /* now delete the files */
2114 if (r->driver_path && r->driver_path[0]) {
2115 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2116 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2119 if (r->config_file && r->config_file[0]) {
2120 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2121 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2124 if (r->data_file && r->data_file[0]) {
2125 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2126 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2129 if (r->help_file && r->help_file[0]) {
2130 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2131 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2134 if (r->dependent_files) {
2136 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2137 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2138 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2148 vfs_ChDir(conn, oldcwd_fname);
2149 TALLOC_FREE(oldcwd_fname);
2150 SMB_VFS_DISCONNECT(conn);
2158 1: level not implemented
2159 2: file doesn't exist
2160 3: can't allocate memory
2161 4: can't free memory
2162 5: non existent struct
2166 A printer and a printer driver are 2 different things.
2167 NT manages them separatelly, Samba does the same.
2168 Why ? Simply because it's easier and it makes sense !
2170 Now explanation: You have 3 printers behind your samba server,
2171 2 of them are the same make and model (laser A and B). But laser B
2172 has an 3000 sheet feeder and laser A doesn't such an option.
2173 Your third printer is an old dot-matrix model for the accounting :-).
2175 If the /usr/local/samba/lib directory (default dir), you will have
2176 5 files to describe all of this.
2178 3 files for the printers (1 by printer):
2181 NTprinter_accounting
2182 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2183 NTdriver_printer model X
2184 NTdriver_printer model Y
2186 jfm: I should use this comment for the text file to explain
2187 same thing for the forms BTW.
2188 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2192 /* Convert generic access rights to printer object specific access rights.
2193 It turns out that NT4 security descriptors use generic access rights and
2194 NT5 the object specific ones. */
2196 void map_printer_permissions(struct security_descriptor *sd)
2200 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2201 se_map_generic(&sd->dacl->aces[i].access_mask,
2202 &printer_generic_mapping);
2206 void map_job_permissions(struct security_descriptor *sd)
2210 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2211 se_map_generic(&sd->dacl->aces[i].access_mask,
2212 &job_generic_mapping);
2217 /****************************************************************************
2218 Check a user has permissions to perform the given operation. We use the
2219 permission constants defined in include/rpc_spoolss.h to check the various
2220 actions we perform when checking printer access.
2222 PRINTER_ACCESS_ADMINISTER:
2223 print_queue_pause, print_queue_resume, update_printer_sec,
2224 update_printer, spoolss_addprinterex_level_2,
2225 _spoolss_setprinterdata
2230 JOB_ACCESS_ADMINISTER:
2231 print_job_delete, print_job_pause, print_job_resume,
2234 Try access control in the following order (for performance reasons):
2235 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2236 2) check security descriptor (bit comparisons in memory)
2237 3) "printer admins" (may result in numerous calls to winbind)
2239 ****************************************************************************/
2240 WERROR print_access_check(const struct auth_session_info *session_info,
2241 struct messaging_context *msg_ctx, int snum,
2244 struct spoolss_security_descriptor *secdesc = NULL;
2245 uint32_t access_granted;
2250 TALLOC_CTX *mem_ctx = NULL;
2252 /* If user is NULL then use the current_user structure */
2254 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2256 if ((session_info->unix_token->uid == sec_initial_uid())
2257 || security_token_has_privilege(session_info->security_token,
2258 SEC_PRIV_PRINT_OPERATOR)) {
2262 /* Get printer name */
2264 pname = lp_printername(talloc_tos(), snum);
2266 if (!pname || !*pname) {
2267 return WERR_ACCESS_DENIED;
2270 /* Get printer security descriptor */
2272 if(!(mem_ctx = talloc_init("print_access_check"))) {
2273 return WERR_NOT_ENOUGH_MEMORY;
2276 result = winreg_get_printer_secdesc_internal(mem_ctx,
2277 get_session_info_system(),
2281 if (!W_ERROR_IS_OK(result)) {
2282 talloc_destroy(mem_ctx);
2283 return WERR_NOT_ENOUGH_MEMORY;
2286 if (access_type == JOB_ACCESS_ADMINISTER) {
2287 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2289 /* Create a child security descriptor to check permissions
2290 against. This is because print jobs are child objects
2291 objects of a printer. */
2292 status = se_create_child_secdesc(mem_ctx,
2296 parent_secdesc->owner_sid,
2297 parent_secdesc->group_sid,
2299 if (!NT_STATUS_IS_OK(status)) {
2300 talloc_destroy(mem_ctx);
2301 return ntstatus_to_werror(status);
2304 map_job_permissions(secdesc);
2306 map_printer_permissions(secdesc);
2310 status = se_access_check(secdesc, session_info->security_token, access_type,
2313 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2315 talloc_destroy(mem_ctx);
2317 return ntstatus_to_werror(status);
2320 /****************************************************************************
2321 Check the time parameters allow a print operation.
2322 *****************************************************************************/
2324 bool print_time_access_check(const struct auth_session_info *session_info,
2325 struct messaging_context *msg_ctx,
2326 const char *servicename)
2328 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2331 time_t now = time(NULL);
2335 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2336 servicename, &pinfo2);
2337 if (!W_ERROR_IS_OK(result)) {
2341 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2346 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2348 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2352 TALLOC_FREE(pinfo2);
2361 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2362 const struct auth_session_info *session_info,
2363 struct messaging_context *msg_ctx,
2364 const char *printer)
2368 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2370 if (!W_ERROR_IS_OK(result)) {
2371 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2372 "%s\n", printer, win_errstr(result)));
2376 void nt_printer_add(TALLOC_CTX *mem_ctx,
2377 const struct auth_session_info *session_info,
2378 struct messaging_context *msg_ctx,
2379 const char *printer)
2383 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2385 if (!W_ERROR_IS_OK(result)) {
2386 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2387 printer, win_errstr(result)));