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 ****************************************************************************/
318 static ssize_t printing_pread_data(files_struct *fsp,
324 off_t in_pos = *poff;
326 /* Don't allow integer wrap on read. */
327 if (in_pos + byte_count < in_pos) {
331 while (total < byte_count) {
332 ssize_t ret = read_file(fsp,
342 if (errno == EINTR) {
352 return (ssize_t)total;
355 /****************************************************************************
356 Detect the major and minor version of a PE file.
359 1 if file is a PE file and we got version numbers,
360 0 if this file is a PE file and we couldn't get the version numbers,
363 NB. buf is passed into and freed inside this function. This is a
364 bad API design, but fixing this is a task for another day.
365 ****************************************************************************/
367 static int handle_pe_file(files_struct *fsp,
375 unsigned int num_sections;
376 unsigned int section_table_bytes;
381 /* Just skip over optional header to get to section table */
382 rel_pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
383 (NE_HEADER_SIZE-PE_HEADER_SIZE);
385 if (in_pos + rel_pos < in_pos) {
389 in_pos = rel_pos + in_pos;
391 /* get the section table */
392 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
394 if (num_sections >= (UINT_MAX / PE_HEADER_SECT_HEADER_SIZE)) {
399 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
400 if (section_table_bytes == 0) {
405 buf = (char *)SMB_MALLOC(section_table_bytes);
407 DBG_ERR("PE file [%s] section table malloc "
408 "failed bytes = %d\n",
410 section_table_bytes);
414 byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
415 if (byte_count < section_table_bytes) {
416 DBG_NOTICE("PE file [%s] Section header too short, "
417 "bytes read = %lu\n",
419 (unsigned long)byte_count);
424 * Iterate the section table looking for
425 * the resource section ".rsrc"
427 for (i = 0; i < num_sections; i++) {
428 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
431 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
432 unsigned int section_pos = IVAL(buf,
434 PE_HEADER_SECT_PTR_DATA_OFFSET);
435 unsigned int section_bytes = IVAL(buf,
437 PE_HEADER_SECT_SIZE_DATA_OFFSET);
439 if (section_bytes == 0) {
444 buf=(char *)SMB_MALLOC(section_bytes);
446 DBG_ERR("PE file [%s] version malloc "
447 "failed bytes = %d\n",
454 * Read from the start of the .rsrc
457 in_pos = section_pos;
459 byte_count = printing_pread_data(fsp,
463 if (byte_count < section_bytes) {
464 DBG_NOTICE("PE file "
465 "[%s] .rsrc section too short, "
466 "bytes read = %lu\n",
468 (unsigned long)byte_count);
472 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
477 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
480 * Scan for 1st 3 unicoded bytes
481 * followed by word aligned magic
485 bool magic_match = false;
493 if (magic_match == false) {
497 /* Align to next long address */
498 mpos = (i + sizeof(VS_SIGNATURE)*2 +
501 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
503 mpos+ VS_MAJOR_OFFSET);
505 mpos+ VS_MINOR_OFFSET);
507 DBG_INFO("PE file [%s] Version = "
508 "%08x:%08x (%d.%d.%d.%d)\n",
523 /* Version info not found, fall back to origin date/time */
524 DBG_DEBUG("PE file [%s] has no version info\n", fname);
533 /****************************************************************************
534 Detect the major and minor version of an NE file.
537 1 if file is an NE file and we got version numbers,
538 0 if this file is an NE file and we couldn't get the version numbers,
541 NB. buf is passed into and freed inside this function. This is a
542 bad API design, but fixing this is a task for another day.
543 ****************************************************************************/
545 static int handle_ne_file(files_struct *fsp,
556 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
557 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
559 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
561 * At this point, we assume the file is in error.
562 * It still could be something else besides a NE file,
563 * but it unlikely at this point.
568 /* Allocate a bit more space to speed up things */
570 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
572 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
579 * This is a HACK! I got tired of trying to sort through the
580 * messy 'NE' file format. If anyone wants to clean this up
581 * please have at it, but this works. 'NE' files will
582 * eventually fade away. JRR
584 byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
585 while (byte_count > 0) {
587 * Cover case that should not occur in a well
588 * formed 'NE' .dll file
590 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
594 for(i=0; i<byte_count; i++) {
596 * Fast skip past data that can't
600 byte_count = printing_pread_data(fsp,
608 * Potential match data crosses buf boundry,
609 * move it to beginning of buf, and fill the
610 * buf with as much as it will hold.
612 if (i>byte_count-VS_VERSION_INFO_SIZE) {
614 ssize_t amount_unused = byte_count-i;
616 memmove(buf, &buf[i], amount_unused);
617 amount_read = printing_pread_data(fsp,
620 VS_NE_BUF_SIZE- amount_unused);
621 if (amount_read < 0) {
622 DBG_ERR("NE file [%s] Read "
629 if (amount_read + amount_unused <
631 /* Check for integer wrap. */
635 byte_count = amount_read +
637 if (byte_count < VS_VERSION_INFO_SIZE) {
645 * Check that the full signature string and
646 * the magic number that follows exist (not
647 * a perfect solution, but the chances that this
648 * occurs in code is, well, remote. Yes I know
649 * I'm comparing the 'V' twice, as it is
650 * simpler to read the code.
652 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
654 * Compute skip alignment to next
658 int skip = -(cpos - (byte_count - i) +
659 sizeof(VS_SIGNATURE)) & 3;
661 i+sizeof(VS_SIGNATURE)+skip)
663 byte_count = printing_pread_data(fsp,
671 i+sizeof(VS_SIGNATURE)+
672 skip+VS_MAJOR_OFFSET);
674 i+sizeof(VS_SIGNATURE)+
675 skip+VS_MINOR_OFFSET);
676 DBG_INFO("NE file [%s] Version "
677 "= %08x:%08x (%d.%d.%d.%d)\n",
691 /* Version info not found, fall back to origin date/time */
692 DBG_ERR("NE file [%s] Version info not found\n", fname);
701 /****************************************************************************
702 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
703 There are two case to be covered here: PE (Portable Executable) and NE (New
704 Executable) files. Both files support the same INFO structure, but PE files
705 store the signature in unicode, and NE files store it as !unicode.
706 returns -1 on error, 1 on version info found, and 0 on no version info found.
707 ****************************************************************************/
709 static int get_file_version(files_struct *fsp,
716 off_t in_pos = fsp->fh->pos;
718 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
720 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
726 byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
727 if (byte_count < DOS_HEADER_SIZE) {
728 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
730 (unsigned long)byte_count);
731 goto no_version_info;
734 /* Is this really a DOS header? */
735 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
736 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
738 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
739 goto no_version_info;
743 * Skip OEM header (if any) and the
744 * DOS stub to start of Windows header.
746 in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
748 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
749 byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
750 if (byte_count < NE_HEADER_SIZE) {
751 DBG_NOTICE("File [%s] Windows header too short, "
752 "bytes read = %lu\n",
754 (unsigned long)byte_count);
756 * Assume this isn't an error...
757 * the file just looks sort of like a PE/NE file
759 goto no_version_info;
763 * The header may be a PE (Portable Executable)
764 * or an NE (New Executable).
766 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
767 return handle_pe_file(fsp,
773 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
774 NE_HEADER_SIGNATURE) {
775 return handle_ne_file(fsp,
783 * Assume this isn't an error... the file just
784 * looks sort of like a PE/NE file.
786 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
788 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
789 /* Fallthrough into no_version_info: */
801 /****************************************************************************
802 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
803 share one or more files. During the MS installation process files are checked
804 to insure that only a newer version of a shared file is installed over an
805 older version. There are several possibilities for this comparison. If there
806 is no previous version, the new one is newer (obviously). If either file is
807 missing the version info structure, compare the creation date (on Unix use
808 the modification date). Otherwise chose the numerically larger version number.
809 ****************************************************************************/
811 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
813 bool use_version = true;
817 time_t new_create_time;
821 time_t old_create_time;
823 struct smb_filename *smb_fname = NULL;
824 files_struct *fsp = NULL;
830 SET_STAT_INVALID(st);
831 new_create_time = (time_t)0;
832 old_create_time = (time_t)0;
834 /* Get file version info (if available) for previous file (if it exists) */
835 status = driver_unix_convert(conn, old_file, &smb_fname);
836 if (!NT_STATUS_IS_OK(status)) {
840 status = SMB_VFS_CREATE_FILE(
843 0, /* root_dir_fid */
844 smb_fname, /* fname */
845 FILE_GENERIC_READ, /* access_mask */
846 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
847 FILE_OPEN, /* create_disposition*/
848 0, /* create_options */
849 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
850 INTERNAL_OPEN_ONLY, /* oplock_request */
852 0, /* allocation_size */
853 0, /* private_flags */
858 NULL, NULL); /* create context */
860 if (!NT_STATUS_IS_OK(status)) {
861 /* Old file not found, so by definition new file is in fact newer */
862 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
863 "errno = %d\n", smb_fname_str_dbg(smb_fname),
869 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
875 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
878 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
881 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
882 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
883 (long)old_create_time));
886 close_file(NULL, fsp, NORMAL_CLOSE);
889 /* Get file version info (if available) for new file */
890 status = driver_unix_convert(conn, new_file, &smb_fname);
891 if (!NT_STATUS_IS_OK(status)) {
895 status = SMB_VFS_CREATE_FILE(
898 0, /* root_dir_fid */
899 smb_fname, /* fname */
900 FILE_GENERIC_READ, /* access_mask */
901 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
902 FILE_OPEN, /* create_disposition*/
903 0, /* create_options */
904 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
905 INTERNAL_OPEN_ONLY, /* oplock_request */
907 0, /* allocation_size */
908 0, /* private_flags */
913 NULL, NULL); /* create context */
915 if (!NT_STATUS_IS_OK(status)) {
916 /* New file not found, this shouldn't occur if the caller did its job */
917 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
918 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
922 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
928 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
931 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
934 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
935 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
936 (long)new_create_time));
939 close_file(NULL, fsp, NORMAL_CLOSE);
942 if (use_version && (new_major != old_major || new_minor != old_minor)) {
943 /* Compare versions and choose the larger version number */
944 if (new_major > old_major ||
945 (new_major == old_major && new_minor > old_minor)) {
947 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
952 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
958 /* Compare modification time/dates and choose the newest time/date */
959 if (new_create_time > old_create_time) {
960 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
965 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
973 close_file(NULL, fsp, NORMAL_CLOSE);
976 TALLOC_FREE(smb_fname);
980 /****************************************************************************
981 Determine the correct cVersion associated with an architecture and driver
982 ****************************************************************************/
983 static uint32_t get_correct_cversion(const struct auth_session_info *session_info,
984 const char *architecture,
985 const char *driverpath_in,
986 const char *driver_directory,
989 TALLOC_CTX *frame = talloc_stackframe();
992 struct smb_filename *smb_fname = NULL;
993 files_struct *fsp = NULL;
994 connection_struct *conn = NULL;
995 struct smb_filename *oldcwd_fname = NULL;
996 char *printdollar = NULL;
997 char *printdollar_path = NULL;
998 char *working_dir = NULL;
999 int printdollar_snum;
1001 *perr = WERR_INVALID_PARAMETER;
1003 /* If architecture is Windows 95/98/ME, the version is always 0. */
1004 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1005 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1011 /* If architecture is Windows x64, the version is always 3. */
1012 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1013 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1019 printdollar_snum = find_service(frame, "print$", &printdollar);
1021 *perr = WERR_NOT_ENOUGH_MEMORY;
1025 if (printdollar_snum == -1) {
1026 *perr = WERR_BAD_NET_NAME;
1031 printdollar_path = lp_path(frame, printdollar_snum);
1032 if (printdollar_path == NULL) {
1033 *perr = WERR_NOT_ENOUGH_MEMORY;
1038 working_dir = talloc_asprintf(frame,
1043 * If the driver has been uploaded into a temorpary driver
1044 * directory, switch to the driver directory.
1046 if (driver_directory != NULL) {
1047 working_dir = talloc_asprintf(frame, "%s/%s/%s",
1053 nt_status = create_conn_struct_cwd(frame,
1054 server_event_context(),
1055 server_messaging_context(),
1059 session_info, &oldcwd_fname);
1060 if (!NT_STATUS_IS_OK(nt_status)) {
1061 DEBUG(0,("get_correct_cversion: create_conn_struct "
1062 "returned %s\n", nt_errstr(nt_status)));
1063 *perr = ntstatus_to_werror(nt_status);
1068 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1069 if (!NT_STATUS_IS_OK(nt_status)) {
1070 DEBUG(0, ("failed set force user / group\n"));
1071 *perr = ntstatus_to_werror(nt_status);
1072 goto error_free_conn;
1075 if (!become_user_by_session(conn, session_info)) {
1076 DEBUG(0, ("failed to become user\n"));
1077 *perr = WERR_ACCESS_DENIED;
1078 goto error_free_conn;
1082 * We switch to the directory where the driver files are located,
1083 * so only work on the file names
1085 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1086 if (!NT_STATUS_IS_OK(nt_status)) {
1087 *perr = ntstatus_to_werror(nt_status);
1091 nt_status = vfs_file_exist(conn, smb_fname);
1092 if (!NT_STATUS_IS_OK(nt_status)) {
1093 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1094 *perr = WERR_FILE_NOT_FOUND;
1098 nt_status = SMB_VFS_CREATE_FILE(
1101 0, /* root_dir_fid */
1102 smb_fname, /* fname */
1103 FILE_GENERIC_READ, /* access_mask */
1104 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1105 FILE_OPEN, /* create_disposition*/
1106 0, /* create_options */
1107 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1108 INTERNAL_OPEN_ONLY, /* oplock_request */
1110 0, /* private_flags */
1111 0, /* allocation_size */
1116 NULL, NULL); /* create context */
1118 if (!NT_STATUS_IS_OK(nt_status)) {
1119 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1120 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1121 *perr = WERR_ACCESS_DENIED;
1128 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1130 *perr = WERR_INVALID_PARAMETER;
1133 DEBUG(6,("get_correct_cversion: Version info not "
1135 smb_fname_str_dbg(smb_fname)));
1136 *perr = WERR_INVALID_PARAMETER;
1141 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1142 * for more details. Version in this case is not just the version of the
1143 * file, but the version in the sense of kernal mode (2) vs. user mode
1144 * (3) drivers. Other bits of the version fields are the version info.
1147 cversion = major & 0x0000ffff;
1149 case 2: /* WinNT drivers */
1150 case 3: /* Win2K drivers */
1154 DEBUG(6,("get_correct_cversion: cversion "
1155 "invalid [%s] cversion = %d\n",
1156 smb_fname_str_dbg(smb_fname),
1161 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1162 " = 0x%x minor = 0x%x\n",
1163 smb_fname_str_dbg(smb_fname), major, minor));
1166 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1167 smb_fname_str_dbg(smb_fname), cversion));
1174 close_file(NULL, fsp, NORMAL_CLOSE);
1177 vfs_ChDir(conn, oldcwd_fname);
1178 SMB_VFS_DISCONNECT(conn);
1181 if (!W_ERROR_IS_OK(*perr)) {
1189 /****************************************************************************
1190 ****************************************************************************/
1192 #define strip_driver_path(_mem_ctx, _element) do { \
1193 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1194 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1195 W_ERROR_HAVE_NO_MEMORY((_element)); \
1199 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1200 const struct auth_session_info *session_info,
1201 const char *architecture,
1202 const char **driver_path,
1203 const char **data_file,
1204 const char **config_file,
1205 const char **help_file,
1206 struct spoolss_StringArray *dependent_files,
1207 enum spoolss_DriverOSVersion *version,
1209 const char **driver_directory)
1211 const char *short_architecture;
1216 if (!*driver_path || !*data_file) {
1217 return WERR_INVALID_PARAMETER;
1220 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1221 return WERR_INVALID_PARAMETER;
1224 if (flags & APD_COPY_FROM_DIRECTORY) {
1229 * driver_path is set to:
1231 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1233 path = talloc_strdup(mem_ctx, *driver_path);
1235 return WERR_NOT_ENOUGH_MEMORY;
1238 /* Remove pscript5.dll */
1239 q = strrchr_m(path, '\\');
1241 return WERR_INVALID_PARAMETER;
1245 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1246 q = strrchr_m(path, '\\');
1248 return WERR_INVALID_PARAMETER;
1252 * Set driver_directory to:
1254 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1256 * This is the directory where all the files have been uploaded
1258 *driver_directory = q + 1;
1261 /* clean up the driver name.
1262 * we can get .\driver.dll
1263 * or worse c:\windows\system\driver.dll !
1265 /* using an intermediate string to not have overlaping memcpy()'s */
1267 strip_driver_path(mem_ctx, *driver_path);
1268 strip_driver_path(mem_ctx, *data_file);
1270 strip_driver_path(mem_ctx, *config_file);
1273 strip_driver_path(mem_ctx, *help_file);
1276 if (dependent_files && dependent_files->string) {
1277 for (i=0; dependent_files->string[i]; i++) {
1278 strip_driver_path(mem_ctx, dependent_files->string[i]);
1282 short_architecture = get_short_archi(architecture);
1283 if (!short_architecture) {
1284 return WERR_UNKNOWN_PRINTER_DRIVER;
1287 /* jfm:7/16/2000 the client always sends the cversion=0.
1288 * The server should check which version the driver is by reading
1289 * the PE header of driver->driverpath.
1291 * For Windows 95/98 the version is 0 (so the value sent is correct)
1292 * For Windows NT (the architecture doesn't matter)
1293 * NT 3.1: cversion=0
1294 * NT 3.5/3.51: cversion=1
1299 *version = get_correct_cversion(session_info,
1304 if (*version == -1) {
1311 /****************************************************************************
1312 ****************************************************************************/
1314 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1315 const struct auth_session_info *session_info,
1316 const struct spoolss_AddDriverInfoCtr *r,
1318 const char **driver_directory)
1322 return clean_up_driver_struct_level(mem_ctx, session_info,
1323 r->info.info3->architecture,
1324 &r->info.info3->driver_path,
1325 &r->info.info3->data_file,
1326 &r->info.info3->config_file,
1327 &r->info.info3->help_file,
1328 r->info.info3->dependent_files,
1329 &r->info.info3->version,
1333 return clean_up_driver_struct_level(mem_ctx, session_info,
1334 r->info.info6->architecture,
1335 &r->info.info6->driver_path,
1336 &r->info.info6->data_file,
1337 &r->info.info6->config_file,
1338 &r->info.info6->help_file,
1339 r->info.info6->dependent_files,
1340 &r->info.info6->version,
1344 return clean_up_driver_struct_level(mem_ctx, session_info,
1345 r->info.info8->architecture,
1346 &r->info.info8->driver_path,
1347 &r->info.info8->data_file,
1348 &r->info.info8->config_file,
1349 &r->info.info8->help_file,
1350 r->info.info8->dependent_files,
1351 &r->info.info8->version,
1355 return WERR_NOT_SUPPORTED;
1359 /****************************************************************************
1360 This function sucks and should be replaced. JRA.
1361 ****************************************************************************/
1363 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1364 const struct spoolss_AddDriverInfo6 *src)
1366 dst->version = src->version;
1368 dst->driver_name = src->driver_name;
1369 dst->architecture = src->architecture;
1370 dst->driver_path = src->driver_path;
1371 dst->data_file = src->data_file;
1372 dst->config_file = src->config_file;
1373 dst->help_file = src->help_file;
1374 dst->monitor_name = src->monitor_name;
1375 dst->default_datatype = src->default_datatype;
1376 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1377 dst->dependent_files = src->dependent_files;
1380 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1381 const struct spoolss_AddDriverInfo8 *src)
1383 dst->version = src->version;
1385 dst->driver_name = src->driver_name;
1386 dst->architecture = src->architecture;
1387 dst->driver_path = src->driver_path;
1388 dst->data_file = src->data_file;
1389 dst->config_file = src->config_file;
1390 dst->help_file = src->help_file;
1391 dst->monitor_name = src->monitor_name;
1392 dst->default_datatype = src->default_datatype;
1393 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1394 dst->dependent_files = src->dependent_files;
1397 /****************************************************************************
1398 ****************************************************************************/
1400 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1401 connection_struct *conn,
1402 const char *driver_file,
1403 const char *short_architecture,
1404 uint32_t driver_version,
1406 const char *driver_directory)
1408 struct smb_filename *smb_fname_old = NULL;
1409 struct smb_filename *smb_fname_new = NULL;
1410 char *old_name = NULL;
1411 char *new_name = NULL;
1415 if (driver_directory != NULL) {
1416 old_name = talloc_asprintf(mem_ctx,
1422 old_name = talloc_asprintf(mem_ctx,
1427 if (old_name == NULL) {
1428 return WERR_NOT_ENOUGH_MEMORY;
1431 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1432 short_architecture, driver_version, driver_file);
1433 if (new_name == NULL) {
1434 TALLOC_FREE(old_name);
1435 return WERR_NOT_ENOUGH_MEMORY;
1438 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1440 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1441 if (!NT_STATUS_IS_OK(status)) {
1442 ret = WERR_NOT_ENOUGH_MEMORY;
1446 /* Setup a synthetic smb_filename struct */
1447 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1448 if (!smb_fname_new) {
1449 ret = WERR_NOT_ENOUGH_MEMORY;
1453 smb_fname_new->base_name = new_name;
1455 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1456 "'%s'\n", smb_fname_old->base_name,
1457 smb_fname_new->base_name));
1459 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1460 OPENX_FILE_EXISTS_TRUNCATE |
1461 OPENX_FILE_CREATE_IF_NOT_EXIST,
1464 if (!NT_STATUS_IS_OK(status)) {
1465 DEBUG(0,("move_driver_file_to_download_area: Unable "
1466 "to rename [%s] to [%s]: %s\n",
1467 smb_fname_old->base_name, new_name,
1468 nt_errstr(status)));
1469 ret = WERR_APP_INIT_FAILURE;
1476 TALLOC_FREE(smb_fname_old);
1477 TALLOC_FREE(smb_fname_new);
1481 WERROR move_driver_to_download_area(const struct auth_session_info *session_info,
1482 const struct spoolss_AddDriverInfoCtr *r,
1483 const char *driver_directory)
1485 struct spoolss_AddDriverInfo3 *driver;
1486 struct spoolss_AddDriverInfo3 converted_driver;
1487 const char *short_architecture;
1488 struct smb_filename *smb_dname = NULL;
1489 char *new_dir = NULL;
1490 connection_struct *conn = NULL;
1493 TALLOC_CTX *ctx = talloc_tos();
1495 struct smb_filename *oldcwd_fname = NULL;
1496 char *printdollar = NULL;
1497 int printdollar_snum;
1498 WERROR err = WERR_OK;
1502 driver = r->info.info3;
1505 convert_level_6_to_level3(&converted_driver, r->info.info6);
1506 driver = &converted_driver;
1509 convert_level_8_to_level3(&converted_driver, r->info.info8);
1510 driver = &converted_driver;
1513 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1514 return WERR_INVALID_LEVEL;
1517 short_architecture = get_short_archi(driver->architecture);
1518 if (!short_architecture) {
1519 return WERR_UNKNOWN_PRINTER_DRIVER;
1522 printdollar_snum = find_service(ctx, "print$", &printdollar);
1524 return WERR_NOT_ENOUGH_MEMORY;
1526 if (printdollar_snum == -1) {
1527 return WERR_BAD_NET_NAME;
1530 nt_status = create_conn_struct_cwd(talloc_tos(),
1531 server_event_context(),
1532 server_messaging_context(),
1535 lp_path(talloc_tos(), printdollar_snum),
1536 session_info, &oldcwd_fname);
1537 if (!NT_STATUS_IS_OK(nt_status)) {
1538 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1539 "returned %s\n", nt_errstr(nt_status)));
1540 err = ntstatus_to_werror(nt_status);
1544 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1545 if (!NT_STATUS_IS_OK(nt_status)) {
1546 DEBUG(0, ("failed set force user / group\n"));
1547 err = ntstatus_to_werror(nt_status);
1551 if (!become_user_by_session(conn, session_info)) {
1552 DEBUG(0, ("failed to become user\n"));
1553 err = WERR_ACCESS_DENIED;
1557 new_dir = talloc_asprintf(ctx,
1562 err = WERR_NOT_ENOUGH_MEMORY;
1565 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1566 if (!NT_STATUS_IS_OK(nt_status)) {
1567 err = WERR_NOT_ENOUGH_MEMORY;
1571 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1573 nt_status = create_directory(conn, NULL, smb_dname);
1574 if (!NT_STATUS_IS_OK(nt_status)
1575 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1576 DEBUG(0, ("failed to create driver destination directory: %s\n",
1577 nt_errstr(nt_status)));
1578 err = ntstatus_to_werror(nt_status);
1582 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1583 * listed for this driver which has already been moved, skip it (note:
1584 * drivers may list the same file name several times. Then check if the
1585 * file already exists in archi\version\, if so, check that the version
1586 * info (or time stamps if version info is unavailable) is newer (or the
1587 * date is later). If it is, move it to archi\version\filexxx.yyy.
1588 * Otherwise, delete the file.
1590 * If a file is not moved to archi\version\ because of an error, all the
1591 * rest of the 'unmoved' driver files are removed from archi\. If one or
1592 * more of the driver's files was already moved to archi\version\, it
1593 * potentially leaves the driver in a partially updated state. Version
1594 * trauma will most likely occur if an client attempts to use any printer
1595 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1596 * done is appropriate... later JRR
1599 DEBUG(5,("Moving files now !\n"));
1601 if (driver->driver_path && strlen(driver->driver_path)) {
1603 err = move_driver_file_to_download_area(ctx,
1605 driver->driver_path,
1610 if (!W_ERROR_IS_OK(err)) {
1615 if (driver->data_file && strlen(driver->data_file)) {
1616 if (!strequal(driver->data_file, driver->driver_path)) {
1618 err = move_driver_file_to_download_area(ctx,
1625 if (!W_ERROR_IS_OK(err)) {
1631 if (driver->config_file && strlen(driver->config_file)) {
1632 if (!strequal(driver->config_file, driver->driver_path) &&
1633 !strequal(driver->config_file, driver->data_file)) {
1635 err = move_driver_file_to_download_area(ctx,
1637 driver->config_file,
1642 if (!W_ERROR_IS_OK(err)) {
1648 if (driver->help_file && strlen(driver->help_file)) {
1649 if (!strequal(driver->help_file, driver->driver_path) &&
1650 !strequal(driver->help_file, driver->data_file) &&
1651 !strequal(driver->help_file, driver->config_file)) {
1653 err = move_driver_file_to_download_area(ctx,
1660 if (!W_ERROR_IS_OK(err)) {
1666 if (driver->dependent_files && driver->dependent_files->string) {
1667 for (i=0; driver->dependent_files->string[i]; i++) {
1668 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1669 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1670 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1671 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1673 for (j=0; j < i; j++) {
1674 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1679 err = move_driver_file_to_download_area(ctx,
1681 driver->dependent_files->string[i],
1686 if (!W_ERROR_IS_OK(err)) {
1698 TALLOC_FREE(smb_dname);
1701 vfs_ChDir(conn, oldcwd_fname);
1702 TALLOC_FREE(oldcwd_fname);
1703 SMB_VFS_DISCONNECT(conn);
1710 /****************************************************************************
1711 Determine whether or not a particular driver is currently assigned
1713 ****************************************************************************/
1715 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1716 struct dcerpc_binding_handle *b,
1717 const struct spoolss_DriverInfo8 *r)
1720 int n_services = lp_numservices();
1721 bool in_use = false;
1722 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1729 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1731 /* loop through the printers.tdb and check for the drivername */
1733 for (snum=0; snum<n_services && !in_use; snum++) {
1734 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1738 result = winreg_get_printer(mem_ctx, b,
1739 lp_servicename(talloc_tos(), snum),
1741 if (!W_ERROR_IS_OK(result)) {
1742 continue; /* skip */
1745 if (strequal(r->driver_name, pinfo2->drivername)) {
1749 TALLOC_FREE(pinfo2);
1752 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1755 struct spoolss_DriverInfo8 *driver = NULL;
1758 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1760 /* we can still remove the driver if there is one of
1761 "Windows NT x86" version 2 or 3 left */
1763 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1764 if (r->version == 2) {
1765 werr = winreg_get_driver(mem_ctx, b,
1769 } else if (r->version == 3) {
1770 werr = winreg_get_driver(mem_ctx, b,
1775 DBG_ERR("Unknown driver version (%d)\n",
1777 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1779 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1780 werr = winreg_get_driver(mem_ctx, b,
1781 SPOOLSS_ARCHITECTURE_NT_X86,
1786 DBG_ERR("Unknown driver architecture: %s\n",
1788 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1791 /* now check the error code */
1793 if ( W_ERROR_IS_OK(werr) ) {
1794 /* it's ok to remove the driver, we have other architctures left */
1796 talloc_free(driver);
1800 /* report that the driver is not in use by default */
1806 /**********************************************************************
1807 Check to see if a ogiven file is in use by *info
1808 *********************************************************************/
1810 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1817 /* mz: skip files that are in the list but already deleted */
1818 if (!file || !file[0]) {
1822 if (strequal(file, info->driver_path))
1825 if (strequal(file, info->data_file))
1828 if (strequal(file, info->config_file))
1831 if (strequal(file, info->help_file))
1834 /* see of there are any dependent files to examine */
1836 if (!info->dependent_files)
1839 while (info->dependent_files[i] && *info->dependent_files[i]) {
1840 if (strequal(file, info->dependent_files[i]))
1849 /**********************************************************************
1850 Utility function to remove the dependent file pointed to by the
1851 input parameter from the list
1852 *********************************************************************/
1854 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1857 /* bump everything down a slot */
1859 while (files && files[idx+1]) {
1860 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1869 /**********************************************************************
1870 Check if any of the files used by src are also used by drv
1871 *********************************************************************/
1873 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1874 struct spoolss_DriverInfo8 *src,
1875 const struct spoolss_DriverInfo8 *drv)
1877 bool in_use = False;
1883 /* check each file. Remove it from the src structure if it overlaps */
1885 if (drv_file_in_use(src->driver_path, drv)) {
1887 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1888 src->driver_path = talloc_strdup(mem_ctx, "");
1889 if (!src->driver_path) { return false; }
1892 if (drv_file_in_use(src->data_file, drv)) {
1894 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1895 src->data_file = talloc_strdup(mem_ctx, "");
1896 if (!src->data_file) { return false; }
1899 if (drv_file_in_use(src->config_file, drv)) {
1901 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1902 src->config_file = talloc_strdup(mem_ctx, "");
1903 if (!src->config_file) { return false; }
1906 if (drv_file_in_use(src->help_file, drv)) {
1908 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1909 src->help_file = talloc_strdup(mem_ctx, "");
1910 if (!src->help_file) { return false; }
1913 /* are there any dependentfiles to examine? */
1915 if (!src->dependent_files)
1918 while (src->dependent_files[i] && *src->dependent_files[i]) {
1919 if (drv_file_in_use(src->dependent_files[i], drv)) {
1921 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1922 trim_dependent_file(mem_ctx, src->dependent_files, i);
1930 /****************************************************************************
1931 Determine whether or not a particular driver files are currently being
1932 used by any other driver.
1934 Return value is True if any files were in use by other drivers
1935 and False otherwise.
1937 Upon return, *info has been modified to only contain the driver files
1938 which are not in use
1942 This needs to check all drivers to ensure that all files in use
1943 have been removed from *info, not just the ones in the first
1945 ****************************************************************************/
1947 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1948 struct dcerpc_binding_handle *b,
1949 struct spoolss_DriverInfo8 *info)
1953 struct spoolss_DriverInfo8 *driver;
1954 bool in_use = false;
1955 uint32_t num_drivers;
1956 const char **drivers;
1962 version = info->version;
1964 /* loop over all driver versions */
1966 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1968 /* get the list of drivers */
1970 result = winreg_get_driver_list(mem_ctx, b,
1971 info->architecture, version,
1972 &num_drivers, &drivers);
1973 if (!W_ERROR_IS_OK(result)) {
1977 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1978 num_drivers, info->architecture, version));
1980 /* check each driver for overlap in files */
1982 for (i = 0; i < num_drivers; i++) {
1983 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1987 result = winreg_get_driver(mem_ctx, b,
1988 info->architecture, drivers[i],
1990 if (!W_ERROR_IS_OK(result)) {
1991 talloc_free(drivers);
1995 /* check if d2 uses any files from d1 */
1996 /* only if this is a different driver than the one being deleted */
1998 if (!strequal(info->driver_name, driver->driver_name)) {
1999 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
2000 /* mz: Do not instantly return -
2001 * we need to ensure this file isn't
2002 * also in use by other drivers. */
2007 talloc_free(driver);
2010 talloc_free(drivers);
2012 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2017 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2018 const char *short_arch,
2022 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2023 struct smb_filename *smb_fname = NULL;
2024 char *print_dlr_path;
2025 NTSTATUS status = NT_STATUS_NO_MEMORY;
2027 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2028 short_arch, vers, fname);
2029 if (print_dlr_path == NULL) {
2033 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2034 if (smb_fname == NULL) {
2038 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2040 talloc_free(tmp_ctx);
2044 /****************************************************************************
2045 Actually delete the driver files. Make sure that
2046 printer_driver_files_in_use() return False before calling
2048 ****************************************************************************/
2050 bool delete_driver_files(const struct auth_session_info *session_info,
2051 const struct spoolss_DriverInfo8 *r)
2053 const char *short_arch;
2054 connection_struct *conn;
2056 struct smb_filename *oldcwd_fname = NULL;
2057 char *printdollar = NULL;
2058 int printdollar_snum;
2065 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2066 r->driver_name, r->version));
2068 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2072 if (printdollar_snum == -1) {
2076 nt_status = create_conn_struct_cwd(talloc_tos(),
2077 server_event_context(),
2078 server_messaging_context(),
2081 lp_path(talloc_tos(), printdollar_snum),
2082 session_info, &oldcwd_fname);
2083 if (!NT_STATUS_IS_OK(nt_status)) {
2084 DEBUG(0,("delete_driver_files: create_conn_struct "
2085 "returned %s\n", nt_errstr(nt_status)));
2089 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2090 if (!NT_STATUS_IS_OK(nt_status)) {
2091 DEBUG(0, ("failed set force user / group\n"));
2096 if (!become_user_by_session(conn, session_info)) {
2097 DEBUG(0, ("failed to become user\n"));
2102 if ( !CAN_WRITE(conn) ) {
2103 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2108 short_arch = get_short_archi(r->architecture);
2109 if (short_arch == NULL) {
2110 DEBUG(0, ("bad architecture %s\n", r->architecture));
2115 /* now delete the files */
2117 if (r->driver_path && r->driver_path[0]) {
2118 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2119 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2122 if (r->config_file && r->config_file[0]) {
2123 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2124 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2127 if (r->data_file && r->data_file[0]) {
2128 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2129 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2132 if (r->help_file && r->help_file[0]) {
2133 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2134 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2137 if (r->dependent_files) {
2139 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2140 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2141 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2151 vfs_ChDir(conn, oldcwd_fname);
2152 TALLOC_FREE(oldcwd_fname);
2153 SMB_VFS_DISCONNECT(conn);
2161 1: level not implemented
2162 2: file doesn't exist
2163 3: can't allocate memory
2164 4: can't free memory
2165 5: non existent struct
2169 A printer and a printer driver are 2 different things.
2170 NT manages them separatelly, Samba does the same.
2171 Why ? Simply because it's easier and it makes sense !
2173 Now explanation: You have 3 printers behind your samba server,
2174 2 of them are the same make and model (laser A and B). But laser B
2175 has an 3000 sheet feeder and laser A doesn't such an option.
2176 Your third printer is an old dot-matrix model for the accounting :-).
2178 If the /usr/local/samba/lib directory (default dir), you will have
2179 5 files to describe all of this.
2181 3 files for the printers (1 by printer):
2184 NTprinter_accounting
2185 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2186 NTdriver_printer model X
2187 NTdriver_printer model Y
2189 jfm: I should use this comment for the text file to explain
2190 same thing for the forms BTW.
2191 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2195 /* Convert generic access rights to printer object specific access rights.
2196 It turns out that NT4 security descriptors use generic access rights and
2197 NT5 the object specific ones. */
2199 void map_printer_permissions(struct security_descriptor *sd)
2203 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2204 se_map_generic(&sd->dacl->aces[i].access_mask,
2205 &printer_generic_mapping);
2209 void map_job_permissions(struct security_descriptor *sd)
2213 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2214 se_map_generic(&sd->dacl->aces[i].access_mask,
2215 &job_generic_mapping);
2220 /****************************************************************************
2221 Check a user has permissions to perform the given operation. We use the
2222 permission constants defined in include/rpc_spoolss.h to check the various
2223 actions we perform when checking printer access.
2225 PRINTER_ACCESS_ADMINISTER:
2226 print_queue_pause, print_queue_resume, update_printer_sec,
2227 update_printer, spoolss_addprinterex_level_2,
2228 _spoolss_setprinterdata
2233 JOB_ACCESS_ADMINISTER:
2234 print_job_delete, print_job_pause, print_job_resume,
2237 Try access control in the following order (for performance reasons):
2238 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2239 2) check security descriptor (bit comparisons in memory)
2240 3) "printer admins" (may result in numerous calls to winbind)
2242 ****************************************************************************/
2243 WERROR print_access_check(const struct auth_session_info *session_info,
2244 struct messaging_context *msg_ctx, int snum,
2247 struct spoolss_security_descriptor *secdesc = NULL;
2248 uint32_t access_granted;
2253 TALLOC_CTX *mem_ctx = NULL;
2255 /* If user is NULL then use the current_user structure */
2257 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2259 if ((session_info->unix_token->uid == sec_initial_uid())
2260 || security_token_has_privilege(session_info->security_token,
2261 SEC_PRIV_PRINT_OPERATOR)) {
2265 /* Get printer name */
2267 pname = lp_printername(talloc_tos(), snum);
2269 if (!pname || !*pname) {
2270 return WERR_ACCESS_DENIED;
2273 /* Get printer security descriptor */
2275 if(!(mem_ctx = talloc_init("print_access_check"))) {
2276 return WERR_NOT_ENOUGH_MEMORY;
2279 result = winreg_get_printer_secdesc_internal(mem_ctx,
2280 get_session_info_system(),
2284 if (!W_ERROR_IS_OK(result)) {
2285 talloc_destroy(mem_ctx);
2286 return WERR_NOT_ENOUGH_MEMORY;
2289 if (access_type == JOB_ACCESS_ADMINISTER) {
2290 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2292 /* Create a child security descriptor to check permissions
2293 against. This is because print jobs are child objects
2294 objects of a printer. */
2295 status = se_create_child_secdesc(mem_ctx,
2299 parent_secdesc->owner_sid,
2300 parent_secdesc->group_sid,
2302 if (!NT_STATUS_IS_OK(status)) {
2303 talloc_destroy(mem_ctx);
2304 return ntstatus_to_werror(status);
2307 map_job_permissions(secdesc);
2309 map_printer_permissions(secdesc);
2313 status = se_access_check(secdesc, session_info->security_token, access_type,
2316 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2318 talloc_destroy(mem_ctx);
2320 return ntstatus_to_werror(status);
2323 /****************************************************************************
2324 Check the time parameters allow a print operation.
2325 *****************************************************************************/
2327 bool print_time_access_check(const struct auth_session_info *session_info,
2328 struct messaging_context *msg_ctx,
2329 const char *servicename)
2331 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2334 time_t now = time(NULL);
2338 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2339 servicename, &pinfo2);
2340 if (!W_ERROR_IS_OK(result)) {
2344 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2349 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2351 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2355 TALLOC_FREE(pinfo2);
2364 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2365 const struct auth_session_info *session_info,
2366 struct messaging_context *msg_ctx,
2367 const char *printer)
2371 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2373 if (!W_ERROR_IS_OK(result)) {
2374 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2375 "%s\n", printer, win_errstr(result)));
2379 void nt_printer_add(TALLOC_CTX *mem_ctx,
2380 const struct auth_session_info *session_info,
2381 struct messaging_context *msg_ctx,
2382 const char *printer)
2386 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2388 if (!W_ERROR_IS_OK(result)) {
2389 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2390 printer, win_errstr(result)));