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 /* Don't allow integer wrap on read. */
328 if (in_pos + byte_count < in_pos) {
332 while (total < byte_count) {
333 ssize_t ret = read_file(fsp,
343 if (errno == EINTR) {
353 return (ssize_t)total;
356 /****************************************************************************
357 Detect the major and minor version of a PE file.
360 1 if file is a PE file and we got version numbers,
361 0 if this file is a PE file and we couldn't get the version numbers,
364 NB. buf is passed into and freed inside this function. This is a
365 bad API design, but fixing this is a task for another day.
366 ****************************************************************************/
368 static int handle_pe_file(files_struct *fsp,
376 unsigned int num_sections;
377 unsigned int section_table_bytes;
382 /* Just skip over optional header to get to section table */
383 rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
384 (NE_HEADER_SIZE-PE_HEADER_SIZE);
386 if (in_pos + rel_pos < in_pos) {
390 in_pos = rel_pos + in_pos;
392 /* get the section table */
393 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
394 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
395 if (section_table_bytes == 0) {
400 buf = (char *)SMB_MALLOC(section_table_bytes);
402 DBG_ERR("PE file [%s] section table malloc "
403 "failed bytes = %d\n",
405 section_table_bytes);
409 byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
410 if (byte_count < section_table_bytes) {
411 DBG_NOTICE("PE file [%s] Section header too short, "
412 "bytes read = %lu\n",
414 (unsigned long)byte_count);
419 * Iterate the section table looking for
420 * the resource section ".rsrc"
422 for (i = 0; i < num_sections; i++) {
423 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
426 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
427 unsigned int section_pos = IVAL(buf,
429 PE_HEADER_SECT_PTR_DATA_OFFSET);
430 unsigned int section_bytes = IVAL(buf,
432 PE_HEADER_SECT_SIZE_DATA_OFFSET);
434 if (section_bytes == 0) {
439 buf=(char *)SMB_MALLOC(section_bytes);
441 DBG_ERR("PE file [%s] version malloc "
442 "failed bytes = %d\n",
449 * Read from the start of the .rsrc
452 in_pos = section_pos;
454 byte_count = printing_pread_data(fsp,
458 if (byte_count < section_bytes) {
459 DBG_NOTICE("PE file "
460 "[%s] .rsrc section too short, "
461 "bytes read = %lu\n",
463 (unsigned long)byte_count);
467 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
472 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
475 * Scan for 1st 3 unicoded bytes
476 * followed by word aligned magic
480 bool magic_match = false;
488 if (magic_match == false) {
492 /* Align to next long address */
493 mpos = (i + sizeof(VS_SIGNATURE)*2 +
496 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
498 mpos+ VS_MAJOR_OFFSET);
500 mpos+ VS_MINOR_OFFSET);
502 DBG_INFO("PE file [%s] Version = "
503 "%08x:%08x (%d.%d.%d.%d)\n",
518 /* Version info not found, fall back to origin date/time */
519 DBG_DEBUG("PE file [%s] has no version info\n", fname);
528 /****************************************************************************
529 Detect the major and minor version of an NE file.
532 1 if file is an NE file and we got version numbers,
533 0 if this file is an NE file and we couldn't get the version numbers,
536 NB. buf is passed into and freed inside this function. This is a
537 bad API design, but fixing this is a task for another day.
538 ****************************************************************************/
540 static int handle_ne_file(files_struct *fsp,
551 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
552 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
554 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
556 * At this point, we assume the file is in error.
557 * It still could be something else besides a NE file,
558 * but it unlikely at this point.
563 /* Allocate a bit more space to speed up things */
565 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
567 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
574 * This is a HACK! I got tired of trying to sort through the
575 * messy 'NE' file format. If anyone wants to clean this up
576 * please have at it, but this works. 'NE' files will
577 * eventually fade away. JRR
579 byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
580 while (byte_count > 0) {
582 * Cover case that should not occur in a well
583 * formed 'NE' .dll file
585 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
589 for(i=0; i<byte_count; i++) {
591 * Fast skip past data that can't
595 byte_count = printing_pread_data(fsp,
603 * Potential match data crosses buf boundry,
604 * move it to beginning of buf, and fill the
605 * buf with as much as it will hold.
607 if (i>byte_count-VS_VERSION_INFO_SIZE) {
609 ssize_t amount_unused = byte_count-i;
611 memmove(buf, &buf[i], amount_unused);
612 amount_read = printing_pread_data(fsp,
615 VS_NE_BUF_SIZE- amount_unused);
616 if (amount_read < 0) {
617 DBG_ERR("NE file [%s] Read "
624 if (amount_read + amount_unused <
626 /* Check for integer wrap. */
630 byte_count = amount_read +
632 if (byte_count < VS_VERSION_INFO_SIZE) {
640 * Check that the full signature string and
641 * the magic number that follows exist (not
642 * a perfect solution, but the chances that this
643 * occurs in code is, well, remote. Yes I know
644 * I'm comparing the 'V' twice, as it is
645 * simpler to read the code.
647 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
649 * Compute skip alignment to next
653 int skip = -(cpos - (byte_count - i) +
654 sizeof(VS_SIGNATURE)) & 3;
656 i+sizeof(VS_SIGNATURE)+skip)
658 byte_count = printing_pread_data(fsp,
666 i+sizeof(VS_SIGNATURE)+
667 skip+VS_MAJOR_OFFSET);
669 i+sizeof(VS_SIGNATURE)+
670 skip+VS_MINOR_OFFSET);
671 DBG_INFO("NE file [%s] Version "
672 "= %08x:%08x (%d.%d.%d.%d)\n",
686 /* Version info not found, fall back to origin date/time */
687 DBG_ERR("NE file [%s] Version info not found\n", fname);
696 /****************************************************************************
697 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
698 There are two case to be covered here: PE (Portable Executable) and NE (New
699 Executable) files. Both files support the same INFO structure, but PE files
700 store the signature in unicode, and NE files store it as !unicode.
701 returns -1 on error, 1 on version info found, and 0 on no version info found.
702 ****************************************************************************/
704 static int get_file_version(files_struct *fsp,
711 off_t in_pos = fsp->fh->pos;
713 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
715 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
721 byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
722 if (byte_count < DOS_HEADER_SIZE) {
723 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
725 (unsigned long)byte_count);
726 goto no_version_info;
729 /* Is this really a DOS header? */
730 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
731 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
733 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
734 goto no_version_info;
738 * Skip OEM header (if any) and the
739 * DOS stub to start of Windows header.
741 in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
743 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
744 byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
745 if (byte_count < NE_HEADER_SIZE) {
746 DBG_NOTICE("File [%s] Windows header too short, "
747 "bytes read = %lu\n",
749 (unsigned long)byte_count);
751 * Assume this isn't an error...
752 * the file just looks sort of like a PE/NE file
754 goto no_version_info;
758 * The header may be a PE (Portable Executable)
759 * or an NE (New Executable).
761 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
762 return handle_pe_file(fsp,
768 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
769 NE_HEADER_SIGNATURE) {
770 return handle_ne_file(fsp,
778 * Assume this isn't an error... the file just
779 * looks sort of like a PE/NE file.
781 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
783 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
784 /* Fallthrough into no_version_info: */
796 /****************************************************************************
797 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
798 share one or more files. During the MS installation process files are checked
799 to insure that only a newer version of a shared file is installed over an
800 older version. There are several possibilities for this comparison. If there
801 is no previous version, the new one is newer (obviously). If either file is
802 missing the version info structure, compare the creation date (on Unix use
803 the modification date). Otherwise chose the numerically larger version number.
804 ****************************************************************************/
806 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
808 bool use_version = true;
812 time_t new_create_time;
816 time_t old_create_time;
818 struct smb_filename *smb_fname = NULL;
819 files_struct *fsp = NULL;
825 SET_STAT_INVALID(st);
826 new_create_time = (time_t)0;
827 old_create_time = (time_t)0;
829 /* Get file version info (if available) for previous file (if it exists) */
830 status = driver_unix_convert(conn, old_file, &smb_fname);
831 if (!NT_STATUS_IS_OK(status)) {
835 status = SMB_VFS_CREATE_FILE(
838 0, /* root_dir_fid */
839 smb_fname, /* fname */
840 FILE_GENERIC_READ, /* access_mask */
841 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
842 FILE_OPEN, /* create_disposition*/
843 0, /* create_options */
844 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
845 INTERNAL_OPEN_ONLY, /* oplock_request */
847 0, /* allocation_size */
848 0, /* private_flags */
853 NULL, NULL); /* create context */
855 if (!NT_STATUS_IS_OK(status)) {
856 /* Old file not found, so by definition new file is in fact newer */
857 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
858 "errno = %d\n", smb_fname_str_dbg(smb_fname),
864 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
870 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
873 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
876 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
877 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
878 (long)old_create_time));
881 close_file(NULL, fsp, NORMAL_CLOSE);
884 /* Get file version info (if available) for new file */
885 status = driver_unix_convert(conn, new_file, &smb_fname);
886 if (!NT_STATUS_IS_OK(status)) {
890 status = SMB_VFS_CREATE_FILE(
893 0, /* root_dir_fid */
894 smb_fname, /* fname */
895 FILE_GENERIC_READ, /* access_mask */
896 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
897 FILE_OPEN, /* create_disposition*/
898 0, /* create_options */
899 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
900 INTERNAL_OPEN_ONLY, /* oplock_request */
902 0, /* allocation_size */
903 0, /* private_flags */
908 NULL, NULL); /* create context */
910 if (!NT_STATUS_IS_OK(status)) {
911 /* New file not found, this shouldn't occur if the caller did its job */
912 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
913 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
917 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
923 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
926 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
929 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
930 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
931 (long)new_create_time));
934 close_file(NULL, fsp, NORMAL_CLOSE);
937 if (use_version && (new_major != old_major || new_minor != old_minor)) {
938 /* Compare versions and choose the larger version number */
939 if (new_major > old_major ||
940 (new_major == old_major && new_minor > old_minor)) {
942 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
947 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
953 /* Compare modification time/dates and choose the newest time/date */
954 if (new_create_time > old_create_time) {
955 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
960 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
968 close_file(NULL, fsp, NORMAL_CLOSE);
971 TALLOC_FREE(smb_fname);
975 /****************************************************************************
976 Determine the correct cVersion associated with an architecture and driver
977 ****************************************************************************/
978 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
979 const char *architecture,
980 const char *driverpath_in,
981 const char *driver_directory,
986 struct smb_filename *smb_fname = NULL;
987 files_struct *fsp = NULL;
988 connection_struct *conn = NULL;
989 struct smb_filename *oldcwd_fname = NULL;
990 char *printdollar = NULL;
991 char *printdollar_path = NULL;
992 char *working_dir = NULL;
993 int printdollar_snum;
995 *perr = WERR_INVALID_PARAMETER;
997 /* If architecture is Windows 95/98/ME, the version is always 0. */
998 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
999 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1004 /* If architecture is Windows x64, the version is always 3. */
1005 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1006 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1011 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1013 *perr = WERR_NOT_ENOUGH_MEMORY;
1016 if (printdollar_snum == -1) {
1017 *perr = WERR_BAD_NET_NAME;
1021 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
1022 if (printdollar_path == NULL) {
1023 *perr = WERR_NOT_ENOUGH_MEMORY;
1027 working_dir = talloc_asprintf(talloc_tos(),
1032 * If the driver has been uploaded into a temorpary driver
1033 * directory, switch to the driver directory.
1035 if (driver_directory != NULL) {
1036 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
1042 nt_status = create_conn_struct_cwd(talloc_tos(),
1043 server_event_context(),
1044 server_messaging_context(),
1048 session_info, &oldcwd_fname);
1049 if (!NT_STATUS_IS_OK(nt_status)) {
1050 DEBUG(0,("get_correct_cversion: create_conn_struct "
1051 "returned %s\n", nt_errstr(nt_status)));
1052 *perr = ntstatus_to_werror(nt_status);
1056 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1057 if (!NT_STATUS_IS_OK(nt_status)) {
1058 DEBUG(0, ("failed set force user / group\n"));
1059 *perr = ntstatus_to_werror(nt_status);
1060 goto error_free_conn;
1063 if (!become_user_by_session(conn, session_info)) {
1064 DEBUG(0, ("failed to become user\n"));
1065 *perr = WERR_ACCESS_DENIED;
1066 goto error_free_conn;
1070 * We switch to the directory where the driver files are located,
1071 * so only work on the file names
1073 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1074 if (!NT_STATUS_IS_OK(nt_status)) {
1075 *perr = ntstatus_to_werror(nt_status);
1079 nt_status = vfs_file_exist(conn, smb_fname);
1080 if (!NT_STATUS_IS_OK(nt_status)) {
1081 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1082 *perr = WERR_FILE_NOT_FOUND;
1086 nt_status = SMB_VFS_CREATE_FILE(
1089 0, /* root_dir_fid */
1090 smb_fname, /* fname */
1091 FILE_GENERIC_READ, /* access_mask */
1092 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1093 FILE_OPEN, /* create_disposition*/
1094 0, /* create_options */
1095 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1096 INTERNAL_OPEN_ONLY, /* oplock_request */
1098 0, /* private_flags */
1099 0, /* allocation_size */
1104 NULL, NULL); /* create context */
1106 if (!NT_STATUS_IS_OK(nt_status)) {
1107 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1108 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1109 *perr = WERR_ACCESS_DENIED;
1116 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1118 *perr = WERR_INVALID_PARAMETER;
1121 DEBUG(6,("get_correct_cversion: Version info not "
1123 smb_fname_str_dbg(smb_fname)));
1124 *perr = WERR_INVALID_PARAMETER;
1129 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1130 * for more details. Version in this case is not just the version of the
1131 * file, but the version in the sense of kernal mode (2) vs. user mode
1132 * (3) drivers. Other bits of the version fields are the version info.
1135 cversion = major & 0x0000ffff;
1137 case 2: /* WinNT drivers */
1138 case 3: /* Win2K drivers */
1142 DEBUG(6,("get_correct_cversion: cversion "
1143 "invalid [%s] cversion = %d\n",
1144 smb_fname_str_dbg(smb_fname),
1149 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1150 " = 0x%x minor = 0x%x\n",
1151 smb_fname_str_dbg(smb_fname), major, minor));
1154 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1155 smb_fname_str_dbg(smb_fname), cversion));
1161 TALLOC_FREE(smb_fname);
1163 close_file(NULL, fsp, NORMAL_CLOSE);
1166 vfs_ChDir(conn, oldcwd_fname);
1167 TALLOC_FREE(oldcwd_fname);
1168 SMB_VFS_DISCONNECT(conn);
1171 if (!W_ERROR_IS_OK(*perr)) {
1178 /****************************************************************************
1179 ****************************************************************************/
1181 #define strip_driver_path(_mem_ctx, _element) do { \
1182 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1183 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1184 W_ERROR_HAVE_NO_MEMORY((_element)); \
1188 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1189 struct auth_session_info *session_info,
1190 const char *architecture,
1191 const char **driver_path,
1192 const char **data_file,
1193 const char **config_file,
1194 const char **help_file,
1195 struct spoolss_StringArray *dependent_files,
1196 enum spoolss_DriverOSVersion *version,
1198 const char **driver_directory)
1200 const char *short_architecture;
1205 if (!*driver_path || !*data_file) {
1206 return WERR_INVALID_PARAMETER;
1209 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1210 return WERR_INVALID_PARAMETER;
1213 if (flags & APD_COPY_FROM_DIRECTORY) {
1218 * driver_path is set to:
1220 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1222 path = talloc_strdup(mem_ctx, *driver_path);
1224 return WERR_NOT_ENOUGH_MEMORY;
1227 /* Remove pscript5.dll */
1228 q = strrchr_m(path, '\\');
1230 return WERR_INVALID_PARAMETER;
1234 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1235 q = strrchr_m(path, '\\');
1237 return WERR_INVALID_PARAMETER;
1241 * Set driver_directory to:
1243 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1245 * This is the directory where all the files have been uploaded
1247 *driver_directory = q + 1;
1250 /* clean up the driver name.
1251 * we can get .\driver.dll
1252 * or worse c:\windows\system\driver.dll !
1254 /* using an intermediate string to not have overlaping memcpy()'s */
1256 strip_driver_path(mem_ctx, *driver_path);
1257 strip_driver_path(mem_ctx, *data_file);
1259 strip_driver_path(mem_ctx, *config_file);
1262 strip_driver_path(mem_ctx, *help_file);
1265 if (dependent_files && dependent_files->string) {
1266 for (i=0; dependent_files->string[i]; i++) {
1267 strip_driver_path(mem_ctx, dependent_files->string[i]);
1271 short_architecture = get_short_archi(architecture);
1272 if (!short_architecture) {
1273 return WERR_UNKNOWN_PRINTER_DRIVER;
1276 /* jfm:7/16/2000 the client always sends the cversion=0.
1277 * The server should check which version the driver is by reading
1278 * the PE header of driver->driverpath.
1280 * For Windows 95/98 the version is 0 (so the value sent is correct)
1281 * For Windows NT (the architecture doesn't matter)
1282 * NT 3.1: cversion=0
1283 * NT 3.5/3.51: cversion=1
1288 *version = get_correct_cversion(session_info,
1293 if (*version == -1) {
1300 /****************************************************************************
1301 ****************************************************************************/
1303 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1304 struct auth_session_info *session_info,
1305 struct spoolss_AddDriverInfoCtr *r,
1307 const char **driver_directory)
1311 return clean_up_driver_struct_level(mem_ctx, session_info,
1312 r->info.info3->architecture,
1313 &r->info.info3->driver_path,
1314 &r->info.info3->data_file,
1315 &r->info.info3->config_file,
1316 &r->info.info3->help_file,
1317 r->info.info3->dependent_files,
1318 &r->info.info3->version,
1322 return clean_up_driver_struct_level(mem_ctx, session_info,
1323 r->info.info6->architecture,
1324 &r->info.info6->driver_path,
1325 &r->info.info6->data_file,
1326 &r->info.info6->config_file,
1327 &r->info.info6->help_file,
1328 r->info.info6->dependent_files,
1329 &r->info.info6->version,
1333 return clean_up_driver_struct_level(mem_ctx, session_info,
1334 r->info.info8->architecture,
1335 &r->info.info8->driver_path,
1336 &r->info.info8->data_file,
1337 &r->info.info8->config_file,
1338 &r->info.info8->help_file,
1339 r->info.info8->dependent_files,
1340 &r->info.info8->version,
1344 return WERR_NOT_SUPPORTED;
1348 /****************************************************************************
1349 This function sucks and should be replaced. JRA.
1350 ****************************************************************************/
1352 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1353 const struct spoolss_AddDriverInfo6 *src)
1355 dst->version = src->version;
1357 dst->driver_name = src->driver_name;
1358 dst->architecture = src->architecture;
1359 dst->driver_path = src->driver_path;
1360 dst->data_file = src->data_file;
1361 dst->config_file = src->config_file;
1362 dst->help_file = src->help_file;
1363 dst->monitor_name = src->monitor_name;
1364 dst->default_datatype = src->default_datatype;
1365 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1366 dst->dependent_files = src->dependent_files;
1369 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1370 const struct spoolss_AddDriverInfo8 *src)
1372 dst->version = src->version;
1374 dst->driver_name = src->driver_name;
1375 dst->architecture = src->architecture;
1376 dst->driver_path = src->driver_path;
1377 dst->data_file = src->data_file;
1378 dst->config_file = src->config_file;
1379 dst->help_file = src->help_file;
1380 dst->monitor_name = src->monitor_name;
1381 dst->default_datatype = src->default_datatype;
1382 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1383 dst->dependent_files = src->dependent_files;
1386 /****************************************************************************
1387 ****************************************************************************/
1389 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1390 connection_struct *conn,
1391 const char *driver_file,
1392 const char *short_architecture,
1393 uint32_t driver_version,
1395 const char *driver_directory)
1397 struct smb_filename *smb_fname_old = NULL;
1398 struct smb_filename *smb_fname_new = NULL;
1399 char *old_name = NULL;
1400 char *new_name = NULL;
1404 if (driver_directory != NULL) {
1405 old_name = talloc_asprintf(mem_ctx,
1411 old_name = talloc_asprintf(mem_ctx,
1416 if (old_name == NULL) {
1417 return WERR_NOT_ENOUGH_MEMORY;
1420 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1421 short_architecture, driver_version, driver_file);
1422 if (new_name == NULL) {
1423 TALLOC_FREE(old_name);
1424 return WERR_NOT_ENOUGH_MEMORY;
1427 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1429 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 ret = WERR_NOT_ENOUGH_MEMORY;
1435 /* Setup a synthetic smb_filename struct */
1436 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1437 if (!smb_fname_new) {
1438 ret = WERR_NOT_ENOUGH_MEMORY;
1442 smb_fname_new->base_name = new_name;
1444 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1445 "'%s'\n", smb_fname_old->base_name,
1446 smb_fname_new->base_name));
1448 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1449 OPENX_FILE_EXISTS_TRUNCATE |
1450 OPENX_FILE_CREATE_IF_NOT_EXIST,
1453 if (!NT_STATUS_IS_OK(status)) {
1454 DEBUG(0,("move_driver_file_to_download_area: Unable "
1455 "to rename [%s] to [%s]: %s\n",
1456 smb_fname_old->base_name, new_name,
1457 nt_errstr(status)));
1458 ret = WERR_APP_INIT_FAILURE;
1465 TALLOC_FREE(smb_fname_old);
1466 TALLOC_FREE(smb_fname_new);
1470 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1471 struct spoolss_AddDriverInfoCtr *r,
1472 const char *driver_directory)
1474 struct spoolss_AddDriverInfo3 *driver;
1475 struct spoolss_AddDriverInfo3 converted_driver;
1476 const char *short_architecture;
1477 struct smb_filename *smb_dname = NULL;
1478 char *new_dir = NULL;
1479 connection_struct *conn = NULL;
1482 TALLOC_CTX *ctx = talloc_tos();
1484 struct smb_filename *oldcwd_fname = NULL;
1485 char *printdollar = NULL;
1486 int printdollar_snum;
1487 WERROR err = WERR_OK;
1491 driver = r->info.info3;
1494 convert_level_6_to_level3(&converted_driver, r->info.info6);
1495 driver = &converted_driver;
1498 convert_level_8_to_level3(&converted_driver, r->info.info8);
1499 driver = &converted_driver;
1502 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1503 return WERR_INVALID_LEVEL;
1506 short_architecture = get_short_archi(driver->architecture);
1507 if (!short_architecture) {
1508 return WERR_UNKNOWN_PRINTER_DRIVER;
1511 printdollar_snum = find_service(ctx, "print$", &printdollar);
1513 return WERR_NOT_ENOUGH_MEMORY;
1515 if (printdollar_snum == -1) {
1516 return WERR_BAD_NET_NAME;
1519 nt_status = create_conn_struct_cwd(talloc_tos(),
1520 server_event_context(),
1521 server_messaging_context(),
1524 lp_path(talloc_tos(), printdollar_snum),
1525 session_info, &oldcwd_fname);
1526 if (!NT_STATUS_IS_OK(nt_status)) {
1527 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1528 "returned %s\n", nt_errstr(nt_status)));
1529 err = ntstatus_to_werror(nt_status);
1533 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1534 if (!NT_STATUS_IS_OK(nt_status)) {
1535 DEBUG(0, ("failed set force user / group\n"));
1536 err = ntstatus_to_werror(nt_status);
1540 if (!become_user_by_session(conn, session_info)) {
1541 DEBUG(0, ("failed to become user\n"));
1542 err = WERR_ACCESS_DENIED;
1546 new_dir = talloc_asprintf(ctx,
1551 err = WERR_NOT_ENOUGH_MEMORY;
1554 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1555 if (!NT_STATUS_IS_OK(nt_status)) {
1556 err = WERR_NOT_ENOUGH_MEMORY;
1560 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1562 nt_status = create_directory(conn, NULL, smb_dname);
1563 if (!NT_STATUS_IS_OK(nt_status)
1564 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1565 DEBUG(0, ("failed to create driver destination directory: %s\n",
1566 nt_errstr(nt_status)));
1567 err = ntstatus_to_werror(nt_status);
1571 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1572 * listed for this driver which has already been moved, skip it (note:
1573 * drivers may list the same file name several times. Then check if the
1574 * file already exists in archi\version\, if so, check that the version
1575 * info (or time stamps if version info is unavailable) is newer (or the
1576 * date is later). If it is, move it to archi\version\filexxx.yyy.
1577 * Otherwise, delete the file.
1579 * If a file is not moved to archi\version\ because of an error, all the
1580 * rest of the 'unmoved' driver files are removed from archi\. If one or
1581 * more of the driver's files was already moved to archi\version\, it
1582 * potentially leaves the driver in a partially updated state. Version
1583 * trauma will most likely occur if an client attempts to use any printer
1584 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1585 * done is appropriate... later JRR
1588 DEBUG(5,("Moving files now !\n"));
1590 if (driver->driver_path && strlen(driver->driver_path)) {
1592 err = move_driver_file_to_download_area(ctx,
1594 driver->driver_path,
1599 if (!W_ERROR_IS_OK(err)) {
1604 if (driver->data_file && strlen(driver->data_file)) {
1605 if (!strequal(driver->data_file, driver->driver_path)) {
1607 err = move_driver_file_to_download_area(ctx,
1614 if (!W_ERROR_IS_OK(err)) {
1620 if (driver->config_file && strlen(driver->config_file)) {
1621 if (!strequal(driver->config_file, driver->driver_path) &&
1622 !strequal(driver->config_file, driver->data_file)) {
1624 err = move_driver_file_to_download_area(ctx,
1626 driver->config_file,
1631 if (!W_ERROR_IS_OK(err)) {
1637 if (driver->help_file && strlen(driver->help_file)) {
1638 if (!strequal(driver->help_file, driver->driver_path) &&
1639 !strequal(driver->help_file, driver->data_file) &&
1640 !strequal(driver->help_file, driver->config_file)) {
1642 err = move_driver_file_to_download_area(ctx,
1649 if (!W_ERROR_IS_OK(err)) {
1655 if (driver->dependent_files && driver->dependent_files->string) {
1656 for (i=0; driver->dependent_files->string[i]; i++) {
1657 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1658 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1659 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1660 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1662 for (j=0; j < i; j++) {
1663 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1668 err = move_driver_file_to_download_area(ctx,
1670 driver->dependent_files->string[i],
1675 if (!W_ERROR_IS_OK(err)) {
1687 TALLOC_FREE(smb_dname);
1690 vfs_ChDir(conn, oldcwd_fname);
1691 TALLOC_FREE(oldcwd_fname);
1692 SMB_VFS_DISCONNECT(conn);
1699 /****************************************************************************
1700 Determine whether or not a particular driver is currently assigned
1702 ****************************************************************************/
1704 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1705 struct dcerpc_binding_handle *b,
1706 const struct spoolss_DriverInfo8 *r)
1709 int n_services = lp_numservices();
1710 bool in_use = false;
1711 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1718 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1720 /* loop through the printers.tdb and check for the drivername */
1722 for (snum=0; snum<n_services && !in_use; snum++) {
1723 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1727 result = winreg_get_printer(mem_ctx, b,
1728 lp_servicename(talloc_tos(), snum),
1730 if (!W_ERROR_IS_OK(result)) {
1731 continue; /* skip */
1734 if (strequal(r->driver_name, pinfo2->drivername)) {
1738 TALLOC_FREE(pinfo2);
1741 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1744 struct spoolss_DriverInfo8 *driver = NULL;
1747 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1749 /* we can still remove the driver if there is one of
1750 "Windows NT x86" version 2 or 3 left */
1752 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1753 if (r->version == 2) {
1754 werr = winreg_get_driver(mem_ctx, b,
1758 } else if (r->version == 3) {
1759 werr = winreg_get_driver(mem_ctx, b,
1764 DBG_ERR("Unknown driver version (%d)\n",
1766 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1768 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1769 werr = winreg_get_driver(mem_ctx, b,
1770 SPOOLSS_ARCHITECTURE_NT_X86,
1775 DBG_ERR("Unknown driver architecture: %s\n",
1777 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1780 /* now check the error code */
1782 if ( W_ERROR_IS_OK(werr) ) {
1783 /* it's ok to remove the driver, we have other architctures left */
1785 talloc_free(driver);
1789 /* report that the driver is not in use by default */
1795 /**********************************************************************
1796 Check to see if a ogiven file is in use by *info
1797 *********************************************************************/
1799 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1806 /* mz: skip files that are in the list but already deleted */
1807 if (!file || !file[0]) {
1811 if (strequal(file, info->driver_path))
1814 if (strequal(file, info->data_file))
1817 if (strequal(file, info->config_file))
1820 if (strequal(file, info->help_file))
1823 /* see of there are any dependent files to examine */
1825 if (!info->dependent_files)
1828 while (info->dependent_files[i] && *info->dependent_files[i]) {
1829 if (strequal(file, info->dependent_files[i]))
1838 /**********************************************************************
1839 Utility function to remove the dependent file pointed to by the
1840 input parameter from the list
1841 *********************************************************************/
1843 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1846 /* bump everything down a slot */
1848 while (files && files[idx+1]) {
1849 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1858 /**********************************************************************
1859 Check if any of the files used by src are also used by drv
1860 *********************************************************************/
1862 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1863 struct spoolss_DriverInfo8 *src,
1864 const struct spoolss_DriverInfo8 *drv)
1866 bool in_use = False;
1872 /* check each file. Remove it from the src structure if it overlaps */
1874 if (drv_file_in_use(src->driver_path, drv)) {
1876 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1877 src->driver_path = talloc_strdup(mem_ctx, "");
1878 if (!src->driver_path) { return false; }
1881 if (drv_file_in_use(src->data_file, drv)) {
1883 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1884 src->data_file = talloc_strdup(mem_ctx, "");
1885 if (!src->data_file) { return false; }
1888 if (drv_file_in_use(src->config_file, drv)) {
1890 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1891 src->config_file = talloc_strdup(mem_ctx, "");
1892 if (!src->config_file) { return false; }
1895 if (drv_file_in_use(src->help_file, drv)) {
1897 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1898 src->help_file = talloc_strdup(mem_ctx, "");
1899 if (!src->help_file) { return false; }
1902 /* are there any dependentfiles to examine? */
1904 if (!src->dependent_files)
1907 while (src->dependent_files[i] && *src->dependent_files[i]) {
1908 if (drv_file_in_use(src->dependent_files[i], drv)) {
1910 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1911 trim_dependent_file(mem_ctx, src->dependent_files, i);
1919 /****************************************************************************
1920 Determine whether or not a particular driver files are currently being
1921 used by any other driver.
1923 Return value is True if any files were in use by other drivers
1924 and False otherwise.
1926 Upon return, *info has been modified to only contain the driver files
1927 which are not in use
1931 This needs to check all drivers to ensure that all files in use
1932 have been removed from *info, not just the ones in the first
1934 ****************************************************************************/
1936 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1937 struct dcerpc_binding_handle *b,
1938 struct spoolss_DriverInfo8 *info)
1942 struct spoolss_DriverInfo8 *driver;
1943 bool in_use = false;
1944 uint32_t num_drivers;
1945 const char **drivers;
1951 version = info->version;
1953 /* loop over all driver versions */
1955 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1957 /* get the list of drivers */
1959 result = winreg_get_driver_list(mem_ctx, b,
1960 info->architecture, version,
1961 &num_drivers, &drivers);
1962 if (!W_ERROR_IS_OK(result)) {
1966 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1967 num_drivers, info->architecture, version));
1969 /* check each driver for overlap in files */
1971 for (i = 0; i < num_drivers; i++) {
1972 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1976 result = winreg_get_driver(mem_ctx, b,
1977 info->architecture, drivers[i],
1979 if (!W_ERROR_IS_OK(result)) {
1980 talloc_free(drivers);
1984 /* check if d2 uses any files from d1 */
1985 /* only if this is a different driver than the one being deleted */
1987 if (!strequal(info->driver_name, driver->driver_name)) {
1988 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1989 /* mz: Do not instantly return -
1990 * we need to ensure this file isn't
1991 * also in use by other drivers. */
1996 talloc_free(driver);
1999 talloc_free(drivers);
2001 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2006 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2007 const char *short_arch,
2011 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2012 struct smb_filename *smb_fname = NULL;
2013 char *print_dlr_path;
2014 NTSTATUS status = NT_STATUS_NO_MEMORY;
2016 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2017 short_arch, vers, fname);
2018 if (print_dlr_path == NULL) {
2022 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2023 if (smb_fname == NULL) {
2027 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2029 talloc_free(tmp_ctx);
2033 /****************************************************************************
2034 Actually delete the driver files. Make sure that
2035 printer_driver_files_in_use() return False before calling
2037 ****************************************************************************/
2039 bool delete_driver_files(const struct auth_session_info *session_info,
2040 const struct spoolss_DriverInfo8 *r)
2042 const char *short_arch;
2043 connection_struct *conn;
2045 struct smb_filename *oldcwd_fname = NULL;
2046 char *printdollar = NULL;
2047 int printdollar_snum;
2054 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2055 r->driver_name, r->version));
2057 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2061 if (printdollar_snum == -1) {
2065 nt_status = create_conn_struct_cwd(talloc_tos(),
2066 server_event_context(),
2067 server_messaging_context(),
2070 lp_path(talloc_tos(), printdollar_snum),
2071 session_info, &oldcwd_fname);
2072 if (!NT_STATUS_IS_OK(nt_status)) {
2073 DEBUG(0,("delete_driver_files: create_conn_struct "
2074 "returned %s\n", nt_errstr(nt_status)));
2078 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2079 if (!NT_STATUS_IS_OK(nt_status)) {
2080 DEBUG(0, ("failed set force user / group\n"));
2085 if (!become_user_by_session(conn, session_info)) {
2086 DEBUG(0, ("failed to become user\n"));
2091 if ( !CAN_WRITE(conn) ) {
2092 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2097 short_arch = get_short_archi(r->architecture);
2098 if (short_arch == NULL) {
2099 DEBUG(0, ("bad architecture %s\n", r->architecture));
2104 /* now delete the files */
2106 if (r->driver_path && r->driver_path[0]) {
2107 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2108 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2111 if (r->config_file && r->config_file[0]) {
2112 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2113 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2116 if (r->data_file && r->data_file[0]) {
2117 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2118 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2121 if (r->help_file && r->help_file[0]) {
2122 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2123 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2126 if (r->dependent_files) {
2128 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2129 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2130 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2140 vfs_ChDir(conn, oldcwd_fname);
2141 TALLOC_FREE(oldcwd_fname);
2142 SMB_VFS_DISCONNECT(conn);
2150 1: level not implemented
2151 2: file doesn't exist
2152 3: can't allocate memory
2153 4: can't free memory
2154 5: non existent struct
2158 A printer and a printer driver are 2 different things.
2159 NT manages them separatelly, Samba does the same.
2160 Why ? Simply because it's easier and it makes sense !
2162 Now explanation: You have 3 printers behind your samba server,
2163 2 of them are the same make and model (laser A and B). But laser B
2164 has an 3000 sheet feeder and laser A doesn't such an option.
2165 Your third printer is an old dot-matrix model for the accounting :-).
2167 If the /usr/local/samba/lib directory (default dir), you will have
2168 5 files to describe all of this.
2170 3 files for the printers (1 by printer):
2173 NTprinter_accounting
2174 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2175 NTdriver_printer model X
2176 NTdriver_printer model Y
2178 jfm: I should use this comment for the text file to explain
2179 same thing for the forms BTW.
2180 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2184 /* Convert generic access rights to printer object specific access rights.
2185 It turns out that NT4 security descriptors use generic access rights and
2186 NT5 the object specific ones. */
2188 void map_printer_permissions(struct security_descriptor *sd)
2192 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2193 se_map_generic(&sd->dacl->aces[i].access_mask,
2194 &printer_generic_mapping);
2198 void map_job_permissions(struct security_descriptor *sd)
2202 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2203 se_map_generic(&sd->dacl->aces[i].access_mask,
2204 &job_generic_mapping);
2209 /****************************************************************************
2210 Check a user has permissions to perform the given operation. We use the
2211 permission constants defined in include/rpc_spoolss.h to check the various
2212 actions we perform when checking printer access.
2214 PRINTER_ACCESS_ADMINISTER:
2215 print_queue_pause, print_queue_resume, update_printer_sec,
2216 update_printer, spoolss_addprinterex_level_2,
2217 _spoolss_setprinterdata
2222 JOB_ACCESS_ADMINISTER:
2223 print_job_delete, print_job_pause, print_job_resume,
2226 Try access control in the following order (for performance reasons):
2227 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2228 2) check security descriptor (bit comparisons in memory)
2229 3) "printer admins" (may result in numerous calls to winbind)
2231 ****************************************************************************/
2232 WERROR print_access_check(const struct auth_session_info *session_info,
2233 struct messaging_context *msg_ctx, int snum,
2236 struct spoolss_security_descriptor *secdesc = NULL;
2237 uint32_t access_granted;
2242 TALLOC_CTX *mem_ctx = NULL;
2244 /* If user is NULL then use the current_user structure */
2246 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2248 if ((session_info->unix_token->uid == sec_initial_uid())
2249 || security_token_has_privilege(session_info->security_token,
2250 SEC_PRIV_PRINT_OPERATOR)) {
2254 /* Get printer name */
2256 pname = lp_printername(talloc_tos(), snum);
2258 if (!pname || !*pname) {
2259 return WERR_ACCESS_DENIED;
2262 /* Get printer security descriptor */
2264 if(!(mem_ctx = talloc_init("print_access_check"))) {
2265 return WERR_NOT_ENOUGH_MEMORY;
2268 result = winreg_get_printer_secdesc_internal(mem_ctx,
2269 get_session_info_system(),
2273 if (!W_ERROR_IS_OK(result)) {
2274 talloc_destroy(mem_ctx);
2275 return WERR_NOT_ENOUGH_MEMORY;
2278 if (access_type == JOB_ACCESS_ADMINISTER) {
2279 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2281 /* Create a child security descriptor to check permissions
2282 against. This is because print jobs are child objects
2283 objects of a printer. */
2284 status = se_create_child_secdesc(mem_ctx,
2288 parent_secdesc->owner_sid,
2289 parent_secdesc->group_sid,
2291 if (!NT_STATUS_IS_OK(status)) {
2292 talloc_destroy(mem_ctx);
2293 return ntstatus_to_werror(status);
2296 map_job_permissions(secdesc);
2298 map_printer_permissions(secdesc);
2302 status = se_access_check(secdesc, session_info->security_token, access_type,
2305 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2307 talloc_destroy(mem_ctx);
2309 return ntstatus_to_werror(status);
2312 /****************************************************************************
2313 Check the time parameters allow a print operation.
2314 *****************************************************************************/
2316 bool print_time_access_check(const struct auth_session_info *session_info,
2317 struct messaging_context *msg_ctx,
2318 const char *servicename)
2320 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2323 time_t now = time(NULL);
2327 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2328 servicename, &pinfo2);
2329 if (!W_ERROR_IS_OK(result)) {
2333 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2338 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2340 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2344 TALLOC_FREE(pinfo2);
2353 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2354 const struct auth_session_info *session_info,
2355 struct messaging_context *msg_ctx,
2356 const char *printer)
2360 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2362 if (!W_ERROR_IS_OK(result)) {
2363 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2364 "%s\n", printer, win_errstr(result)));
2368 void nt_printer_add(TALLOC_CTX *mem_ctx,
2369 const struct auth_session_info *session_info,
2370 struct messaging_context *msg_ctx,
2371 const char *printer)
2375 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2377 if (!W_ERROR_IS_OK(result)) {
2378 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2379 printer, win_errstr(result)));