2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "printing/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.h"
38 /* Map generic permissions to printer object specific permissions */
40 const struct generic_mapping printer_generic_mapping = {
47 /* Map generic permissions to print server object specific permissions */
49 const struct generic_mapping printserver_generic_mapping = {
56 /* Map generic permissions to job object specific permissions */
58 const struct generic_mapping job_generic_mapping = {
65 static const struct print_architecture_table_node archi_table[]= {
67 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
68 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
69 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
70 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
71 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
72 {"Windows IA64", SPL_ARCH_IA64, 3 },
73 {"Windows x64", SPL_ARCH_X64, 3 },
77 static bool print_driver_directories_init(void)
82 TALLOC_CTX *mem_ctx = talloc_stackframe();
83 const char *dir_list[] = {
89 service = lp_servicenumber("print$");
91 /* We don't have a print$ share */
92 DEBUG(5, ("No print$ share has been configured.\n"));
97 driver_path = lp_path(mem_ctx, service);
98 if (driver_path == NULL) {
103 ok = directory_create_or_exist(driver_path, 0755);
105 DEBUG(1, ("Failed to create printer driver directory %s\n",
107 talloc_free(mem_ctx);
111 for (i = 0; archi_table[i].long_archi != NULL; i++) {
112 const char *arch_path;
114 arch_path = talloc_asprintf(mem_ctx,
117 archi_table[i].short_archi);
118 if (arch_path == NULL) {
119 talloc_free(mem_ctx);
123 ok = directory_create_or_exist(arch_path, 0755);
125 DEBUG(1, ("Failed to create printer driver "
126 "architecture directory %s\n",
128 talloc_free(mem_ctx);
133 for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
136 path = talloc_asprintf(mem_ctx,
141 talloc_free(mem_ctx);
145 ok = directory_create_or_exist(path, 0755);
147 DEBUG(1, ("Failed to create printer driver "
148 "architecture directory %s\n",
150 talloc_free(mem_ctx);
155 driver_path = state_path("DriverStore");
156 if (driver_path == NULL) {
157 talloc_free(mem_ctx);
161 ok = directory_create_or_exist(driver_path, 0755);
163 DEBUG(1,("failed to create path %s\n", driver_path));
164 talloc_free(mem_ctx);
168 driver_path = state_path("DriverStore/FileRepository");
169 if (driver_path == NULL) {
170 talloc_free(mem_ctx);
174 ok = directory_create_or_exist(driver_path, 0755);
176 DEBUG(1,("failed to create path %s\n", driver_path));
177 talloc_free(mem_ctx);
181 driver_path = state_path("DriverStore/Temp");
182 if (driver_path == NULL) {
183 talloc_free(mem_ctx);
187 ok = directory_create_or_exist(driver_path, 0755);
189 DEBUG(1,("failed to create path %s\n", driver_path));
190 talloc_free(mem_ctx);
194 talloc_free(mem_ctx);
198 /****************************************************************************
199 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
200 background lpq updater.
201 ****************************************************************************/
203 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
206 struct server_id server_id,
209 extern pid_t background_lpq_updater_pid;
211 if (background_lpq_updater_pid == -1) {
212 DEBUG(3,("no background lpq queue updater\n"));
216 messaging_send_buf(msg,
217 pid_to_procid(background_lpq_updater_pid),
218 MSG_PRINTER_DRVUPGRADE,
223 /****************************************************************************
224 Open the NT printing tdbs. Done once before fork().
225 ****************************************************************************/
227 bool nt_printing_init(struct messaging_context *msg_ctx)
231 if (!print_driver_directories_init()) {
235 if (!nt_printing_tdb_upgrade()) {
240 * register callback to handle updating printers as new
241 * drivers are installed. Forwards to background lpq updater.
243 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
244 forward_drv_upgrade_printer_msg);
246 if ( lp_security() == SEC_ADS ) {
247 win_rc = check_published_printers(msg_ctx);
248 if (!W_ERROR_IS_OK(win_rc))
249 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
255 /*******************************************************************
256 Function to allow filename parsing "the old way".
257 ********************************************************************/
259 static NTSTATUS driver_unix_convert(connection_struct *conn,
260 const char *old_name,
261 struct smb_filename **smb_fname)
264 TALLOC_CTX *ctx = talloc_tos();
265 char *name = talloc_strdup(ctx, old_name);
268 return NT_STATUS_NO_MEMORY;
271 name = unix_clean_name(ctx, name);
273 return NT_STATUS_NO_MEMORY;
275 trim_string(name,"/","/");
277 status = unix_convert(ctx, conn, name, smb_fname, 0);
278 if (!NT_STATUS_IS_OK(status)) {
279 return NT_STATUS_NO_MEMORY;
285 /****************************************************************************
286 Function to do the mapping between the long architecture name and
288 ****************************************************************************/
290 const char *get_short_archi(const char *long_archi)
294 DEBUG(107,("Getting architecture dependent directory\n"));
297 } while ( (archi_table[i].long_archi!=NULL ) &&
298 strcasecmp_m(long_archi, archi_table[i].long_archi) );
300 if (archi_table[i].long_archi==NULL) {
301 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
305 /* this might be client code - but shouldn't this be an fstrcpy etc? */
307 DEBUGADD(108,("index: [%d]\n", i));
308 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
309 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
311 return archi_table[i].short_archi;
314 /****************************************************************************
315 Read data from fsp on the vfs.
316 (note: EINTR re-read differs from vfs_write_data)
317 ****************************************************************************/
319 static ssize_t printing_pread_data(files_struct *fsp,
325 off_t in_pos = *poff;
327 if (in_pos != (off_t)-1) {
328 in_pos = SMB_VFS_LSEEK(fsp, in_pos, SEEK_SET);
329 if (in_pos == (off_t)-1) {
332 /* Don't allow integer wrap on read. */
333 if (in_pos + byte_count < in_pos) {
338 while (total < byte_count) {
339 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
343 if (*poff != (off_t)-1) {
349 if (errno == EINTR) {
358 if (*poff != (off_t)-1) {
361 return (ssize_t)total;
364 /****************************************************************************
365 Detect the major and minor version of a PE file.
368 1 if file is a PE file and we got version numbers,
369 0 if this file is a PE file and we couldn't get the version numbers,
372 NB. buf is passed into and freed inside this function. This is a
373 bad API design, but fixing this is a task for another day.
374 ****************************************************************************/
376 static int handle_pe_file(files_struct *fsp,
383 unsigned int num_sections;
384 unsigned int section_table_bytes;
391 /* Just skip over optional header to get to section table */
392 pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
393 (NE_HEADER_SIZE-PE_HEADER_SIZE);
395 oret = SMB_VFS_LSEEK(fsp, pos, SEEK_CUR);
396 if (oret == (off_t)-1) {
397 DBG_NOTICE("File [%s] Windows optional header "
398 "too short, errno = %d\n",
404 /* get the section table */
405 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
406 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
407 if (section_table_bytes == 0) {
412 buf = (char *)SMB_MALLOC(section_table_bytes);
414 DBG_ERR("PE file [%s] section table malloc "
415 "failed bytes = %d\n",
417 section_table_bytes);
421 byte_count = printing_pread_data(fsp, buf, &in_pos, section_table_bytes);
422 if (byte_count < section_table_bytes) {
423 DBG_NOTICE("PE file [%s] Section header too short, "
424 "bytes read = %lu\n",
426 (unsigned long)byte_count);
431 * Iterate the section table looking for
432 * the resource section ".rsrc"
434 for (i = 0; i < num_sections; i++) {
435 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
438 &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) {
439 unsigned int section_pos = IVAL(buf,
441 PE_HEADER_SECT_PTR_DATA_OFFSET);
442 unsigned int section_bytes = IVAL(buf,
444 PE_HEADER_SECT_SIZE_DATA_OFFSET);
446 if (section_bytes == 0) {
451 buf=(char *)SMB_MALLOC(section_bytes);
453 DBG_ERR("PE file [%s] version malloc "
454 "failed bytes = %d\n",
461 * Seek to the start of the .rsrc
464 oret = SMB_VFS_LSEEK(fsp,
467 if (oret == (off_t)-1) {
468 DBG_NOTICE("PE file [%s] too short for "
469 "section info, errno = %d\n",
475 byte_count = printing_pread_data(fsp,
479 if (byte_count < section_bytes) {
480 DBG_NOTICE("PE file "
481 "[%s] .rsrc section too short, "
482 "bytes read = %lu\n",
484 (unsigned long)byte_count);
488 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) {
493 i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE;
496 * Scan for 1st 3 unicoded bytes
497 * followed by word aligned magic
501 bool magic_match = false;
509 if (magic_match == false) {
513 /* Align to next long address */
514 mpos = (i + sizeof(VS_SIGNATURE)*2 +
517 if (IVAL(buf,mpos) == VS_MAGIC_VALUE) {
519 mpos+ VS_MAJOR_OFFSET);
521 mpos+ VS_MINOR_OFFSET);
523 DBG_INFO("PE file [%s] Version = "
524 "%08x:%08x (%d.%d.%d.%d)\n",
539 /* Version info not found, fall back to origin date/time */
540 DBG_DEBUG("PE file [%s] has no version info\n", fname);
549 /****************************************************************************
550 Detect the major and minor version of an NE file.
553 1 if file is an NE file and we got version numbers,
554 0 if this file is an NE file and we couldn't get the version numbers,
557 NB. buf is passed into and freed inside this function. This is a
558 bad API design, but fixing this is a task for another day.
559 ****************************************************************************/
561 static int handle_ne_file(files_struct *fsp,
572 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
573 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
575 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
577 * At this point, we assume the file is in error.
578 * It still could be something else besides a NE file,
579 * but it unlikely at this point.
584 /* Allocate a bit more space to speed up things */
586 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
588 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
595 * This is a HACK! I got tired of trying to sort through the
596 * messy 'NE' file format. If anyone wants to clean this up
597 * please have at it, but this works. 'NE' files will
598 * eventually fade away. JRR
600 byte_count = printing_pread_data(fsp, buf, &in_pos, VS_NE_BUF_SIZE);
601 while (byte_count > 0) {
603 * Cover case that should not occur in a well
604 * formed 'NE' .dll file
606 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
610 for(i=0; i<byte_count; i++) {
612 * Fast skip past data that can't
616 byte_count = printing_pread_data(fsp,
624 * Potential match data crosses buf boundry,
625 * move it to beginning of buf, and fill the
626 * buf with as much as it will hold.
628 if (i>byte_count-VS_VERSION_INFO_SIZE) {
630 ssize_t amount_unused = byte_count-i;
632 memmove(buf, &buf[i], amount_unused);
633 amount_read = printing_pread_data(fsp,
636 VS_NE_BUF_SIZE- amount_unused);
637 if (amount_read < 0) {
638 DBG_ERR("NE file [%s] Read "
645 if (amount_read + amount_unused <
647 /* Check for integer wrap. */
651 byte_count = amount_read +
653 if (byte_count < VS_VERSION_INFO_SIZE) {
661 * Check that the full signature string and
662 * the magic number that follows exist (not
663 * a perfect solution, but the chances that this
664 * occurs in code is, well, remote. Yes I know
665 * I'm comparing the 'V' twice, as it is
666 * simpler to read the code.
668 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
670 * Compute skip alignment to next
673 off_t cpos = SMB_VFS_LSEEK(fsp,
677 int skip = -(cpos - (byte_count - i) +
678 sizeof(VS_SIGNATURE)) & 3;
680 i+sizeof(VS_SIGNATURE)+skip)
682 byte_count = printing_pread_data(fsp,
690 i+sizeof(VS_SIGNATURE)+
691 skip+VS_MAJOR_OFFSET);
693 i+sizeof(VS_SIGNATURE)+
694 skip+VS_MINOR_OFFSET);
695 DBG_INFO("NE file [%s] Version "
696 "= %08x:%08x (%d.%d.%d.%d)\n",
710 /* Version info not found, fall back to origin date/time */
711 DBG_ERR("NE file [%s] Version info not found\n", fname);
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct *fsp,
735 off_t in_pos = fsp->fh->pos;
737 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
739 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
745 byte_count = printing_pread_data(fsp, buf, &in_pos, DOS_HEADER_SIZE);
746 if (byte_count < DOS_HEADER_SIZE) {
747 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
749 (unsigned long)byte_count);
750 goto no_version_info;
753 /* Is this really a DOS header? */
754 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
755 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
757 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
758 goto no_version_info;
762 * Skip OEM header (if any) and the
763 * DOS stub to start of Windows header.
765 in_pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
767 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
768 byte_count = printing_pread_data(fsp, buf, &in_pos, NE_HEADER_SIZE);
769 if (byte_count < NE_HEADER_SIZE) {
770 DBG_NOTICE("File [%s] Windows header too short, "
771 "bytes read = %lu\n",
773 (unsigned long)byte_count);
775 * Assume this isn't an error...
776 * the file just looks sort of like a PE/NE file
778 goto no_version_info;
782 * The header may be a PE (Portable Executable)
783 * or an NE (New Executable).
785 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
786 return handle_pe_file(fsp,
791 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
792 NE_HEADER_SIGNATURE) {
793 return handle_ne_file(fsp,
800 * Assume this isn't an error... the file just
801 * looks sort of like a PE/NE file.
803 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
805 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
806 /* Fallthrough into no_version_info: */
818 /****************************************************************************
819 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
820 share one or more files. During the MS installation process files are checked
821 to insure that only a newer version of a shared file is installed over an
822 older version. There are several possibilities for this comparison. If there
823 is no previous version, the new one is newer (obviously). If either file is
824 missing the version info structure, compare the creation date (on Unix use
825 the modification date). Otherwise chose the numerically larger version number.
826 ****************************************************************************/
828 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
830 bool use_version = true;
834 time_t new_create_time;
838 time_t old_create_time;
840 struct smb_filename *smb_fname = NULL;
841 files_struct *fsp = NULL;
847 SET_STAT_INVALID(st);
848 new_create_time = (time_t)0;
849 old_create_time = (time_t)0;
851 /* Get file version info (if available) for previous file (if it exists) */
852 status = driver_unix_convert(conn, old_file, &smb_fname);
853 if (!NT_STATUS_IS_OK(status)) {
857 status = SMB_VFS_CREATE_FILE(
860 0, /* root_dir_fid */
861 smb_fname, /* fname */
862 FILE_GENERIC_READ, /* access_mask */
863 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
864 FILE_OPEN, /* create_disposition*/
865 0, /* create_options */
866 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
867 INTERNAL_OPEN_ONLY, /* oplock_request */
869 0, /* allocation_size */
870 0, /* private_flags */
875 NULL, NULL); /* create context */
877 if (!NT_STATUS_IS_OK(status)) {
878 /* Old file not found, so by definition new file is in fact newer */
879 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
880 "errno = %d\n", smb_fname_str_dbg(smb_fname),
886 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
892 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
895 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
898 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
899 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
900 (long)old_create_time));
903 close_file(NULL, fsp, NORMAL_CLOSE);
906 /* Get file version info (if available) for new file */
907 status = driver_unix_convert(conn, new_file, &smb_fname);
908 if (!NT_STATUS_IS_OK(status)) {
912 status = SMB_VFS_CREATE_FILE(
915 0, /* root_dir_fid */
916 smb_fname, /* fname */
917 FILE_GENERIC_READ, /* access_mask */
918 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
919 FILE_OPEN, /* create_disposition*/
920 0, /* create_options */
921 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
922 INTERNAL_OPEN_ONLY, /* oplock_request */
924 0, /* allocation_size */
925 0, /* private_flags */
930 NULL, NULL); /* create context */
932 if (!NT_STATUS_IS_OK(status)) {
933 /* New file not found, this shouldn't occur if the caller did its job */
934 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
935 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
939 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
945 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
948 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
951 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
952 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
953 (long)new_create_time));
956 close_file(NULL, fsp, NORMAL_CLOSE);
959 if (use_version && (new_major != old_major || new_minor != old_minor)) {
960 /* Compare versions and choose the larger version number */
961 if (new_major > old_major ||
962 (new_major == old_major && new_minor > old_minor)) {
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));
975 /* Compare modification time/dates and choose the newest time/date */
976 if (new_create_time > old_create_time) {
977 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
982 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
990 close_file(NULL, fsp, NORMAL_CLOSE);
993 TALLOC_FREE(smb_fname);
997 /****************************************************************************
998 Determine the correct cVersion associated with an architecture and driver
999 ****************************************************************************/
1000 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
1001 const char *architecture,
1002 const char *driverpath_in,
1003 const char *driver_directory,
1008 struct smb_filename *smb_fname = NULL;
1009 files_struct *fsp = NULL;
1010 connection_struct *conn = NULL;
1011 struct smb_filename *oldcwd_fname = NULL;
1012 char *printdollar = NULL;
1013 char *printdollar_path = NULL;
1014 char *working_dir = NULL;
1015 int printdollar_snum;
1017 *perr = WERR_INVALID_PARAMETER;
1019 /* If architecture is Windows 95/98/ME, the version is always 0. */
1020 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1021 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1026 /* If architecture is Windows x64, the version is always 3. */
1027 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1028 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1033 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1035 *perr = WERR_NOT_ENOUGH_MEMORY;
1038 if (printdollar_snum == -1) {
1039 *perr = WERR_BAD_NET_NAME;
1043 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
1044 if (printdollar_path == NULL) {
1045 *perr = WERR_NOT_ENOUGH_MEMORY;
1049 working_dir = talloc_asprintf(talloc_tos(),
1054 * If the driver has been uploaded into a temorpary driver
1055 * directory, switch to the driver directory.
1057 if (driver_directory != NULL) {
1058 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
1064 nt_status = create_conn_struct_cwd(talloc_tos(),
1065 server_event_context(),
1066 server_messaging_context(),
1070 session_info, &oldcwd_fname);
1071 if (!NT_STATUS_IS_OK(nt_status)) {
1072 DEBUG(0,("get_correct_cversion: create_conn_struct "
1073 "returned %s\n", nt_errstr(nt_status)));
1074 *perr = ntstatus_to_werror(nt_status);
1078 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1079 if (!NT_STATUS_IS_OK(nt_status)) {
1080 DEBUG(0, ("failed set force user / group\n"));
1081 *perr = ntstatus_to_werror(nt_status);
1082 goto error_free_conn;
1085 if (!become_user_by_session(conn, session_info)) {
1086 DEBUG(0, ("failed to become user\n"));
1087 *perr = WERR_ACCESS_DENIED;
1088 goto error_free_conn;
1092 * We switch to the directory where the driver files are located,
1093 * so only work on the file names
1095 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1096 if (!NT_STATUS_IS_OK(nt_status)) {
1097 *perr = ntstatus_to_werror(nt_status);
1101 nt_status = vfs_file_exist(conn, smb_fname);
1102 if (!NT_STATUS_IS_OK(nt_status)) {
1103 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1104 *perr = WERR_FILE_NOT_FOUND;
1108 nt_status = SMB_VFS_CREATE_FILE(
1111 0, /* root_dir_fid */
1112 smb_fname, /* fname */
1113 FILE_GENERIC_READ, /* access_mask */
1114 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1115 FILE_OPEN, /* create_disposition*/
1116 0, /* create_options */
1117 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1118 INTERNAL_OPEN_ONLY, /* oplock_request */
1120 0, /* private_flags */
1121 0, /* allocation_size */
1126 NULL, NULL); /* create context */
1128 if (!NT_STATUS_IS_OK(nt_status)) {
1129 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1130 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1131 *perr = WERR_ACCESS_DENIED;
1138 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1140 *perr = WERR_INVALID_PARAMETER;
1143 DEBUG(6,("get_correct_cversion: Version info not "
1145 smb_fname_str_dbg(smb_fname)));
1146 *perr = WERR_INVALID_PARAMETER;
1151 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1152 * for more details. Version in this case is not just the version of the
1153 * file, but the version in the sense of kernal mode (2) vs. user mode
1154 * (3) drivers. Other bits of the version fields are the version info.
1157 cversion = major & 0x0000ffff;
1159 case 2: /* WinNT drivers */
1160 case 3: /* Win2K drivers */
1164 DEBUG(6,("get_correct_cversion: cversion "
1165 "invalid [%s] cversion = %d\n",
1166 smb_fname_str_dbg(smb_fname),
1171 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1172 " = 0x%x minor = 0x%x\n",
1173 smb_fname_str_dbg(smb_fname), major, minor));
1176 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1177 smb_fname_str_dbg(smb_fname), cversion));
1183 TALLOC_FREE(smb_fname);
1185 close_file(NULL, fsp, NORMAL_CLOSE);
1188 vfs_ChDir(conn, oldcwd_fname);
1189 TALLOC_FREE(oldcwd_fname);
1190 SMB_VFS_DISCONNECT(conn);
1193 if (!W_ERROR_IS_OK(*perr)) {
1200 /****************************************************************************
1201 ****************************************************************************/
1203 #define strip_driver_path(_mem_ctx, _element) do { \
1204 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1205 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1206 W_ERROR_HAVE_NO_MEMORY((_element)); \
1210 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1211 struct auth_session_info *session_info,
1212 const char *architecture,
1213 const char **driver_path,
1214 const char **data_file,
1215 const char **config_file,
1216 const char **help_file,
1217 struct spoolss_StringArray *dependent_files,
1218 enum spoolss_DriverOSVersion *version,
1220 const char **driver_directory)
1222 const char *short_architecture;
1227 if (!*driver_path || !*data_file) {
1228 return WERR_INVALID_PARAMETER;
1231 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1232 return WERR_INVALID_PARAMETER;
1235 if (flags & APD_COPY_FROM_DIRECTORY) {
1240 * driver_path is set to:
1242 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1244 path = talloc_strdup(mem_ctx, *driver_path);
1246 return WERR_NOT_ENOUGH_MEMORY;
1249 /* Remove pscript5.dll */
1250 q = strrchr_m(path, '\\');
1252 return WERR_INVALID_PARAMETER;
1256 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1257 q = strrchr_m(path, '\\');
1259 return WERR_INVALID_PARAMETER;
1263 * Set driver_directory to:
1265 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1267 * This is the directory where all the files have been uploaded
1269 *driver_directory = q + 1;
1272 /* clean up the driver name.
1273 * we can get .\driver.dll
1274 * or worse c:\windows\system\driver.dll !
1276 /* using an intermediate string to not have overlaping memcpy()'s */
1278 strip_driver_path(mem_ctx, *driver_path);
1279 strip_driver_path(mem_ctx, *data_file);
1281 strip_driver_path(mem_ctx, *config_file);
1284 strip_driver_path(mem_ctx, *help_file);
1287 if (dependent_files && dependent_files->string) {
1288 for (i=0; dependent_files->string[i]; i++) {
1289 strip_driver_path(mem_ctx, dependent_files->string[i]);
1293 short_architecture = get_short_archi(architecture);
1294 if (!short_architecture) {
1295 return WERR_UNKNOWN_PRINTER_DRIVER;
1298 /* jfm:7/16/2000 the client always sends the cversion=0.
1299 * The server should check which version the driver is by reading
1300 * the PE header of driver->driverpath.
1302 * For Windows 95/98 the version is 0 (so the value sent is correct)
1303 * For Windows NT (the architecture doesn't matter)
1304 * NT 3.1: cversion=0
1305 * NT 3.5/3.51: cversion=1
1310 *version = get_correct_cversion(session_info,
1315 if (*version == -1) {
1322 /****************************************************************************
1323 ****************************************************************************/
1325 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1326 struct auth_session_info *session_info,
1327 struct spoolss_AddDriverInfoCtr *r,
1329 const char **driver_directory)
1333 return clean_up_driver_struct_level(mem_ctx, session_info,
1334 r->info.info3->architecture,
1335 &r->info.info3->driver_path,
1336 &r->info.info3->data_file,
1337 &r->info.info3->config_file,
1338 &r->info.info3->help_file,
1339 r->info.info3->dependent_files,
1340 &r->info.info3->version,
1344 return clean_up_driver_struct_level(mem_ctx, session_info,
1345 r->info.info6->architecture,
1346 &r->info.info6->driver_path,
1347 &r->info.info6->data_file,
1348 &r->info.info6->config_file,
1349 &r->info.info6->help_file,
1350 r->info.info6->dependent_files,
1351 &r->info.info6->version,
1355 return clean_up_driver_struct_level(mem_ctx, session_info,
1356 r->info.info8->architecture,
1357 &r->info.info8->driver_path,
1358 &r->info.info8->data_file,
1359 &r->info.info8->config_file,
1360 &r->info.info8->help_file,
1361 r->info.info8->dependent_files,
1362 &r->info.info8->version,
1366 return WERR_NOT_SUPPORTED;
1370 /****************************************************************************
1371 This function sucks and should be replaced. JRA.
1372 ****************************************************************************/
1374 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1375 const struct spoolss_AddDriverInfo6 *src)
1377 dst->version = src->version;
1379 dst->driver_name = src->driver_name;
1380 dst->architecture = src->architecture;
1381 dst->driver_path = src->driver_path;
1382 dst->data_file = src->data_file;
1383 dst->config_file = src->config_file;
1384 dst->help_file = src->help_file;
1385 dst->monitor_name = src->monitor_name;
1386 dst->default_datatype = src->default_datatype;
1387 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1388 dst->dependent_files = src->dependent_files;
1391 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1392 const struct spoolss_AddDriverInfo8 *src)
1394 dst->version = src->version;
1396 dst->driver_name = src->driver_name;
1397 dst->architecture = src->architecture;
1398 dst->driver_path = src->driver_path;
1399 dst->data_file = src->data_file;
1400 dst->config_file = src->config_file;
1401 dst->help_file = src->help_file;
1402 dst->monitor_name = src->monitor_name;
1403 dst->default_datatype = src->default_datatype;
1404 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1405 dst->dependent_files = src->dependent_files;
1408 /****************************************************************************
1409 ****************************************************************************/
1411 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1412 connection_struct *conn,
1413 const char *driver_file,
1414 const char *short_architecture,
1415 uint32_t driver_version,
1417 const char *driver_directory)
1419 struct smb_filename *smb_fname_old = NULL;
1420 struct smb_filename *smb_fname_new = NULL;
1421 char *old_name = NULL;
1422 char *new_name = NULL;
1426 if (driver_directory != NULL) {
1427 old_name = talloc_asprintf(mem_ctx,
1433 old_name = talloc_asprintf(mem_ctx,
1438 if (old_name == NULL) {
1439 return WERR_NOT_ENOUGH_MEMORY;
1442 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1443 short_architecture, driver_version, driver_file);
1444 if (new_name == NULL) {
1445 TALLOC_FREE(old_name);
1446 return WERR_NOT_ENOUGH_MEMORY;
1449 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1451 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 ret = WERR_NOT_ENOUGH_MEMORY;
1457 /* Setup a synthetic smb_filename struct */
1458 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1459 if (!smb_fname_new) {
1460 ret = WERR_NOT_ENOUGH_MEMORY;
1464 smb_fname_new->base_name = new_name;
1466 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1467 "'%s'\n", smb_fname_old->base_name,
1468 smb_fname_new->base_name));
1470 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1471 OPENX_FILE_EXISTS_TRUNCATE |
1472 OPENX_FILE_CREATE_IF_NOT_EXIST,
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(0,("move_driver_file_to_download_area: Unable "
1477 "to rename [%s] to [%s]: %s\n",
1478 smb_fname_old->base_name, new_name,
1479 nt_errstr(status)));
1480 ret = WERR_APP_INIT_FAILURE;
1487 TALLOC_FREE(smb_fname_old);
1488 TALLOC_FREE(smb_fname_new);
1492 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1493 struct spoolss_AddDriverInfoCtr *r,
1494 const char *driver_directory)
1496 struct spoolss_AddDriverInfo3 *driver;
1497 struct spoolss_AddDriverInfo3 converted_driver;
1498 const char *short_architecture;
1499 struct smb_filename *smb_dname = NULL;
1500 char *new_dir = NULL;
1501 connection_struct *conn = NULL;
1504 TALLOC_CTX *ctx = talloc_tos();
1506 struct smb_filename *oldcwd_fname = NULL;
1507 char *printdollar = NULL;
1508 int printdollar_snum;
1509 WERROR err = WERR_OK;
1513 driver = r->info.info3;
1516 convert_level_6_to_level3(&converted_driver, r->info.info6);
1517 driver = &converted_driver;
1520 convert_level_8_to_level3(&converted_driver, r->info.info8);
1521 driver = &converted_driver;
1524 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1525 return WERR_INVALID_LEVEL;
1528 short_architecture = get_short_archi(driver->architecture);
1529 if (!short_architecture) {
1530 return WERR_UNKNOWN_PRINTER_DRIVER;
1533 printdollar_snum = find_service(ctx, "print$", &printdollar);
1535 return WERR_NOT_ENOUGH_MEMORY;
1537 if (printdollar_snum == -1) {
1538 return WERR_BAD_NET_NAME;
1541 nt_status = create_conn_struct_cwd(talloc_tos(),
1542 server_event_context(),
1543 server_messaging_context(),
1546 lp_path(talloc_tos(), printdollar_snum),
1547 session_info, &oldcwd_fname);
1548 if (!NT_STATUS_IS_OK(nt_status)) {
1549 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1550 "returned %s\n", nt_errstr(nt_status)));
1551 err = ntstatus_to_werror(nt_status);
1555 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1556 if (!NT_STATUS_IS_OK(nt_status)) {
1557 DEBUG(0, ("failed set force user / group\n"));
1558 err = ntstatus_to_werror(nt_status);
1562 if (!become_user_by_session(conn, session_info)) {
1563 DEBUG(0, ("failed to become user\n"));
1564 err = WERR_ACCESS_DENIED;
1568 new_dir = talloc_asprintf(ctx,
1573 err = WERR_NOT_ENOUGH_MEMORY;
1576 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1577 if (!NT_STATUS_IS_OK(nt_status)) {
1578 err = WERR_NOT_ENOUGH_MEMORY;
1582 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1584 nt_status = create_directory(conn, NULL, smb_dname);
1585 if (!NT_STATUS_IS_OK(nt_status)
1586 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1587 DEBUG(0, ("failed to create driver destination directory: %s\n",
1588 nt_errstr(nt_status)));
1589 err = ntstatus_to_werror(nt_status);
1593 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1594 * listed for this driver which has already been moved, skip it (note:
1595 * drivers may list the same file name several times. Then check if the
1596 * file already exists in archi\version\, if so, check that the version
1597 * info (or time stamps if version info is unavailable) is newer (or the
1598 * date is later). If it is, move it to archi\version\filexxx.yyy.
1599 * Otherwise, delete the file.
1601 * If a file is not moved to archi\version\ because of an error, all the
1602 * rest of the 'unmoved' driver files are removed from archi\. If one or
1603 * more of the driver's files was already moved to archi\version\, it
1604 * potentially leaves the driver in a partially updated state. Version
1605 * trauma will most likely occur if an client attempts to use any printer
1606 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1607 * done is appropriate... later JRR
1610 DEBUG(5,("Moving files now !\n"));
1612 if (driver->driver_path && strlen(driver->driver_path)) {
1614 err = move_driver_file_to_download_area(ctx,
1616 driver->driver_path,
1621 if (!W_ERROR_IS_OK(err)) {
1626 if (driver->data_file && strlen(driver->data_file)) {
1627 if (!strequal(driver->data_file, driver->driver_path)) {
1629 err = move_driver_file_to_download_area(ctx,
1636 if (!W_ERROR_IS_OK(err)) {
1642 if (driver->config_file && strlen(driver->config_file)) {
1643 if (!strequal(driver->config_file, driver->driver_path) &&
1644 !strequal(driver->config_file, driver->data_file)) {
1646 err = move_driver_file_to_download_area(ctx,
1648 driver->config_file,
1653 if (!W_ERROR_IS_OK(err)) {
1659 if (driver->help_file && strlen(driver->help_file)) {
1660 if (!strequal(driver->help_file, driver->driver_path) &&
1661 !strequal(driver->help_file, driver->data_file) &&
1662 !strequal(driver->help_file, driver->config_file)) {
1664 err = move_driver_file_to_download_area(ctx,
1671 if (!W_ERROR_IS_OK(err)) {
1677 if (driver->dependent_files && driver->dependent_files->string) {
1678 for (i=0; driver->dependent_files->string[i]; i++) {
1679 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1680 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1681 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1682 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1684 for (j=0; j < i; j++) {
1685 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1690 err = move_driver_file_to_download_area(ctx,
1692 driver->dependent_files->string[i],
1697 if (!W_ERROR_IS_OK(err)) {
1709 TALLOC_FREE(smb_dname);
1712 vfs_ChDir(conn, oldcwd_fname);
1713 TALLOC_FREE(oldcwd_fname);
1714 SMB_VFS_DISCONNECT(conn);
1721 /****************************************************************************
1722 Determine whether or not a particular driver is currently assigned
1724 ****************************************************************************/
1726 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1727 struct dcerpc_binding_handle *b,
1728 const struct spoolss_DriverInfo8 *r)
1731 int n_services = lp_numservices();
1732 bool in_use = false;
1733 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1740 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1742 /* loop through the printers.tdb and check for the drivername */
1744 for (snum=0; snum<n_services && !in_use; snum++) {
1745 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1749 result = winreg_get_printer(mem_ctx, b,
1750 lp_servicename(talloc_tos(), snum),
1752 if (!W_ERROR_IS_OK(result)) {
1753 continue; /* skip */
1756 if (strequal(r->driver_name, pinfo2->drivername)) {
1760 TALLOC_FREE(pinfo2);
1763 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1766 struct spoolss_DriverInfo8 *driver = NULL;
1769 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1771 /* we can still remove the driver if there is one of
1772 "Windows NT x86" version 2 or 3 left */
1774 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1775 if (r->version == 2) {
1776 werr = winreg_get_driver(mem_ctx, b,
1780 } else if (r->version == 3) {
1781 werr = winreg_get_driver(mem_ctx, b,
1786 DBG_ERR("Unknown driver version (%d)\n",
1788 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1790 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1791 werr = winreg_get_driver(mem_ctx, b,
1792 SPOOLSS_ARCHITECTURE_NT_X86,
1797 DBG_ERR("Unknown driver architecture: %s\n",
1799 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1802 /* now check the error code */
1804 if ( W_ERROR_IS_OK(werr) ) {
1805 /* it's ok to remove the driver, we have other architctures left */
1807 talloc_free(driver);
1811 /* report that the driver is not in use by default */
1817 /**********************************************************************
1818 Check to see if a ogiven file is in use by *info
1819 *********************************************************************/
1821 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1828 /* mz: skip files that are in the list but already deleted */
1829 if (!file || !file[0]) {
1833 if (strequal(file, info->driver_path))
1836 if (strequal(file, info->data_file))
1839 if (strequal(file, info->config_file))
1842 if (strequal(file, info->help_file))
1845 /* see of there are any dependent files to examine */
1847 if (!info->dependent_files)
1850 while (info->dependent_files[i] && *info->dependent_files[i]) {
1851 if (strequal(file, info->dependent_files[i]))
1860 /**********************************************************************
1861 Utility function to remove the dependent file pointed to by the
1862 input parameter from the list
1863 *********************************************************************/
1865 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1868 /* bump everything down a slot */
1870 while (files && files[idx+1]) {
1871 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1880 /**********************************************************************
1881 Check if any of the files used by src are also used by drv
1882 *********************************************************************/
1884 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1885 struct spoolss_DriverInfo8 *src,
1886 const struct spoolss_DriverInfo8 *drv)
1888 bool in_use = False;
1894 /* check each file. Remove it from the src structure if it overlaps */
1896 if (drv_file_in_use(src->driver_path, drv)) {
1898 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1899 src->driver_path = talloc_strdup(mem_ctx, "");
1900 if (!src->driver_path) { return false; }
1903 if (drv_file_in_use(src->data_file, drv)) {
1905 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1906 src->data_file = talloc_strdup(mem_ctx, "");
1907 if (!src->data_file) { return false; }
1910 if (drv_file_in_use(src->config_file, drv)) {
1912 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1913 src->config_file = talloc_strdup(mem_ctx, "");
1914 if (!src->config_file) { return false; }
1917 if (drv_file_in_use(src->help_file, drv)) {
1919 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1920 src->help_file = talloc_strdup(mem_ctx, "");
1921 if (!src->help_file) { return false; }
1924 /* are there any dependentfiles to examine? */
1926 if (!src->dependent_files)
1929 while (src->dependent_files[i] && *src->dependent_files[i]) {
1930 if (drv_file_in_use(src->dependent_files[i], drv)) {
1932 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1933 trim_dependent_file(mem_ctx, src->dependent_files, i);
1941 /****************************************************************************
1942 Determine whether or not a particular driver files are currently being
1943 used by any other driver.
1945 Return value is True if any files were in use by other drivers
1946 and False otherwise.
1948 Upon return, *info has been modified to only contain the driver files
1949 which are not in use
1953 This needs to check all drivers to ensure that all files in use
1954 have been removed from *info, not just the ones in the first
1956 ****************************************************************************/
1958 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1959 struct dcerpc_binding_handle *b,
1960 struct spoolss_DriverInfo8 *info)
1964 struct spoolss_DriverInfo8 *driver;
1965 bool in_use = false;
1966 uint32_t num_drivers;
1967 const char **drivers;
1973 version = info->version;
1975 /* loop over all driver versions */
1977 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1979 /* get the list of drivers */
1981 result = winreg_get_driver_list(mem_ctx, b,
1982 info->architecture, version,
1983 &num_drivers, &drivers);
1984 if (!W_ERROR_IS_OK(result)) {
1988 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1989 num_drivers, info->architecture, version));
1991 /* check each driver for overlap in files */
1993 for (i = 0; i < num_drivers; i++) {
1994 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1998 result = winreg_get_driver(mem_ctx, b,
1999 info->architecture, drivers[i],
2001 if (!W_ERROR_IS_OK(result)) {
2002 talloc_free(drivers);
2006 /* check if d2 uses any files from d1 */
2007 /* only if this is a different driver than the one being deleted */
2009 if (!strequal(info->driver_name, driver->driver_name)) {
2010 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
2011 /* mz: Do not instantly return -
2012 * we need to ensure this file isn't
2013 * also in use by other drivers. */
2018 talloc_free(driver);
2021 talloc_free(drivers);
2023 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2028 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2029 const char *short_arch,
2033 TALLOC_CTX *tmp_ctx = talloc_new(conn);
2034 struct smb_filename *smb_fname = NULL;
2035 char *print_dlr_path;
2036 NTSTATUS status = NT_STATUS_NO_MEMORY;
2038 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2039 short_arch, vers, fname);
2040 if (print_dlr_path == NULL) {
2044 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2045 if (smb_fname == NULL) {
2049 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2051 talloc_free(tmp_ctx);
2055 /****************************************************************************
2056 Actually delete the driver files. Make sure that
2057 printer_driver_files_in_use() return False before calling
2059 ****************************************************************************/
2061 bool delete_driver_files(const struct auth_session_info *session_info,
2062 const struct spoolss_DriverInfo8 *r)
2064 const char *short_arch;
2065 connection_struct *conn;
2067 struct smb_filename *oldcwd_fname = NULL;
2068 char *printdollar = NULL;
2069 int printdollar_snum;
2076 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2077 r->driver_name, r->version));
2079 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2083 if (printdollar_snum == -1) {
2087 nt_status = create_conn_struct_cwd(talloc_tos(),
2088 server_event_context(),
2089 server_messaging_context(),
2092 lp_path(talloc_tos(), printdollar_snum),
2093 session_info, &oldcwd_fname);
2094 if (!NT_STATUS_IS_OK(nt_status)) {
2095 DEBUG(0,("delete_driver_files: create_conn_struct "
2096 "returned %s\n", nt_errstr(nt_status)));
2100 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2101 if (!NT_STATUS_IS_OK(nt_status)) {
2102 DEBUG(0, ("failed set force user / group\n"));
2107 if (!become_user_by_session(conn, session_info)) {
2108 DEBUG(0, ("failed to become user\n"));
2113 if ( !CAN_WRITE(conn) ) {
2114 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2119 short_arch = get_short_archi(r->architecture);
2120 if (short_arch == NULL) {
2121 DEBUG(0, ("bad architecture %s\n", r->architecture));
2126 /* now delete the files */
2128 if (r->driver_path && r->driver_path[0]) {
2129 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2130 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2133 if (r->config_file && r->config_file[0]) {
2134 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2135 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2138 if (r->data_file && r->data_file[0]) {
2139 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2140 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2143 if (r->help_file && r->help_file[0]) {
2144 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2145 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2148 if (r->dependent_files) {
2150 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2151 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2152 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2162 vfs_ChDir(conn, oldcwd_fname);
2163 TALLOC_FREE(oldcwd_fname);
2164 SMB_VFS_DISCONNECT(conn);
2172 1: level not implemented
2173 2: file doesn't exist
2174 3: can't allocate memory
2175 4: can't free memory
2176 5: non existent struct
2180 A printer and a printer driver are 2 different things.
2181 NT manages them separatelly, Samba does the same.
2182 Why ? Simply because it's easier and it makes sense !
2184 Now explanation: You have 3 printers behind your samba server,
2185 2 of them are the same make and model (laser A and B). But laser B
2186 has an 3000 sheet feeder and laser A doesn't such an option.
2187 Your third printer is an old dot-matrix model for the accounting :-).
2189 If the /usr/local/samba/lib directory (default dir), you will have
2190 5 files to describe all of this.
2192 3 files for the printers (1 by printer):
2195 NTprinter_accounting
2196 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2197 NTdriver_printer model X
2198 NTdriver_printer model Y
2200 jfm: I should use this comment for the text file to explain
2201 same thing for the forms BTW.
2202 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2206 /* Convert generic access rights to printer object specific access rights.
2207 It turns out that NT4 security descriptors use generic access rights and
2208 NT5 the object specific ones. */
2210 void map_printer_permissions(struct security_descriptor *sd)
2214 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2215 se_map_generic(&sd->dacl->aces[i].access_mask,
2216 &printer_generic_mapping);
2220 void map_job_permissions(struct security_descriptor *sd)
2224 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2225 se_map_generic(&sd->dacl->aces[i].access_mask,
2226 &job_generic_mapping);
2231 /****************************************************************************
2232 Check a user has permissions to perform the given operation. We use the
2233 permission constants defined in include/rpc_spoolss.h to check the various
2234 actions we perform when checking printer access.
2236 PRINTER_ACCESS_ADMINISTER:
2237 print_queue_pause, print_queue_resume, update_printer_sec,
2238 update_printer, spoolss_addprinterex_level_2,
2239 _spoolss_setprinterdata
2244 JOB_ACCESS_ADMINISTER:
2245 print_job_delete, print_job_pause, print_job_resume,
2248 Try access control in the following order (for performance reasons):
2249 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2250 2) check security descriptor (bit comparisons in memory)
2251 3) "printer admins" (may result in numerous calls to winbind)
2253 ****************************************************************************/
2254 WERROR print_access_check(const struct auth_session_info *session_info,
2255 struct messaging_context *msg_ctx, int snum,
2258 struct spoolss_security_descriptor *secdesc = NULL;
2259 uint32_t access_granted;
2264 TALLOC_CTX *mem_ctx = NULL;
2266 /* If user is NULL then use the current_user structure */
2268 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2270 if ((session_info->unix_token->uid == sec_initial_uid())
2271 || security_token_has_privilege(session_info->security_token,
2272 SEC_PRIV_PRINT_OPERATOR)) {
2276 /* Get printer name */
2278 pname = lp_printername(talloc_tos(), snum);
2280 if (!pname || !*pname) {
2281 return WERR_ACCESS_DENIED;
2284 /* Get printer security descriptor */
2286 if(!(mem_ctx = talloc_init("print_access_check"))) {
2287 return WERR_NOT_ENOUGH_MEMORY;
2290 result = winreg_get_printer_secdesc_internal(mem_ctx,
2291 get_session_info_system(),
2295 if (!W_ERROR_IS_OK(result)) {
2296 talloc_destroy(mem_ctx);
2297 return WERR_NOT_ENOUGH_MEMORY;
2300 if (access_type == JOB_ACCESS_ADMINISTER) {
2301 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2303 /* Create a child security descriptor to check permissions
2304 against. This is because print jobs are child objects
2305 objects of a printer. */
2306 status = se_create_child_secdesc(mem_ctx,
2310 parent_secdesc->owner_sid,
2311 parent_secdesc->group_sid,
2313 if (!NT_STATUS_IS_OK(status)) {
2314 talloc_destroy(mem_ctx);
2315 return ntstatus_to_werror(status);
2318 map_job_permissions(secdesc);
2320 map_printer_permissions(secdesc);
2324 status = se_access_check(secdesc, session_info->security_token, access_type,
2327 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2329 talloc_destroy(mem_ctx);
2331 return ntstatus_to_werror(status);
2334 /****************************************************************************
2335 Check the time parameters allow a print operation.
2336 *****************************************************************************/
2338 bool print_time_access_check(const struct auth_session_info *session_info,
2339 struct messaging_context *msg_ctx,
2340 const char *servicename)
2342 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2345 time_t now = time(NULL);
2349 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2350 servicename, &pinfo2);
2351 if (!W_ERROR_IS_OK(result)) {
2355 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2360 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2362 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2366 TALLOC_FREE(pinfo2);
2375 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2376 const struct auth_session_info *session_info,
2377 struct messaging_context *msg_ctx,
2378 const char *printer)
2382 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2384 if (!W_ERROR_IS_OK(result)) {
2385 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2386 "%s\n", printer, win_errstr(result)));
2390 void nt_printer_add(TALLOC_CTX *mem_ctx,
2391 const struct auth_session_info *session_info,
2392 struct messaging_context *msg_ctx,
2393 const char *printer)
2397 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2399 if (!W_ERROR_IS_OK(result)) {
2400 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2401 printer, win_errstr(result)));