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);
393 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
394 if (section_table_bytes == 0) {
399 buf = (char *)SMB_MALLOC(section_table_bytes);
401 DBG_ERR("PE file [%s] section table malloc "
402 "failed bytes = %d\n",
404 section_table_bytes);
408 byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
409 if (byte_count < section_table_bytes) {
410 DBG_NOTICE("PE file [%s] Section header too short, "
411 "bytes read = %lu\n",
413 (unsigned long)byte_count);
418 * Iterate the section table looking for
419 * the resource section ".rsrc"
421 for (i = 0; i < num_sections; i++) {
422 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
425 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
426 unsigned int section_pos = IVAL(buf,
428 PE_HEADER_SECT_PTR_DATA_OFFSET);
429 unsigned int section_bytes = IVAL(buf,
431 PE_HEADER_SECT_SIZE_DATA_OFFSET);
433 if (section_bytes == 0) {
438 buf=(char *)SMB_MALLOC(section_bytes);
440 DBG_ERR("PE file [%s] version malloc "
441 "failed bytes = %d\n",
448 * Read from the start of the .rsrc
451 in_pos = section_pos;
453 byte_count = printing_pread_data(fsp,
457 if (byte_count < section_bytes) {
458 DBG_NOTICE("PE file "
459 "[%s] .rsrc section too short, "
460 "bytes read = %lu\n",
462 (unsigned long)byte_count);
466 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
471 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
474 * Scan for 1st 3 unicoded bytes
475 * followed by word aligned magic
479 bool magic_match = false;
487 if (magic_match == false) {
491 /* Align to next long address */
492 mpos = (i + sizeof(VS_SIGNATURE)*2 +
495 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
497 mpos+ VS_MAJOR_OFFSET);
499 mpos+ VS_MINOR_OFFSET);
501 DBG_INFO("PE file [%s] Version = "
502 "%08x:%08x (%d.%d.%d.%d)\n",
517 /* Version info not found, fall back to origin date/time */
518 DBG_DEBUG("PE file [%s] has no version info\n", fname);
527 /****************************************************************************
528 Detect the major and minor version of an NE file.
531 1 if file is an NE file and we got version numbers,
532 0 if this file is an NE file and we couldn't get the version numbers,
535 NB. buf is passed into and freed inside this function. This is a
536 bad API design, but fixing this is a task for another day.
537 ****************************************************************************/
539 static int handle_ne_file(files_struct *fsp,
550 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
551 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
553 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
555 * At this point, we assume the file is in error.
556 * It still could be something else besides a NE file,
557 * but it unlikely at this point.
562 /* Allocate a bit more space to speed up things */
564 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
566 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
573 * This is a HACK! I got tired of trying to sort through the
574 * messy 'NE' file format. If anyone wants to clean this up
575 * please have at it, but this works. 'NE' files will
576 * eventually fade away. JRR
578 byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
579 while (byte_count > 0) {
581 * Cover case that should not occur in a well
582 * formed 'NE' .dll file
584 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
588 for(i=0; i<byte_count; i++) {
590 * Fast skip past data that can't
594 byte_count = printing_pread_data(fsp,
602 * Potential match data crosses buf boundry,
603 * move it to beginning of buf, and fill the
604 * buf with as much as it will hold.
606 if (i>byte_count-VS_VERSION_INFO_SIZE) {
608 ssize_t amount_unused = byte_count-i;
610 memmove(buf, &buf[i], amount_unused);
611 amount_read = printing_pread_data(fsp,
614 VS_NE_BUF_SIZE- amount_unused);
615 if (amount_read < 0) {
616 DBG_ERR("NE file [%s] Read "
623 if (amount_read + amount_unused <
625 /* Check for integer wrap. */
629 byte_count = amount_read +
631 if (byte_count < VS_VERSION_INFO_SIZE) {
639 * Check that the full signature string and
640 * the magic number that follows exist (not
641 * a perfect solution, but the chances that this
642 * occurs in code is, well, remote. Yes I know
643 * I'm comparing the 'V' twice, as it is
644 * simpler to read the code.
646 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
648 * Compute skip alignment to next
652 int skip = -(cpos - (byte_count - i) +
653 sizeof(VS_SIGNATURE)) & 3;
655 i+sizeof(VS_SIGNATURE)+skip)
657 byte_count = printing_pread_data(fsp,
665 i+sizeof(VS_SIGNATURE)+
666 skip+VS_MAJOR_OFFSET);
668 i+sizeof(VS_SIGNATURE)+
669 skip+VS_MINOR_OFFSET);
670 DBG_INFO("NE file [%s] Version "
671 "= %08x:%08x (%d.%d.%d.%d)\n",
685 /* Version info not found, fall back to origin date/time */
686 DBG_ERR("NE file [%s] Version info not found\n", fname);
695 /****************************************************************************
696 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
697 There are two case to be covered here: PE (Portable Executable) and NE (New
698 Executable) files. Both files support the same INFO structure, but PE files
699 store the signature in unicode, and NE files store it as !unicode.
700 returns -1 on error, 1 on version info found, and 0 on no version info found.
701 ****************************************************************************/
703 static int get_file_version(files_struct *fsp,
710 off_t in_pos = fsp->fh->pos;
712 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
714 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
720 byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
721 if (byte_count < DOS_HEADER_SIZE) {
722 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
724 (unsigned long)byte_count);
725 goto no_version_info;
728 /* Is this really a DOS header? */
729 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
730 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
732 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
733 goto no_version_info;
737 * Skip OEM header (if any) and the
738 * DOS stub to start of Windows header.
740 in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
742 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
743 byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
744 if (byte_count < NE_HEADER_SIZE) {
745 DBG_NOTICE("File [%s] Windows header too short, "
746 "bytes read = %lu\n",
748 (unsigned long)byte_count);
750 * Assume this isn't an error...
751 * the file just looks sort of like a PE/NE file
753 goto no_version_info;
757 * The header may be a PE (Portable Executable)
758 * or an NE (New Executable).
760 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
761 return handle_pe_file(fsp,
767 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
768 NE_HEADER_SIGNATURE) {
769 return handle_ne_file(fsp,
777 * Assume this isn't an error... the file just
778 * looks sort of like a PE/NE file.
780 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
782 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
783 /* Fallthrough into no_version_info: */
795 /****************************************************************************
796 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
797 share one or more files. During the MS installation process files are checked
798 to insure that only a newer version of a shared file is installed over an
799 older version. There are several possibilities for this comparison. If there
800 is no previous version, the new one is newer (obviously). If either file is
801 missing the version info structure, compare the creation date (on Unix use
802 the modification date). Otherwise chose the numerically larger version number.
803 ****************************************************************************/
805 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
807 bool use_version = true;
811 time_t new_create_time;
815 time_t old_create_time;
817 struct smb_filename *smb_fname = NULL;
818 files_struct *fsp = NULL;
824 SET_STAT_INVALID(st);
825 new_create_time = (time_t)0;
826 old_create_time = (time_t)0;
828 /* Get file version info (if available) for previous file (if it exists) */
829 status = driver_unix_convert(conn, old_file, &smb_fname);
830 if (!NT_STATUS_IS_OK(status)) {
834 status = SMB_VFS_CREATE_FILE(
837 0, /* root_dir_fid */
838 smb_fname, /* fname */
839 FILE_GENERIC_READ, /* access_mask */
840 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
841 FILE_OPEN, /* create_disposition*/
842 0, /* create_options */
843 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
844 INTERNAL_OPEN_ONLY, /* oplock_request */
846 0, /* allocation_size */
847 0, /* private_flags */
852 NULL, NULL); /* create context */
854 if (!NT_STATUS_IS_OK(status)) {
855 /* Old file not found, so by definition new file is in fact newer */
856 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
857 "errno = %d\n", smb_fname_str_dbg(smb_fname),
863 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
869 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
872 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
875 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
876 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
877 (long)old_create_time));
880 close_file(NULL, fsp, NORMAL_CLOSE);
883 /* Get file version info (if available) for new file */
884 status = driver_unix_convert(conn, new_file, &smb_fname);
885 if (!NT_STATUS_IS_OK(status)) {
889 status = SMB_VFS_CREATE_FILE(
892 0, /* root_dir_fid */
893 smb_fname, /* fname */
894 FILE_GENERIC_READ, /* access_mask */
895 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
896 FILE_OPEN, /* create_disposition*/
897 0, /* create_options */
898 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
899 INTERNAL_OPEN_ONLY, /* oplock_request */
901 0, /* allocation_size */
902 0, /* private_flags */
907 NULL, NULL); /* create context */
909 if (!NT_STATUS_IS_OK(status)) {
910 /* New file not found, this shouldn't occur if the caller did its job */
911 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
912 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
916 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
922 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
925 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
928 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
929 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
930 (long)new_create_time));
933 close_file(NULL, fsp, NORMAL_CLOSE);
936 if (use_version && (new_major != old_major || new_minor != old_minor)) {
937 /* Compare versions and choose the larger version number */
938 if (new_major > old_major ||
939 (new_major == old_major && new_minor > old_minor)) {
941 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
946 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
952 /* Compare modification time/dates and choose the newest time/date */
953 if (new_create_time > old_create_time) {
954 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
959 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
967 close_file(NULL, fsp, NORMAL_CLOSE);
970 TALLOC_FREE(smb_fname);
974 /****************************************************************************
975 Determine the correct cVersion associated with an architecture and driver
976 ****************************************************************************/
977 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
978 const char *architecture,
979 const char *driverpath_in,
980 const char *driver_directory,
985 struct smb_filename *smb_fname = NULL;
986 files_struct *fsp = NULL;
987 connection_struct *conn = NULL;
988 struct smb_filename *oldcwd_fname = NULL;
989 char *printdollar = NULL;
990 char *printdollar_path = NULL;
991 char *working_dir = NULL;
992 int printdollar_snum;
994 *perr = WERR_INVALID_PARAMETER;
996 /* If architecture is Windows 95/98/ME, the version is always 0. */
997 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
998 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1003 /* If architecture is Windows x64, the version is always 3. */
1004 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1005 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1010 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1012 *perr = WERR_NOT_ENOUGH_MEMORY;
1015 if (printdollar_snum == -1) {
1016 *perr = WERR_BAD_NET_NAME;
1020 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
1021 if (printdollar_path == NULL) {
1022 *perr = WERR_NOT_ENOUGH_MEMORY;
1026 working_dir = talloc_asprintf(talloc_tos(),
1031 * If the driver has been uploaded into a temorpary driver
1032 * directory, switch to the driver directory.
1034 if (driver_directory != NULL) {
1035 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
1041 nt_status = create_conn_struct_cwd(talloc_tos(),
1042 server_event_context(),
1043 server_messaging_context(),
1047 session_info, &oldcwd_fname);
1048 if (!NT_STATUS_IS_OK(nt_status)) {
1049 DEBUG(0,("get_correct_cversion: create_conn_struct "
1050 "returned %s\n", nt_errstr(nt_status)));
1051 *perr = ntstatus_to_werror(nt_status);
1055 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1056 if (!NT_STATUS_IS_OK(nt_status)) {
1057 DEBUG(0, ("failed set force user / group\n"));
1058 *perr = ntstatus_to_werror(nt_status);
1059 goto error_free_conn;
1062 if (!become_user_by_session(conn, session_info)) {
1063 DEBUG(0, ("failed to become user\n"));
1064 *perr = WERR_ACCESS_DENIED;
1065 goto error_free_conn;
1069 * We switch to the directory where the driver files are located,
1070 * so only work on the file names
1072 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1073 if (!NT_STATUS_IS_OK(nt_status)) {
1074 *perr = ntstatus_to_werror(nt_status);
1078 nt_status = vfs_file_exist(conn, smb_fname);
1079 if (!NT_STATUS_IS_OK(nt_status)) {
1080 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1081 *perr = WERR_FILE_NOT_FOUND;
1085 nt_status = SMB_VFS_CREATE_FILE(
1088 0, /* root_dir_fid */
1089 smb_fname, /* fname */
1090 FILE_GENERIC_READ, /* access_mask */
1091 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1092 FILE_OPEN, /* create_disposition*/
1093 0, /* create_options */
1094 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1095 INTERNAL_OPEN_ONLY, /* oplock_request */
1097 0, /* private_flags */
1098 0, /* allocation_size */
1103 NULL, NULL); /* create context */
1105 if (!NT_STATUS_IS_OK(nt_status)) {
1106 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1107 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1108 *perr = WERR_ACCESS_DENIED;
1115 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1117 *perr = WERR_INVALID_PARAMETER;
1120 DEBUG(6,("get_correct_cversion: Version info not "
1122 smb_fname_str_dbg(smb_fname)));
1123 *perr = WERR_INVALID_PARAMETER;
1128 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1129 * for more details. Version in this case is not just the version of the
1130 * file, but the version in the sense of kernal mode (2) vs. user mode
1131 * (3) drivers. Other bits of the version fields are the version info.
1134 cversion = major & 0x0000ffff;
1136 case 2: /* WinNT drivers */
1137 case 3: /* Win2K drivers */
1141 DEBUG(6,("get_correct_cversion: cversion "
1142 "invalid [%s] cversion = %d\n",
1143 smb_fname_str_dbg(smb_fname),
1148 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1149 " = 0x%x minor = 0x%x\n",
1150 smb_fname_str_dbg(smb_fname), major, minor));
1153 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1154 smb_fname_str_dbg(smb_fname), cversion));
1160 TALLOC_FREE(smb_fname);
1162 close_file(NULL, fsp, NORMAL_CLOSE);
1165 vfs_ChDir(conn, oldcwd_fname);
1166 TALLOC_FREE(oldcwd_fname);
1167 SMB_VFS_DISCONNECT(conn);
1170 if (!W_ERROR_IS_OK(*perr)) {
1177 /****************************************************************************
1178 ****************************************************************************/
1180 #define strip_driver_path(_mem_ctx, _element) do { \
1181 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1182 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1183 W_ERROR_HAVE_NO_MEMORY((_element)); \
1187 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1188 struct auth_session_info *session_info,
1189 const char *architecture,
1190 const char **driver_path,
1191 const char **data_file,
1192 const char **config_file,
1193 const char **help_file,
1194 struct spoolss_StringArray *dependent_files,
1195 enum spoolss_DriverOSVersion *version,
1197 const char **driver_directory)
1199 const char *short_architecture;
1204 if (!*driver_path || !*data_file) {
1205 return WERR_INVALID_PARAMETER;
1208 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1209 return WERR_INVALID_PARAMETER;
1212 if (flags & APD_COPY_FROM_DIRECTORY) {
1217 * driver_path is set to:
1219 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1221 path = talloc_strdup(mem_ctx, *driver_path);
1223 return WERR_NOT_ENOUGH_MEMORY;
1226 /* Remove pscript5.dll */
1227 q = strrchr_m(path, '\\');
1229 return WERR_INVALID_PARAMETER;
1233 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1234 q = strrchr_m(path, '\\');
1236 return WERR_INVALID_PARAMETER;
1240 * Set driver_directory to:
1242 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1244 * This is the directory where all the files have been uploaded
1246 *driver_directory = q + 1;
1249 /* clean up the driver name.
1250 * we can get .\driver.dll
1251 * or worse c:\windows\system\driver.dll !
1253 /* using an intermediate string to not have overlaping memcpy()'s */
1255 strip_driver_path(mem_ctx, *driver_path);
1256 strip_driver_path(mem_ctx, *data_file);
1258 strip_driver_path(mem_ctx, *config_file);
1261 strip_driver_path(mem_ctx, *help_file);
1264 if (dependent_files && dependent_files->string) {
1265 for (i=0; dependent_files->string[i]; i++) {
1266 strip_driver_path(mem_ctx, dependent_files->string[i]);
1270 short_architecture = get_short_archi(architecture);
1271 if (!short_architecture) {
1272 return WERR_UNKNOWN_PRINTER_DRIVER;
1275 /* jfm:7/16/2000 the client always sends the cversion=0.
1276 * The server should check which version the driver is by reading
1277 * the PE header of driver->driverpath.
1279 * For Windows 95/98 the version is 0 (so the value sent is correct)
1280 * For Windows NT (the architecture doesn't matter)
1281 * NT 3.1: cversion=0
1282 * NT 3.5/3.51: cversion=1
1287 *version = get_correct_cversion(session_info,
1292 if (*version == -1) {
1299 /****************************************************************************
1300 ****************************************************************************/
1302 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1303 struct auth_session_info *session_info,
1304 struct spoolss_AddDriverInfoCtr *r,
1306 const char **driver_directory)
1310 return clean_up_driver_struct_level(mem_ctx, session_info,
1311 r->info.info3->architecture,
1312 &r->info.info3->driver_path,
1313 &r->info.info3->data_file,
1314 &r->info.info3->config_file,
1315 &r->info.info3->help_file,
1316 r->info.info3->dependent_files,
1317 &r->info.info3->version,
1321 return clean_up_driver_struct_level(mem_ctx, session_info,
1322 r->info.info6->architecture,
1323 &r->info.info6->driver_path,
1324 &r->info.info6->data_file,
1325 &r->info.info6->config_file,
1326 &r->info.info6->help_file,
1327 r->info.info6->dependent_files,
1328 &r->info.info6->version,
1332 return clean_up_driver_struct_level(mem_ctx, session_info,
1333 r->info.info8->architecture,
1334 &r->info.info8->driver_path,
1335 &r->info.info8->data_file,
1336 &r->info.info8->config_file,
1337 &r->info.info8->help_file,
1338 r->info.info8->dependent_files,
1339 &r->info.info8->version,
1343 return WERR_NOT_SUPPORTED;
1347 /****************************************************************************
1348 This function sucks and should be replaced. JRA.
1349 ****************************************************************************/
1351 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1352 const struct spoolss_AddDriverInfo6 *src)
1354 dst->version = src->version;
1356 dst->driver_name = src->driver_name;
1357 dst->architecture = src->architecture;
1358 dst->driver_path = src->driver_path;
1359 dst->data_file = src->data_file;
1360 dst->config_file = src->config_file;
1361 dst->help_file = src->help_file;
1362 dst->monitor_name = src->monitor_name;
1363 dst->default_datatype = src->default_datatype;
1364 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1365 dst->dependent_files = src->dependent_files;
1368 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1369 const struct spoolss_AddDriverInfo8 *src)
1371 dst->version = src->version;
1373 dst->driver_name = src->driver_name;
1374 dst->architecture = src->architecture;
1375 dst->driver_path = src->driver_path;
1376 dst->data_file = src->data_file;
1377 dst->config_file = src->config_file;
1378 dst->help_file = src->help_file;
1379 dst->monitor_name = src->monitor_name;
1380 dst->default_datatype = src->default_datatype;
1381 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1382 dst->dependent_files = src->dependent_files;
1385 /****************************************************************************
1386 ****************************************************************************/
1388 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1389 connection_struct *conn,
1390 const char *driver_file,
1391 const char *short_architecture,
1392 uint32_t driver_version,
1394 const char *driver_directory)
1396 struct smb_filename *smb_fname_old = NULL;
1397 struct smb_filename *smb_fname_new = NULL;
1398 char *old_name = NULL;
1399 char *new_name = NULL;
1403 if (driver_directory != NULL) {
1404 old_name = talloc_asprintf(mem_ctx,
1410 old_name = talloc_asprintf(mem_ctx,
1415 if (old_name == NULL) {
1416 return WERR_NOT_ENOUGH_MEMORY;
1419 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1420 short_architecture, driver_version, driver_file);
1421 if (new_name == NULL) {
1422 TALLOC_FREE(old_name);
1423 return WERR_NOT_ENOUGH_MEMORY;
1426 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1428 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 ret = WERR_NOT_ENOUGH_MEMORY;
1434 /* Setup a synthetic smb_filename struct */
1435 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1436 if (!smb_fname_new) {
1437 ret = WERR_NOT_ENOUGH_MEMORY;
1441 smb_fname_new->base_name = new_name;
1443 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1444 "'%s'\n", smb_fname_old->base_name,
1445 smb_fname_new->base_name));
1447 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1448 OPENX_FILE_EXISTS_TRUNCATE |
1449 OPENX_FILE_CREATE_IF_NOT_EXIST,
1452 if (!NT_STATUS_IS_OK(status)) {
1453 DEBUG(0,("move_driver_file_to_download_area: Unable "
1454 "to rename [%s] to [%s]: %s\n",
1455 smb_fname_old->base_name, new_name,
1456 nt_errstr(status)));
1457 ret = WERR_APP_INIT_FAILURE;
1464 TALLOC_FREE(smb_fname_old);
1465 TALLOC_FREE(smb_fname_new);
1469 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1470 struct spoolss_AddDriverInfoCtr *r,
1471 const char *driver_directory)
1473 struct spoolss_AddDriverInfo3 *driver;
1474 struct spoolss_AddDriverInfo3 converted_driver;
1475 const char *short_architecture;
1476 struct smb_filename *smb_dname = NULL;
1477 char *new_dir = NULL;
1478 connection_struct *conn = NULL;
1481 TALLOC_CTX *ctx = talloc_tos();
1483 struct smb_filename *oldcwd_fname = NULL;
1484 char *printdollar = NULL;
1485 int printdollar_snum;
1486 WERROR err = WERR_OK;
1490 driver = r->info.info3;
1493 convert_level_6_to_level3(&converted_driver, r->info.info6);
1494 driver = &converted_driver;
1497 convert_level_8_to_level3(&converted_driver, r->info.info8);
1498 driver = &converted_driver;
1501 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1502 return WERR_INVALID_LEVEL;
1505 short_architecture = get_short_archi(driver->architecture);
1506 if (!short_architecture) {
1507 return WERR_UNKNOWN_PRINTER_DRIVER;
1510 printdollar_snum = find_service(ctx, "print$", &printdollar);
1512 return WERR_NOT_ENOUGH_MEMORY;
1514 if (printdollar_snum == -1) {
1515 return WERR_BAD_NET_NAME;
1518 nt_status = create_conn_struct_cwd(talloc_tos(),
1519 server_event_context(),
1520 server_messaging_context(),
1523 lp_path(talloc_tos(), printdollar_snum),
1524 session_info, &oldcwd_fname);
1525 if (!NT_STATUS_IS_OK(nt_status)) {
1526 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1527 "returned %s\n", nt_errstr(nt_status)));
1528 err = ntstatus_to_werror(nt_status);
1532 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1533 if (!NT_STATUS_IS_OK(nt_status)) {
1534 DEBUG(0, ("failed set force user / group\n"));
1535 err = ntstatus_to_werror(nt_status);
1539 if (!become_user_by_session(conn, session_info)) {
1540 DEBUG(0, ("failed to become user\n"));
1541 err = WERR_ACCESS_DENIED;
1545 new_dir = talloc_asprintf(ctx,
1550 err = WERR_NOT_ENOUGH_MEMORY;
1553 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1554 if (!NT_STATUS_IS_OK(nt_status)) {
1555 err = WERR_NOT_ENOUGH_MEMORY;
1559 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1561 nt_status = create_directory(conn, NULL, smb_dname);
1562 if (!NT_STATUS_IS_OK(nt_status)
1563 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1564 DEBUG(0, ("failed to create driver destination directory: %s\n",
1565 nt_errstr(nt_status)));
1566 err = ntstatus_to_werror(nt_status);
1570 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1571 * listed for this driver which has already been moved, skip it (note:
1572 * drivers may list the same file name several times. Then check if the
1573 * file already exists in archi\version\, if so, check that the version
1574 * info (or time stamps if version info is unavailable) is newer (or the
1575 * date is later). If it is, move it to archi\version\filexxx.yyy.
1576 * Otherwise, delete the file.
1578 * If a file is not moved to archi\version\ because of an error, all the
1579 * rest of the 'unmoved' driver files are removed from archi\. If one or
1580 * more of the driver's files was already moved to archi\version\, it
1581 * potentially leaves the driver in a partially updated state. Version
1582 * trauma will most likely occur if an client attempts to use any printer
1583 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1584 * done is appropriate... later JRR
1587 DEBUG(5,("Moving files now !\n"));
1589 if (driver->driver_path && strlen(driver->driver_path)) {
1591 err = move_driver_file_to_download_area(ctx,
1593 driver->driver_path,
1598 if (!W_ERROR_IS_OK(err)) {
1603 if (driver->data_file && strlen(driver->data_file)) {
1604 if (!strequal(driver->data_file, driver->driver_path)) {
1606 err = move_driver_file_to_download_area(ctx,
1613 if (!W_ERROR_IS_OK(err)) {
1619 if (driver->config_file && strlen(driver->config_file)) {
1620 if (!strequal(driver->config_file, driver->driver_path) &&
1621 !strequal(driver->config_file, driver->data_file)) {
1623 err = move_driver_file_to_download_area(ctx,
1625 driver->config_file,
1630 if (!W_ERROR_IS_OK(err)) {
1636 if (driver->help_file && strlen(driver->help_file)) {
1637 if (!strequal(driver->help_file, driver->driver_path) &&
1638 !strequal(driver->help_file, driver->data_file) &&
1639 !strequal(driver->help_file, driver->config_file)) {
1641 err = move_driver_file_to_download_area(ctx,
1648 if (!W_ERROR_IS_OK(err)) {
1654 if (driver->dependent_files && driver->dependent_files->string) {
1655 for (i=0; driver->dependent_files->string[i]; i++) {
1656 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1657 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1658 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1659 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1661 for (j=0; j < i; j++) {
1662 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1667 err = move_driver_file_to_download_area(ctx,
1669 driver->dependent_files->string[i],
1674 if (!W_ERROR_IS_OK(err)) {
1686 TALLOC_FREE(smb_dname);
1689 vfs_ChDir(conn, oldcwd_fname);
1690 TALLOC_FREE(oldcwd_fname);
1691 SMB_VFS_DISCONNECT(conn);
1698 /****************************************************************************
1699 Determine whether or not a particular driver is currently assigned
1701 ****************************************************************************/
1703 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1704 struct dcerpc_binding_handle *b,
1705 const struct spoolss_DriverInfo8 *r)
1708 int n_services = lp_numservices();
1709 bool in_use = false;
1710 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1717 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1719 /* loop through the printers.tdb and check for the drivername */
1721 for (snum=0; snum<n_services && !in_use; snum++) {
1722 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1726 result = winreg_get_printer(mem_ctx, b,
1727 lp_servicename(talloc_tos(), snum),
1729 if (!W_ERROR_IS_OK(result)) {
1730 continue; /* skip */
1733 if (strequal(r->driver_name, pinfo2->drivername)) {
1737 TALLOC_FREE(pinfo2);
1740 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1743 struct spoolss_DriverInfo8 *driver = NULL;
1746 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1748 /* we can still remove the driver if there is one of
1749 "Windows NT x86" version 2 or 3 left */
1751 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1752 if (r->version == 2) {
1753 werr = winreg_get_driver(mem_ctx, b,
1757 } else if (r->version == 3) {
1758 werr = winreg_get_driver(mem_ctx, b,
1763 DBG_ERR("Unknown driver version (%d)\n",
1765 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1767 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1768 werr = winreg_get_driver(mem_ctx, b,
1769 SPOOLSS_ARCHITECTURE_NT_X86,
1774 DBG_ERR("Unknown driver architecture: %s\n",
1776 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1779 /* now check the error code */
1781 if ( W_ERROR_IS_OK(werr) ) {
1782 /* it's ok to remove the driver, we have other architctures left */
1784 talloc_free(driver);
1788 /* report that the driver is not in use by default */
1794 /**********************************************************************
1795 Check to see if a ogiven file is in use by *info
1796 *********************************************************************/
1798 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1805 /* mz: skip files that are in the list but already deleted */
1806 if (!file || !file[0]) {
1810 if (strequal(file, info->driver_path))
1813 if (strequal(file, info->data_file))
1816 if (strequal(file, info->config_file))
1819 if (strequal(file, info->help_file))
1822 /* see of there are any dependent files to examine */
1824 if (!info->dependent_files)
1827 while (info->dependent_files[i] && *info->dependent_files[i]) {
1828 if (strequal(file, info->dependent_files[i]))
1837 /**********************************************************************
1838 Utility function to remove the dependent file pointed to by the
1839 input parameter from the list
1840 *********************************************************************/
1842 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1845 /* bump everything down a slot */
1847 while (files && files[idx+1]) {
1848 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1857 /**********************************************************************
1858 Check if any of the files used by src are also used by drv
1859 *********************************************************************/
1861 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1862 struct spoolss_DriverInfo8 *src,
1863 const struct spoolss_DriverInfo8 *drv)
1865 bool in_use = False;
1871 /* check each file. Remove it from the src structure if it overlaps */
1873 if (drv_file_in_use(src->driver_path, drv)) {
1875 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1876 src->driver_path = talloc_strdup(mem_ctx, "");
1877 if (!src->driver_path) { return false; }
1880 if (drv_file_in_use(src->data_file, drv)) {
1882 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1883 src->data_file = talloc_strdup(mem_ctx, "");
1884 if (!src->data_file) { return false; }
1887 if (drv_file_in_use(src->config_file, drv)) {
1889 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1890 src->config_file = talloc_strdup(mem_ctx, "");
1891 if (!src->config_file) { return false; }
1894 if (drv_file_in_use(src->help_file, drv)) {
1896 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1897 src->help_file = talloc_strdup(mem_ctx, "");
1898 if (!src->help_file) { return false; }
1901 /* are there any dependentfiles to examine? */
1903 if (!src->dependent_files)
1906 while (src->dependent_files[i] && *src->dependent_files[i]) {
1907 if (drv_file_in_use(src->dependent_files[i], drv)) {
1909 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1910 trim_dependent_file(mem_ctx, src->dependent_files, i);
1918 /****************************************************************************
1919 Determine whether or not a particular driver files are currently being
1920 used by any other driver.
1922 Return value is True if any files were in use by other drivers
1923 and False otherwise.
1925 Upon return, *info has been modified to only contain the driver files
1926 which are not in use
1930 This needs to check all drivers to ensure that all files in use
1931 have been removed from *info, not just the ones in the first
1933 ****************************************************************************/
1935 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1936 struct dcerpc_binding_handle *b,
1937 struct spoolss_DriverInfo8 *info)
1941 struct spoolss_DriverInfo8 *driver;
1942 bool in_use = false;
1943 uint32_t num_drivers;
1944 const char **drivers;
1950 version = info->version;
1952 /* loop over all driver versions */
1954 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1956 /* get the list of drivers */
1958 result = winreg_get_driver_list(mem_ctx, b,
1959 info->architecture, version,
1960 &num_drivers, &drivers);
1961 if (!W_ERROR_IS_OK(result)) {
1965 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1966 num_drivers, info->architecture, version));
1968 /* check each driver for overlap in files */
1970 for (i = 0; i < num_drivers; i++) {
1971 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1975 result = winreg_get_driver(mem_ctx, b,
1976 info->architecture, drivers[i],
1978 if (!W_ERROR_IS_OK(result)) {
1979 talloc_free(drivers);
1983 /* check if d2 uses any files from d1 */
1984 /* only if this is a different driver than the one being deleted */
1986 if (!strequal(info->driver_name, driver->driver_name)) {
1987 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1988 /* mz: Do not instantly return -
1989 * we need to ensure this file isn't
1990 * also in use by other drivers. */
1995 talloc_free(driver);
1998 talloc_free(drivers);
2000 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2005 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2006 const char *short_arch,
2010 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2011 struct smb_filename *smb_fname = NULL;
2012 char *print_dlr_path;
2013 NTSTATUS status = NT_STATUS_NO_MEMORY;
2015 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2016 short_arch, vers, fname);
2017 if (print_dlr_path == NULL) {
2021 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2022 if (smb_fname == NULL) {
2026 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2028 talloc_free(tmp_ctx);
2032 /****************************************************************************
2033 Actually delete the driver files. Make sure that
2034 printer_driver_files_in_use() return False before calling
2036 ****************************************************************************/
2038 bool delete_driver_files(const struct auth_session_info *session_info,
2039 const struct spoolss_DriverInfo8 *r)
2041 const char *short_arch;
2042 connection_struct *conn;
2044 struct smb_filename *oldcwd_fname = NULL;
2045 char *printdollar = NULL;
2046 int printdollar_snum;
2053 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2054 r->driver_name, r->version));
2056 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2060 if (printdollar_snum == -1) {
2064 nt_status = create_conn_struct_cwd(talloc_tos(),
2065 server_event_context(),
2066 server_messaging_context(),
2069 lp_path(talloc_tos(), printdollar_snum),
2070 session_info, &oldcwd_fname);
2071 if (!NT_STATUS_IS_OK(nt_status)) {
2072 DEBUG(0,("delete_driver_files: create_conn_struct "
2073 "returned %s\n", nt_errstr(nt_status)));
2077 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2078 if (!NT_STATUS_IS_OK(nt_status)) {
2079 DEBUG(0, ("failed set force user / group\n"));
2084 if (!become_user_by_session(conn, session_info)) {
2085 DEBUG(0, ("failed to become user\n"));
2090 if ( !CAN_WRITE(conn) ) {
2091 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2096 short_arch = get_short_archi(r->architecture);
2097 if (short_arch == NULL) {
2098 DEBUG(0, ("bad architecture %s\n", r->architecture));
2103 /* now delete the files */
2105 if (r->driver_path && r->driver_path[0]) {
2106 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2107 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2110 if (r->config_file && r->config_file[0]) {
2111 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2112 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2115 if (r->data_file && r->data_file[0]) {
2116 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2117 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2120 if (r->help_file && r->help_file[0]) {
2121 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2122 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2125 if (r->dependent_files) {
2127 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2128 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2129 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2139 vfs_ChDir(conn, oldcwd_fname);
2140 TALLOC_FREE(oldcwd_fname);
2141 SMB_VFS_DISCONNECT(conn);
2149 1: level not implemented
2150 2: file doesn't exist
2151 3: can't allocate memory
2152 4: can't free memory
2153 5: non existent struct
2157 A printer and a printer driver are 2 different things.
2158 NT manages them separatelly, Samba does the same.
2159 Why ? Simply because it's easier and it makes sense !
2161 Now explanation: You have 3 printers behind your samba server,
2162 2 of them are the same make and model (laser A and B). But laser B
2163 has an 3000 sheet feeder and laser A doesn't such an option.
2164 Your third printer is an old dot-matrix model for the accounting :-).
2166 If the /usr/local/samba/lib directory (default dir), you will have
2167 5 files to describe all of this.
2169 3 files for the printers (1 by printer):
2172 NTprinter_accounting
2173 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2174 NTdriver_printer model X
2175 NTdriver_printer model Y
2177 jfm: I should use this comment for the text file to explain
2178 same thing for the forms BTW.
2179 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2183 /* Convert generic access rights to printer object specific access rights.
2184 It turns out that NT4 security descriptors use generic access rights and
2185 NT5 the object specific ones. */
2187 void map_printer_permissions(struct security_descriptor *sd)
2191 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2192 se_map_generic(&sd->dacl->aces[i].access_mask,
2193 &printer_generic_mapping);
2197 void map_job_permissions(struct security_descriptor *sd)
2201 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2202 se_map_generic(&sd->dacl->aces[i].access_mask,
2203 &job_generic_mapping);
2208 /****************************************************************************
2209 Check a user has permissions to perform the given operation. We use the
2210 permission constants defined in include/rpc_spoolss.h to check the various
2211 actions we perform when checking printer access.
2213 PRINTER_ACCESS_ADMINISTER:
2214 print_queue_pause, print_queue_resume, update_printer_sec,
2215 update_printer, spoolss_addprinterex_level_2,
2216 _spoolss_setprinterdata
2221 JOB_ACCESS_ADMINISTER:
2222 print_job_delete, print_job_pause, print_job_resume,
2225 Try access control in the following order (for performance reasons):
2226 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2227 2) check security descriptor (bit comparisons in memory)
2228 3) "printer admins" (may result in numerous calls to winbind)
2230 ****************************************************************************/
2231 WERROR print_access_check(const struct auth_session_info *session_info,
2232 struct messaging_context *msg_ctx, int snum,
2235 struct spoolss_security_descriptor *secdesc = NULL;
2236 uint32_t access_granted;
2241 TALLOC_CTX *mem_ctx = NULL;
2243 /* If user is NULL then use the current_user structure */
2245 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2247 if ((session_info->unix_token->uid == sec_initial_uid())
2248 || security_token_has_privilege(session_info->security_token,
2249 SEC_PRIV_PRINT_OPERATOR)) {
2253 /* Get printer name */
2255 pname = lp_printername(talloc_tos(), snum);
2257 if (!pname || !*pname) {
2258 return WERR_ACCESS_DENIED;
2261 /* Get printer security descriptor */
2263 if(!(mem_ctx = talloc_init("print_access_check"))) {
2264 return WERR_NOT_ENOUGH_MEMORY;
2267 result = winreg_get_printer_secdesc_internal(mem_ctx,
2268 get_session_info_system(),
2272 if (!W_ERROR_IS_OK(result)) {
2273 talloc_destroy(mem_ctx);
2274 return WERR_NOT_ENOUGH_MEMORY;
2277 if (access_type == JOB_ACCESS_ADMINISTER) {
2278 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2280 /* Create a child security descriptor to check permissions
2281 against. This is because print jobs are child objects
2282 objects of a printer. */
2283 status = se_create_child_secdesc(mem_ctx,
2287 parent_secdesc->owner_sid,
2288 parent_secdesc->group_sid,
2290 if (!NT_STATUS_IS_OK(status)) {
2291 talloc_destroy(mem_ctx);
2292 return ntstatus_to_werror(status);
2295 map_job_permissions(secdesc);
2297 map_printer_permissions(secdesc);
2301 status = se_access_check(secdesc, session_info->security_token, access_type,
2304 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2306 talloc_destroy(mem_ctx);
2308 return ntstatus_to_werror(status);
2311 /****************************************************************************
2312 Check the time parameters allow a print operation.
2313 *****************************************************************************/
2315 bool print_time_access_check(const struct auth_session_info *session_info,
2316 struct messaging_context *msg_ctx,
2317 const char *servicename)
2319 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2322 time_t now = time(NULL);
2326 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2327 servicename, &pinfo2);
2328 if (!W_ERROR_IS_OK(result)) {
2332 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2337 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2339 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2343 TALLOC_FREE(pinfo2);
2352 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2353 const struct auth_session_info *session_info,
2354 struct messaging_context *msg_ctx,
2355 const char *printer)
2359 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2361 if (!W_ERROR_IS_OK(result)) {
2362 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2363 "%s\n", printer, win_errstr(result)));
2367 void nt_printer_add(TALLOC_CTX *mem_ctx,
2368 const struct auth_session_info *session_info,
2369 struct messaging_context *msg_ctx,
2370 const char *printer)
2374 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2376 if (!W_ERROR_IS_OK(result)) {
2377 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2378 printer, win_errstr(result)));