2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "printing/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.h"
38 /* Map generic permissions to printer object specific permissions */
40 const struct generic_mapping printer_generic_mapping = {
47 /* Map generic permissions to print server object specific permissions */
49 const struct generic_mapping printserver_generic_mapping = {
56 /* Map generic permissions to job object specific permissions */
58 const struct generic_mapping job_generic_mapping = {
65 static const struct print_architecture_table_node archi_table[]= {
67 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
68 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
69 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
70 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
71 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
72 {"Windows IA64", SPL_ARCH_IA64, 3 },
73 {"Windows x64", SPL_ARCH_X64, 3 },
77 static bool print_driver_directories_init(void)
82 TALLOC_CTX *mem_ctx = talloc_stackframe();
83 const char *dir_list[] = {
89 service = lp_servicenumber("print$");
91 /* We don't have a print$ share */
92 DEBUG(5, ("No print$ share has been configured.\n"));
97 driver_path = lp_path(mem_ctx, service);
98 if (driver_path == NULL) {
103 ok = directory_create_or_exist(driver_path, 0755);
105 DEBUG(1, ("Failed to create printer driver directory %s\n",
107 talloc_free(mem_ctx);
111 for (i = 0; archi_table[i].long_archi != NULL; i++) {
112 const char *arch_path;
114 arch_path = talloc_asprintf(mem_ctx,
117 archi_table[i].short_archi);
118 if (arch_path == NULL) {
119 talloc_free(mem_ctx);
123 ok = directory_create_or_exist(arch_path, 0755);
125 DEBUG(1, ("Failed to create printer driver "
126 "architecture directory %s\n",
128 talloc_free(mem_ctx);
133 for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
136 path = talloc_asprintf(mem_ctx,
141 talloc_free(mem_ctx);
145 ok = directory_create_or_exist(path, 0755);
147 DEBUG(1, ("Failed to create printer driver "
148 "architecture directory %s\n",
150 talloc_free(mem_ctx);
155 driver_path = state_path("DriverStore");
156 if (driver_path == NULL) {
157 talloc_free(mem_ctx);
161 ok = directory_create_or_exist(driver_path, 0755);
163 DEBUG(1,("failed to create path %s\n", driver_path));
164 talloc_free(mem_ctx);
168 driver_path = state_path("DriverStore/FileRepository");
169 if (driver_path == NULL) {
170 talloc_free(mem_ctx);
174 ok = directory_create_or_exist(driver_path, 0755);
176 DEBUG(1,("failed to create path %s\n", driver_path));
177 talloc_free(mem_ctx);
181 driver_path = state_path("DriverStore/Temp");
182 if (driver_path == NULL) {
183 talloc_free(mem_ctx);
187 ok = directory_create_or_exist(driver_path, 0755);
189 DEBUG(1,("failed to create path %s\n", driver_path));
190 talloc_free(mem_ctx);
194 talloc_free(mem_ctx);
198 /****************************************************************************
199 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
200 background lpq updater.
201 ****************************************************************************/
203 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
206 struct server_id server_id,
209 extern pid_t background_lpq_updater_pid;
211 if (background_lpq_updater_pid == -1) {
212 DEBUG(3,("no background lpq queue updater\n"));
216 messaging_send_buf(msg,
217 pid_to_procid(background_lpq_updater_pid),
218 MSG_PRINTER_DRVUPGRADE,
223 /****************************************************************************
224 Open the NT printing tdbs. Done once before fork().
225 ****************************************************************************/
227 bool nt_printing_init(struct messaging_context *msg_ctx)
231 if (!print_driver_directories_init()) {
235 if (!nt_printing_tdb_upgrade()) {
240 * register callback to handle updating printers as new
241 * drivers are installed. Forwards to background lpq updater.
243 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
244 forward_drv_upgrade_printer_msg);
246 if ( lp_security() == SEC_ADS ) {
247 win_rc = check_published_printers(msg_ctx);
248 if (!W_ERROR_IS_OK(win_rc))
249 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
255 /*******************************************************************
256 Function to allow filename parsing "the old way".
257 ********************************************************************/
259 static NTSTATUS driver_unix_convert(connection_struct *conn,
260 const char *old_name,
261 struct smb_filename **smb_fname)
264 TALLOC_CTX *ctx = talloc_tos();
265 char *name = talloc_strdup(ctx, old_name);
268 return NT_STATUS_NO_MEMORY;
271 name = unix_clean_name(ctx, name);
273 return NT_STATUS_NO_MEMORY;
275 trim_string(name,"/","/");
277 status = unix_convert(ctx, conn, name, smb_fname, 0);
278 if (!NT_STATUS_IS_OK(status)) {
279 return NT_STATUS_NO_MEMORY;
285 /****************************************************************************
286 Function to do the mapping between the long architecture name and
288 ****************************************************************************/
290 const char *get_short_archi(const char *long_archi)
294 DEBUG(107,("Getting architecture dependent directory\n"));
297 } while ( (archi_table[i].long_archi!=NULL ) &&
298 strcasecmp_m(long_archi, archi_table[i].long_archi) );
300 if (archi_table[i].long_archi==NULL) {
301 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
305 /* this might be client code - but shouldn't this be an fstrcpy etc? */
307 DEBUGADD(108,("index: [%d]\n", i));
308 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
309 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
311 return archi_table[i].short_archi;
314 /****************************************************************************
315 Read data from fsp on the vfs.
316 (note: EINTR re-read differs from vfs_write_data)
317 ****************************************************************************/
319 static ssize_t printing_read_data(files_struct *fsp,
325 while (total < byte_count) {
326 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
333 if (errno == EINTR) {
341 return (ssize_t)total;
344 /****************************************************************************
345 Detect the major and minor version of a PE file.
348 1 if file is a PE file and we got version numbers,
349 0 if this file is a PE file and we couldn't get the version numbers,
352 NB. buf is passed into and freed inside this function. This is a
353 bad API design, but fixing this is a task for another day.
354 ****************************************************************************/
356 static int handle_pe_file(files_struct *fsp,
363 unsigned int num_sections;
364 unsigned int section_table_bytes;
370 /* Just skip over optional header to get to section table */
371 pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
372 (NE_HEADER_SIZE-PE_HEADER_SIZE);
374 oret = SMB_VFS_LSEEK(fsp, pos, SEEK_CUR);
375 if (oret == (off_t)-1) {
376 DBG_NOTICE("File [%s] Windows optional header "
377 "too short, errno = %d\n",
383 /* get the section table */
384 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
385 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
386 if (section_table_bytes == 0) {
391 buf = (char *)SMB_MALLOC(section_table_bytes);
393 DBG_ERR("PE file [%s] section table malloc "
394 "failed bytes = %d\n",
396 section_table_bytes);
400 byte_count = printing_read_data(fsp, buf, section_table_bytes);
401 if (byte_count < section_table_bytes) {
402 DBG_NOTICE("PE file [%s] Section header too short, "
403 "bytes read = %lu\n",
405 (unsigned long)byte_count);
410 * Iterate the section table looking for
411 * the resource section ".rsrc"
413 for (i = 0; i < num_sections; i++) {
414 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
417 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
418 unsigned int section_pos = IVAL(buf,
420 PE_HEADER_SECT_PTR_DATA_OFFSET);
421 unsigned int section_bytes = IVAL(buf,
423 PE_HEADER_SECT_SIZE_DATA_OFFSET);
425 if (section_bytes == 0) {
430 buf=(char *)SMB_MALLOC(section_bytes);
432 DBG_ERR("PE file [%s] version malloc "
433 "failed bytes = %d\n",
440 * Seek to the start of the .rsrc
443 oret = SMB_VFS_LSEEK(fsp,
446 if (oret == (off_t)-1) {
447 DBG_NOTICE("PE file [%s] too short for "
448 "section info, errno = %d\n",
454 byte_count = printing_read_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,
549 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
550 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
552 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
554 * At this point, we assume the file is in error.
555 * It still could be something else besides a NE file,
556 * but it unlikely at this point.
561 /* Allocate a bit more space to speed up things */
563 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
565 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
572 * This is a HACK! I got tired of trying to sort through the
573 * messy 'NE' file format. If anyone wants to clean this up
574 * please have at it, but this works. 'NE' files will
575 * eventually fade away. JRR
577 byte_count = printing_read_data(fsp, buf, VS_NE_BUF_SIZE);
578 while (byte_count > 0) {
580 * Cover case that should not occur in a well
581 * formed 'NE' .dll file
583 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
587 for(i=0; i<byte_count; i++) {
589 * Fast skip past data that can't
593 byte_count = printing_read_data(fsp,
600 * Potential match data crosses buf boundry,
601 * move it to beginning of buf, and fill the
602 * buf with as much as it will hold.
604 if (i>byte_count-VS_VERSION_INFO_SIZE) {
606 ssize_t amount_unused = byte_count-i;
608 memmove(buf, &buf[i], amount_unused);
609 amount_read = printing_read_data(fsp,
611 VS_NE_BUF_SIZE- amount_unused);
612 if (amount_read < 0) {
613 DBG_ERR("NE file [%s] Read "
620 if (amount_read + amount_unused <
622 /* Check for integer wrap. */
626 byte_count = amount_read +
628 if (byte_count < VS_VERSION_INFO_SIZE) {
636 * Check that the full signature string and
637 * the magic number that follows exist (not
638 * a perfect solution, but the chances that this
639 * occurs in code is, well, remote. Yes I know
640 * I'm comparing the 'V' twice, as it is
641 * simpler to read the code.
643 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
645 * Compute skip alignment to next
648 off_t cpos = SMB_VFS_LSEEK(fsp,
652 int skip = -(cpos - (byte_count - i) +
653 sizeof(VS_SIGNATURE)) & 3;
655 i+sizeof(VS_SIGNATURE)+skip)
657 byte_count = printing_read_data(fsp,
664 i+sizeof(VS_SIGNATURE)+
665 skip+VS_MAJOR_OFFSET);
667 i+sizeof(VS_SIGNATURE)+
668 skip+VS_MINOR_OFFSET);
669 DBG_INFO("NE file [%s] Version "
670 "= %08x:%08x (%d.%d.%d.%d)\n",
684 /* Version info not found, fall back to origin date/time */
685 DBG_ERR("NE file [%s] Version info not found\n", fname);
694 /****************************************************************************
695 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
696 There are two case to be covered here: PE (Portable Executable) and NE (New
697 Executable) files. Both files support the same INFO structure, but PE files
698 store the signature in unicode, and NE files store it as !unicode.
699 returns -1 on error, 1 on version info found, and 0 on no version info found.
700 ****************************************************************************/
702 static int get_file_version(files_struct *fsp,
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_read_data(fsp, buf, 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 pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
741 oret = SMB_VFS_LSEEK(fsp, pos, SEEK_SET);
742 if (oret == (off_t)-1) {
743 DBG_NOTICE("File [%s] too short, errno = %d\n",
747 * Assume this isn't an error...
748 * the file just looks sort of like a PE/NE file.
750 goto no_version_info;
752 pos = oret; /* Update new position. */
754 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
755 byte_count = printing_read_data(fsp, buf, NE_HEADER_SIZE);
756 if (byte_count < NE_HEADER_SIZE) {
757 DBG_NOTICE("File [%s] Windows header too short, "
758 "bytes read = %lu\n",
760 (unsigned long)byte_count);
762 * Assume this isn't an error...
763 * the file just looks sort of like a PE/NE file
765 goto no_version_info;
769 * The header may be a PE (Portable Executable)
770 * or an NE (New Executable).
772 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
773 return handle_pe_file(fsp,
778 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
779 NE_HEADER_SIGNATURE) {
780 return handle_ne_file(fsp,
787 * Assume this isn't an error... the file just
788 * looks sort of like a PE/NE file.
790 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
792 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
793 /* Fallthrough into no_version_info: */
805 /****************************************************************************
806 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
807 share one or more files. During the MS installation process files are checked
808 to insure that only a newer version of a shared file is installed over an
809 older version. There are several possibilities for this comparison. If there
810 is no previous version, the new one is newer (obviously). If either file is
811 missing the version info structure, compare the creation date (on Unix use
812 the modification date). Otherwise chose the numerically larger version number.
813 ****************************************************************************/
815 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
817 bool use_version = true;
821 time_t new_create_time;
825 time_t old_create_time;
827 struct smb_filename *smb_fname = NULL;
828 files_struct *fsp = NULL;
834 SET_STAT_INVALID(st);
835 new_create_time = (time_t)0;
836 old_create_time = (time_t)0;
838 /* Get file version info (if available) for previous file (if it exists) */
839 status = driver_unix_convert(conn, old_file, &smb_fname);
840 if (!NT_STATUS_IS_OK(status)) {
844 status = SMB_VFS_CREATE_FILE(
847 0, /* root_dir_fid */
848 smb_fname, /* fname */
849 FILE_GENERIC_READ, /* access_mask */
850 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
851 FILE_OPEN, /* create_disposition*/
852 0, /* create_options */
853 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
854 INTERNAL_OPEN_ONLY, /* oplock_request */
856 0, /* allocation_size */
857 0, /* private_flags */
862 NULL, NULL); /* create context */
864 if (!NT_STATUS_IS_OK(status)) {
865 /* Old file not found, so by definition new file is in fact newer */
866 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
867 "errno = %d\n", smb_fname_str_dbg(smb_fname),
873 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
879 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
882 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
885 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
886 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
887 (long)old_create_time));
890 close_file(NULL, fsp, NORMAL_CLOSE);
893 /* Get file version info (if available) for new file */
894 status = driver_unix_convert(conn, new_file, &smb_fname);
895 if (!NT_STATUS_IS_OK(status)) {
899 status = SMB_VFS_CREATE_FILE(
902 0, /* root_dir_fid */
903 smb_fname, /* fname */
904 FILE_GENERIC_READ, /* access_mask */
905 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
906 FILE_OPEN, /* create_disposition*/
907 0, /* create_options */
908 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
909 INTERNAL_OPEN_ONLY, /* oplock_request */
911 0, /* allocation_size */
912 0, /* private_flags */
917 NULL, NULL); /* create context */
919 if (!NT_STATUS_IS_OK(status)) {
920 /* New file not found, this shouldn't occur if the caller did its job */
921 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
922 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
926 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
932 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
935 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
938 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
939 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
940 (long)new_create_time));
943 close_file(NULL, fsp, NORMAL_CLOSE);
946 if (use_version && (new_major != old_major || new_minor != old_minor)) {
947 /* Compare versions and choose the larger version number */
948 if (new_major > old_major ||
949 (new_major == old_major && new_minor > old_minor)) {
951 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
956 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
962 /* Compare modification time/dates and choose the newest time/date */
963 if (new_create_time > old_create_time) {
964 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
969 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
977 close_file(NULL, fsp, NORMAL_CLOSE);
980 TALLOC_FREE(smb_fname);
984 /****************************************************************************
985 Determine the correct cVersion associated with an architecture and driver
986 ****************************************************************************/
987 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
988 const char *architecture,
989 const char *driverpath_in,
990 const char *driver_directory,
995 struct smb_filename *smb_fname = NULL;
996 files_struct *fsp = NULL;
997 connection_struct *conn = NULL;
998 struct smb_filename *oldcwd_fname = NULL;
999 char *printdollar = NULL;
1000 char *printdollar_path = NULL;
1001 char *working_dir = NULL;
1002 int printdollar_snum;
1004 *perr = WERR_INVALID_PARAMETER;
1006 /* If architecture is Windows 95/98/ME, the version is always 0. */
1007 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1008 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1013 /* If architecture is Windows x64, the version is always 3. */
1014 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1015 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1020 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1022 *perr = WERR_NOT_ENOUGH_MEMORY;
1025 if (printdollar_snum == -1) {
1026 *perr = WERR_BAD_NET_NAME;
1030 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
1031 if (printdollar_path == NULL) {
1032 *perr = WERR_NOT_ENOUGH_MEMORY;
1036 working_dir = talloc_asprintf(talloc_tos(),
1041 * If the driver has been uploaded into a temorpary driver
1042 * directory, switch to the driver directory.
1044 if (driver_directory != NULL) {
1045 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
1051 nt_status = create_conn_struct_cwd(talloc_tos(),
1052 server_event_context(),
1053 server_messaging_context(),
1057 session_info, &oldcwd_fname);
1058 if (!NT_STATUS_IS_OK(nt_status)) {
1059 DEBUG(0,("get_correct_cversion: create_conn_struct "
1060 "returned %s\n", nt_errstr(nt_status)));
1061 *perr = ntstatus_to_werror(nt_status);
1065 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1066 if (!NT_STATUS_IS_OK(nt_status)) {
1067 DEBUG(0, ("failed set force user / group\n"));
1068 *perr = ntstatus_to_werror(nt_status);
1069 goto error_free_conn;
1072 if (!become_user_by_session(conn, session_info)) {
1073 DEBUG(0, ("failed to become user\n"));
1074 *perr = WERR_ACCESS_DENIED;
1075 goto error_free_conn;
1079 * We switch to the directory where the driver files are located,
1080 * so only work on the file names
1082 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1083 if (!NT_STATUS_IS_OK(nt_status)) {
1084 *perr = ntstatus_to_werror(nt_status);
1088 nt_status = vfs_file_exist(conn, smb_fname);
1089 if (!NT_STATUS_IS_OK(nt_status)) {
1090 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1091 *perr = WERR_FILE_NOT_FOUND;
1095 nt_status = SMB_VFS_CREATE_FILE(
1098 0, /* root_dir_fid */
1099 smb_fname, /* fname */
1100 FILE_GENERIC_READ, /* access_mask */
1101 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1102 FILE_OPEN, /* create_disposition*/
1103 0, /* create_options */
1104 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1105 INTERNAL_OPEN_ONLY, /* oplock_request */
1107 0, /* private_flags */
1108 0, /* allocation_size */
1113 NULL, NULL); /* create context */
1115 if (!NT_STATUS_IS_OK(nt_status)) {
1116 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1117 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1118 *perr = WERR_ACCESS_DENIED;
1125 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1127 *perr = WERR_INVALID_PARAMETER;
1130 DEBUG(6,("get_correct_cversion: Version info not "
1132 smb_fname_str_dbg(smb_fname)));
1133 *perr = WERR_INVALID_PARAMETER;
1138 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1139 * for more details. Version in this case is not just the version of the
1140 * file, but the version in the sense of kernal mode (2) vs. user mode
1141 * (3) drivers. Other bits of the version fields are the version info.
1144 cversion = major & 0x0000ffff;
1146 case 2: /* WinNT drivers */
1147 case 3: /* Win2K drivers */
1151 DEBUG(6,("get_correct_cversion: cversion "
1152 "invalid [%s] cversion = %d\n",
1153 smb_fname_str_dbg(smb_fname),
1158 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1159 " = 0x%x minor = 0x%x\n",
1160 smb_fname_str_dbg(smb_fname), major, minor));
1163 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1164 smb_fname_str_dbg(smb_fname), cversion));
1170 TALLOC_FREE(smb_fname);
1172 close_file(NULL, fsp, NORMAL_CLOSE);
1175 vfs_ChDir(conn, oldcwd_fname);
1176 TALLOC_FREE(oldcwd_fname);
1177 SMB_VFS_DISCONNECT(conn);
1180 if (!W_ERROR_IS_OK(*perr)) {
1187 /****************************************************************************
1188 ****************************************************************************/
1190 #define strip_driver_path(_mem_ctx, _element) do { \
1191 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1192 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1193 W_ERROR_HAVE_NO_MEMORY((_element)); \
1197 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1198 struct auth_session_info *session_info,
1199 const char *architecture,
1200 const char **driver_path,
1201 const char **data_file,
1202 const char **config_file,
1203 const char **help_file,
1204 struct spoolss_StringArray *dependent_files,
1205 enum spoolss_DriverOSVersion *version,
1207 const char **driver_directory)
1209 const char *short_architecture;
1214 if (!*driver_path || !*data_file) {
1215 return WERR_INVALID_PARAMETER;
1218 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1219 return WERR_INVALID_PARAMETER;
1222 if (flags & APD_COPY_FROM_DIRECTORY) {
1227 * driver_path is set to:
1229 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1231 path = talloc_strdup(mem_ctx, *driver_path);
1233 return WERR_NOT_ENOUGH_MEMORY;
1236 /* Remove pscript5.dll */
1237 q = strrchr_m(path, '\\');
1239 return WERR_INVALID_PARAMETER;
1243 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1244 q = strrchr_m(path, '\\');
1246 return WERR_INVALID_PARAMETER;
1250 * Set driver_directory to:
1252 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1254 * This is the directory where all the files have been uploaded
1256 *driver_directory = q + 1;
1259 /* clean up the driver name.
1260 * we can get .\driver.dll
1261 * or worse c:\windows\system\driver.dll !
1263 /* using an intermediate string to not have overlaping memcpy()'s */
1265 strip_driver_path(mem_ctx, *driver_path);
1266 strip_driver_path(mem_ctx, *data_file);
1268 strip_driver_path(mem_ctx, *config_file);
1271 strip_driver_path(mem_ctx, *help_file);
1274 if (dependent_files && dependent_files->string) {
1275 for (i=0; dependent_files->string[i]; i++) {
1276 strip_driver_path(mem_ctx, dependent_files->string[i]);
1280 short_architecture = get_short_archi(architecture);
1281 if (!short_architecture) {
1282 return WERR_UNKNOWN_PRINTER_DRIVER;
1285 /* jfm:7/16/2000 the client always sends the cversion=0.
1286 * The server should check which version the driver is by reading
1287 * the PE header of driver->driverpath.
1289 * For Windows 95/98 the version is 0 (so the value sent is correct)
1290 * For Windows NT (the architecture doesn't matter)
1291 * NT 3.1: cversion=0
1292 * NT 3.5/3.51: cversion=1
1297 *version = get_correct_cversion(session_info,
1302 if (*version == -1) {
1309 /****************************************************************************
1310 ****************************************************************************/
1312 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1313 struct auth_session_info *session_info,
1314 struct spoolss_AddDriverInfoCtr *r,
1316 const char **driver_directory)
1320 return clean_up_driver_struct_level(mem_ctx, session_info,
1321 r->info.info3->architecture,
1322 &r->info.info3->driver_path,
1323 &r->info.info3->data_file,
1324 &r->info.info3->config_file,
1325 &r->info.info3->help_file,
1326 r->info.info3->dependent_files,
1327 &r->info.info3->version,
1331 return clean_up_driver_struct_level(mem_ctx, session_info,
1332 r->info.info6->architecture,
1333 &r->info.info6->driver_path,
1334 &r->info.info6->data_file,
1335 &r->info.info6->config_file,
1336 &r->info.info6->help_file,
1337 r->info.info6->dependent_files,
1338 &r->info.info6->version,
1342 return clean_up_driver_struct_level(mem_ctx, session_info,
1343 r->info.info8->architecture,
1344 &r->info.info8->driver_path,
1345 &r->info.info8->data_file,
1346 &r->info.info8->config_file,
1347 &r->info.info8->help_file,
1348 r->info.info8->dependent_files,
1349 &r->info.info8->version,
1353 return WERR_NOT_SUPPORTED;
1357 /****************************************************************************
1358 This function sucks and should be replaced. JRA.
1359 ****************************************************************************/
1361 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1362 const struct spoolss_AddDriverInfo6 *src)
1364 dst->version = src->version;
1366 dst->driver_name = src->driver_name;
1367 dst->architecture = src->architecture;
1368 dst->driver_path = src->driver_path;
1369 dst->data_file = src->data_file;
1370 dst->config_file = src->config_file;
1371 dst->help_file = src->help_file;
1372 dst->monitor_name = src->monitor_name;
1373 dst->default_datatype = src->default_datatype;
1374 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1375 dst->dependent_files = src->dependent_files;
1378 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1379 const struct spoolss_AddDriverInfo8 *src)
1381 dst->version = src->version;
1383 dst->driver_name = src->driver_name;
1384 dst->architecture = src->architecture;
1385 dst->driver_path = src->driver_path;
1386 dst->data_file = src->data_file;
1387 dst->config_file = src->config_file;
1388 dst->help_file = src->help_file;
1389 dst->monitor_name = src->monitor_name;
1390 dst->default_datatype = src->default_datatype;
1391 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1392 dst->dependent_files = src->dependent_files;
1395 /****************************************************************************
1396 ****************************************************************************/
1398 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1399 connection_struct *conn,
1400 const char *driver_file,
1401 const char *short_architecture,
1402 uint32_t driver_version,
1404 const char *driver_directory)
1406 struct smb_filename *smb_fname_old = NULL;
1407 struct smb_filename *smb_fname_new = NULL;
1408 char *old_name = NULL;
1409 char *new_name = NULL;
1413 if (driver_directory != NULL) {
1414 old_name = talloc_asprintf(mem_ctx,
1420 old_name = talloc_asprintf(mem_ctx,
1425 if (old_name == NULL) {
1426 return WERR_NOT_ENOUGH_MEMORY;
1429 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1430 short_architecture, driver_version, driver_file);
1431 if (new_name == NULL) {
1432 TALLOC_FREE(old_name);
1433 return WERR_NOT_ENOUGH_MEMORY;
1436 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1438 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 ret = WERR_NOT_ENOUGH_MEMORY;
1444 /* Setup a synthetic smb_filename struct */
1445 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1446 if (!smb_fname_new) {
1447 ret = WERR_NOT_ENOUGH_MEMORY;
1451 smb_fname_new->base_name = new_name;
1453 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1454 "'%s'\n", smb_fname_old->base_name,
1455 smb_fname_new->base_name));
1457 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1458 OPENX_FILE_EXISTS_TRUNCATE |
1459 OPENX_FILE_CREATE_IF_NOT_EXIST,
1462 if (!NT_STATUS_IS_OK(status)) {
1463 DEBUG(0,("move_driver_file_to_download_area: Unable "
1464 "to rename [%s] to [%s]: %s\n",
1465 smb_fname_old->base_name, new_name,
1466 nt_errstr(status)));
1467 ret = WERR_APP_INIT_FAILURE;
1474 TALLOC_FREE(smb_fname_old);
1475 TALLOC_FREE(smb_fname_new);
1479 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1480 struct spoolss_AddDriverInfoCtr *r,
1481 const char *driver_directory)
1483 struct spoolss_AddDriverInfo3 *driver;
1484 struct spoolss_AddDriverInfo3 converted_driver;
1485 const char *short_architecture;
1486 struct smb_filename *smb_dname = NULL;
1487 char *new_dir = NULL;
1488 connection_struct *conn = NULL;
1491 TALLOC_CTX *ctx = talloc_tos();
1493 struct smb_filename *oldcwd_fname = NULL;
1494 char *printdollar = NULL;
1495 int printdollar_snum;
1496 WERROR err = WERR_OK;
1500 driver = r->info.info3;
1503 convert_level_6_to_level3(&converted_driver, r->info.info6);
1504 driver = &converted_driver;
1507 convert_level_8_to_level3(&converted_driver, r->info.info8);
1508 driver = &converted_driver;
1511 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1512 return WERR_INVALID_LEVEL;
1515 short_architecture = get_short_archi(driver->architecture);
1516 if (!short_architecture) {
1517 return WERR_UNKNOWN_PRINTER_DRIVER;
1520 printdollar_snum = find_service(ctx, "print$", &printdollar);
1522 return WERR_NOT_ENOUGH_MEMORY;
1524 if (printdollar_snum == -1) {
1525 return WERR_BAD_NET_NAME;
1528 nt_status = create_conn_struct_cwd(talloc_tos(),
1529 server_event_context(),
1530 server_messaging_context(),
1533 lp_path(talloc_tos(), printdollar_snum),
1534 session_info, &oldcwd_fname);
1535 if (!NT_STATUS_IS_OK(nt_status)) {
1536 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1537 "returned %s\n", nt_errstr(nt_status)));
1538 err = ntstatus_to_werror(nt_status);
1542 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1543 if (!NT_STATUS_IS_OK(nt_status)) {
1544 DEBUG(0, ("failed set force user / group\n"));
1545 err = ntstatus_to_werror(nt_status);
1549 if (!become_user_by_session(conn, session_info)) {
1550 DEBUG(0, ("failed to become user\n"));
1551 err = WERR_ACCESS_DENIED;
1555 new_dir = talloc_asprintf(ctx,
1560 err = WERR_NOT_ENOUGH_MEMORY;
1563 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1564 if (!NT_STATUS_IS_OK(nt_status)) {
1565 err = WERR_NOT_ENOUGH_MEMORY;
1569 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1571 nt_status = create_directory(conn, NULL, smb_dname);
1572 if (!NT_STATUS_IS_OK(nt_status)
1573 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1574 DEBUG(0, ("failed to create driver destination directory: %s\n",
1575 nt_errstr(nt_status)));
1576 err = ntstatus_to_werror(nt_status);
1580 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1581 * listed for this driver which has already been moved, skip it (note:
1582 * drivers may list the same file name several times. Then check if the
1583 * file already exists in archi\version\, if so, check that the version
1584 * info (or time stamps if version info is unavailable) is newer (or the
1585 * date is later). If it is, move it to archi\version\filexxx.yyy.
1586 * Otherwise, delete the file.
1588 * If a file is not moved to archi\version\ because of an error, all the
1589 * rest of the 'unmoved' driver files are removed from archi\. If one or
1590 * more of the driver's files was already moved to archi\version\, it
1591 * potentially leaves the driver in a partially updated state. Version
1592 * trauma will most likely occur if an client attempts to use any printer
1593 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1594 * done is appropriate... later JRR
1597 DEBUG(5,("Moving files now !\n"));
1599 if (driver->driver_path && strlen(driver->driver_path)) {
1601 err = move_driver_file_to_download_area(ctx,
1603 driver->driver_path,
1608 if (!W_ERROR_IS_OK(err)) {
1613 if (driver->data_file && strlen(driver->data_file)) {
1614 if (!strequal(driver->data_file, driver->driver_path)) {
1616 err = move_driver_file_to_download_area(ctx,
1623 if (!W_ERROR_IS_OK(err)) {
1629 if (driver->config_file && strlen(driver->config_file)) {
1630 if (!strequal(driver->config_file, driver->driver_path) &&
1631 !strequal(driver->config_file, driver->data_file)) {
1633 err = move_driver_file_to_download_area(ctx,
1635 driver->config_file,
1640 if (!W_ERROR_IS_OK(err)) {
1646 if (driver->help_file && strlen(driver->help_file)) {
1647 if (!strequal(driver->help_file, driver->driver_path) &&
1648 !strequal(driver->help_file, driver->data_file) &&
1649 !strequal(driver->help_file, driver->config_file)) {
1651 err = move_driver_file_to_download_area(ctx,
1658 if (!W_ERROR_IS_OK(err)) {
1664 if (driver->dependent_files && driver->dependent_files->string) {
1665 for (i=0; driver->dependent_files->string[i]; i++) {
1666 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1667 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1668 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1669 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1671 for (j=0; j < i; j++) {
1672 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1677 err = move_driver_file_to_download_area(ctx,
1679 driver->dependent_files->string[i],
1684 if (!W_ERROR_IS_OK(err)) {
1696 TALLOC_FREE(smb_dname);
1699 vfs_ChDir(conn, oldcwd_fname);
1700 TALLOC_FREE(oldcwd_fname);
1701 SMB_VFS_DISCONNECT(conn);
1708 /****************************************************************************
1709 Determine whether or not a particular driver is currently assigned
1711 ****************************************************************************/
1713 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1714 struct dcerpc_binding_handle *b,
1715 const struct spoolss_DriverInfo8 *r)
1718 int n_services = lp_numservices();
1719 bool in_use = false;
1720 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1727 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1729 /* loop through the printers.tdb and check for the drivername */
1731 for (snum=0; snum<n_services && !in_use; snum++) {
1732 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1736 result = winreg_get_printer(mem_ctx, b,
1737 lp_servicename(talloc_tos(), snum),
1739 if (!W_ERROR_IS_OK(result)) {
1740 continue; /* skip */
1743 if (strequal(r->driver_name, pinfo2->drivername)) {
1747 TALLOC_FREE(pinfo2);
1750 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1753 struct spoolss_DriverInfo8 *driver = NULL;
1756 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1758 /* we can still remove the driver if there is one of
1759 "Windows NT x86" version 2 or 3 left */
1761 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1762 if (r->version == 2) {
1763 werr = winreg_get_driver(mem_ctx, b,
1767 } else if (r->version == 3) {
1768 werr = winreg_get_driver(mem_ctx, b,
1773 DBG_ERR("Unknown driver version (%d)\n",
1775 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1777 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1778 werr = winreg_get_driver(mem_ctx, b,
1779 SPOOLSS_ARCHITECTURE_NT_X86,
1784 DBG_ERR("Unknown driver architecture: %s\n",
1786 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1789 /* now check the error code */
1791 if ( W_ERROR_IS_OK(werr) ) {
1792 /* it's ok to remove the driver, we have other architctures left */
1794 talloc_free(driver);
1798 /* report that the driver is not in use by default */
1804 /**********************************************************************
1805 Check to see if a ogiven file is in use by *info
1806 *********************************************************************/
1808 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1815 /* mz: skip files that are in the list but already deleted */
1816 if (!file || !file[0]) {
1820 if (strequal(file, info->driver_path))
1823 if (strequal(file, info->data_file))
1826 if (strequal(file, info->config_file))
1829 if (strequal(file, info->help_file))
1832 /* see of there are any dependent files to examine */
1834 if (!info->dependent_files)
1837 while (info->dependent_files[i] && *info->dependent_files[i]) {
1838 if (strequal(file, info->dependent_files[i]))
1847 /**********************************************************************
1848 Utility function to remove the dependent file pointed to by the
1849 input parameter from the list
1850 *********************************************************************/
1852 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1855 /* bump everything down a slot */
1857 while (files && files[idx+1]) {
1858 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1867 /**********************************************************************
1868 Check if any of the files used by src are also used by drv
1869 *********************************************************************/
1871 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1872 struct spoolss_DriverInfo8 *src,
1873 const struct spoolss_DriverInfo8 *drv)
1875 bool in_use = False;
1881 /* check each file. Remove it from the src structure if it overlaps */
1883 if (drv_file_in_use(src->driver_path, drv)) {
1885 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1886 src->driver_path = talloc_strdup(mem_ctx, "");
1887 if (!src->driver_path) { return false; }
1890 if (drv_file_in_use(src->data_file, drv)) {
1892 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1893 src->data_file = talloc_strdup(mem_ctx, "");
1894 if (!src->data_file) { return false; }
1897 if (drv_file_in_use(src->config_file, drv)) {
1899 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1900 src->config_file = talloc_strdup(mem_ctx, "");
1901 if (!src->config_file) { return false; }
1904 if (drv_file_in_use(src->help_file, drv)) {
1906 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1907 src->help_file = talloc_strdup(mem_ctx, "");
1908 if (!src->help_file) { return false; }
1911 /* are there any dependentfiles to examine? */
1913 if (!src->dependent_files)
1916 while (src->dependent_files[i] && *src->dependent_files[i]) {
1917 if (drv_file_in_use(src->dependent_files[i], drv)) {
1919 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1920 trim_dependent_file(mem_ctx, src->dependent_files, i);
1928 /****************************************************************************
1929 Determine whether or not a particular driver files are currently being
1930 used by any other driver.
1932 Return value is True if any files were in use by other drivers
1933 and False otherwise.
1935 Upon return, *info has been modified to only contain the driver files
1936 which are not in use
1940 This needs to check all drivers to ensure that all files in use
1941 have been removed from *info, not just the ones in the first
1943 ****************************************************************************/
1945 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1946 struct dcerpc_binding_handle *b,
1947 struct spoolss_DriverInfo8 *info)
1951 struct spoolss_DriverInfo8 *driver;
1952 bool in_use = false;
1953 uint32_t num_drivers;
1954 const char **drivers;
1960 version = info->version;
1962 /* loop over all driver versions */
1964 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1966 /* get the list of drivers */
1968 result = winreg_get_driver_list(mem_ctx, b,
1969 info->architecture, version,
1970 &num_drivers, &drivers);
1971 if (!W_ERROR_IS_OK(result)) {
1975 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1976 num_drivers, info->architecture, version));
1978 /* check each driver for overlap in files */
1980 for (i = 0; i < num_drivers; i++) {
1981 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1985 result = winreg_get_driver(mem_ctx, b,
1986 info->architecture, drivers[i],
1988 if (!W_ERROR_IS_OK(result)) {
1989 talloc_free(drivers);
1993 /* check if d2 uses any files from d1 */
1994 /* only if this is a different driver than the one being deleted */
1996 if (!strequal(info->driver_name, driver->driver_name)) {
1997 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1998 /* mz: Do not instantly return -
1999 * we need to ensure this file isn't
2000 * also in use by other drivers. */
2005 talloc_free(driver);
2008 talloc_free(drivers);
2010 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2015 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2016 const char *short_arch,
2020 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2021 struct smb_filename *smb_fname = NULL;
2022 char *print_dlr_path;
2023 NTSTATUS status = NT_STATUS_NO_MEMORY;
2025 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2026 short_arch, vers, fname);
2027 if (print_dlr_path == NULL) {
2031 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2032 if (smb_fname == NULL) {
2036 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2038 talloc_free(tmp_ctx);
2042 /****************************************************************************
2043 Actually delete the driver files. Make sure that
2044 printer_driver_files_in_use() return False before calling
2046 ****************************************************************************/
2048 bool delete_driver_files(const struct auth_session_info *session_info,
2049 const struct spoolss_DriverInfo8 *r)
2051 const char *short_arch;
2052 connection_struct *conn;
2054 struct smb_filename *oldcwd_fname = NULL;
2055 char *printdollar = NULL;
2056 int printdollar_snum;
2063 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2064 r->driver_name, r->version));
2066 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2070 if (printdollar_snum == -1) {
2074 nt_status = create_conn_struct_cwd(talloc_tos(),
2075 server_event_context(),
2076 server_messaging_context(),
2079 lp_path(talloc_tos(), printdollar_snum),
2080 session_info, &oldcwd_fname);
2081 if (!NT_STATUS_IS_OK(nt_status)) {
2082 DEBUG(0,("delete_driver_files: create_conn_struct "
2083 "returned %s\n", nt_errstr(nt_status)));
2087 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2088 if (!NT_STATUS_IS_OK(nt_status)) {
2089 DEBUG(0, ("failed set force user / group\n"));
2094 if (!become_user_by_session(conn, session_info)) {
2095 DEBUG(0, ("failed to become user\n"));
2100 if ( !CAN_WRITE(conn) ) {
2101 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2106 short_arch = get_short_archi(r->architecture);
2107 if (short_arch == NULL) {
2108 DEBUG(0, ("bad architecture %s\n", r->architecture));
2113 /* now delete the files */
2115 if (r->driver_path && r->driver_path[0]) {
2116 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2117 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2120 if (r->config_file && r->config_file[0]) {
2121 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2122 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2125 if (r->data_file && r->data_file[0]) {
2126 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2127 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2130 if (r->help_file && r->help_file[0]) {
2131 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2132 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2135 if (r->dependent_files) {
2137 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2138 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2139 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2149 vfs_ChDir(conn, oldcwd_fname);
2150 TALLOC_FREE(oldcwd_fname);
2151 SMB_VFS_DISCONNECT(conn);
2159 1: level not implemented
2160 2: file doesn't exist
2161 3: can't allocate memory
2162 4: can't free memory
2163 5: non existent struct
2167 A printer and a printer driver are 2 different things.
2168 NT manages them separatelly, Samba does the same.
2169 Why ? Simply because it's easier and it makes sense !
2171 Now explanation: You have 3 printers behind your samba server,
2172 2 of them are the same make and model (laser A and B). But laser B
2173 has an 3000 sheet feeder and laser A doesn't such an option.
2174 Your third printer is an old dot-matrix model for the accounting :-).
2176 If the /usr/local/samba/lib directory (default dir), you will have
2177 5 files to describe all of this.
2179 3 files for the printers (1 by printer):
2182 NTprinter_accounting
2183 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2184 NTdriver_printer model X
2185 NTdriver_printer model Y
2187 jfm: I should use this comment for the text file to explain
2188 same thing for the forms BTW.
2189 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2193 /* Convert generic access rights to printer object specific access rights.
2194 It turns out that NT4 security descriptors use generic access rights and
2195 NT5 the object specific ones. */
2197 void map_printer_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 &printer_generic_mapping);
2207 void map_job_permissions(struct security_descriptor *sd)
2211 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2212 se_map_generic(&sd->dacl->aces[i].access_mask,
2213 &job_generic_mapping);
2218 /****************************************************************************
2219 Check a user has permissions to perform the given operation. We use the
2220 permission constants defined in include/rpc_spoolss.h to check the various
2221 actions we perform when checking printer access.
2223 PRINTER_ACCESS_ADMINISTER:
2224 print_queue_pause, print_queue_resume, update_printer_sec,
2225 update_printer, spoolss_addprinterex_level_2,
2226 _spoolss_setprinterdata
2231 JOB_ACCESS_ADMINISTER:
2232 print_job_delete, print_job_pause, print_job_resume,
2235 Try access control in the following order (for performance reasons):
2236 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2237 2) check security descriptor (bit comparisons in memory)
2238 3) "printer admins" (may result in numerous calls to winbind)
2240 ****************************************************************************/
2241 WERROR print_access_check(const struct auth_session_info *session_info,
2242 struct messaging_context *msg_ctx, int snum,
2245 struct spoolss_security_descriptor *secdesc = NULL;
2246 uint32_t access_granted;
2251 TALLOC_CTX *mem_ctx = NULL;
2253 /* If user is NULL then use the current_user structure */
2255 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2257 if ((session_info->unix_token->uid == sec_initial_uid())
2258 || security_token_has_privilege(session_info->security_token,
2259 SEC_PRIV_PRINT_OPERATOR)) {
2263 /* Get printer name */
2265 pname = lp_printername(talloc_tos(), snum);
2267 if (!pname || !*pname) {
2268 return WERR_ACCESS_DENIED;
2271 /* Get printer security descriptor */
2273 if(!(mem_ctx = talloc_init("print_access_check"))) {
2274 return WERR_NOT_ENOUGH_MEMORY;
2277 result = winreg_get_printer_secdesc_internal(mem_ctx,
2278 get_session_info_system(),
2282 if (!W_ERROR_IS_OK(result)) {
2283 talloc_destroy(mem_ctx);
2284 return WERR_NOT_ENOUGH_MEMORY;
2287 if (access_type == JOB_ACCESS_ADMINISTER) {
2288 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2290 /* Create a child security descriptor to check permissions
2291 against. This is because print jobs are child objects
2292 objects of a printer. */
2293 status = se_create_child_secdesc(mem_ctx,
2297 parent_secdesc->owner_sid,
2298 parent_secdesc->group_sid,
2300 if (!NT_STATUS_IS_OK(status)) {
2301 talloc_destroy(mem_ctx);
2302 return ntstatus_to_werror(status);
2305 map_job_permissions(secdesc);
2307 map_printer_permissions(secdesc);
2311 status = se_access_check(secdesc, session_info->security_token, access_type,
2314 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2316 talloc_destroy(mem_ctx);
2318 return ntstatus_to_werror(status);
2321 /****************************************************************************
2322 Check the time parameters allow a print operation.
2323 *****************************************************************************/
2325 bool print_time_access_check(const struct auth_session_info *session_info,
2326 struct messaging_context *msg_ctx,
2327 const char *servicename)
2329 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2332 time_t now = time(NULL);
2336 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2337 servicename, &pinfo2);
2338 if (!W_ERROR_IS_OK(result)) {
2342 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2347 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2349 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2353 TALLOC_FREE(pinfo2);
2362 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2363 const struct auth_session_info *session_info,
2364 struct messaging_context *msg_ctx,
2365 const char *printer)
2369 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2371 if (!W_ERROR_IS_OK(result)) {
2372 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2373 "%s\n", printer, win_errstr(result)));
2377 void nt_printer_add(TALLOC_CTX *mem_ctx,
2378 const struct auth_session_info *session_info,
2379 struct messaging_context *msg_ctx,
2380 const char *printer)
2384 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2386 if (!W_ERROR_IS_OK(result)) {
2387 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2388 printer, win_errstr(result)));