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 vfs_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 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
346 There are two case to be covered here: PE (Portable Executable) and NE (New
347 Executable) files. Both files support the same INFO structure, but PE files
348 store the signature in unicode, and NE files store it as !unicode.
349 returns -1 on error, 1 on version info found, and 0 on no version info found.
350 ****************************************************************************/
352 static int get_file_version(files_struct *fsp,
363 buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE);
365 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
371 byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE);
372 if (byte_count < DOS_HEADER_SIZE) {
373 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
375 (unsigned long)byte_count);
376 goto no_version_info;
379 /* Is this really a DOS header? */
380 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
381 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
383 SVAL(buf,DOS_HEADER_MAGIC_OFFSET));
384 goto no_version_info;
388 * Skip OEM header (if any) and the
389 * DOS stub to start of Windows header.
391 pos = SVAL(buf,DOS_HEADER_LFANEW_OFFSET);
392 oret = SMB_VFS_LSEEK(fsp, pos, SEEK_SET);
393 if (oret == (off_t)-1) {
394 DBG_NOTICE("File [%s] too short, errno = %d\n",
398 * Assume this isn't an error...
399 * the file just looks sort of like a PE/NE file.
401 goto no_version_info;
404 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
405 byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE);
406 if (byte_count < NE_HEADER_SIZE) {
407 DBG_NOTICE("File [%s] Windows header too short, "
408 "bytes read = %lu\n",
410 (unsigned long)byte_count);
412 * Assume this isn't an error...
413 * the file just looks sort of like a PE/NE file
415 goto no_version_info;
419 * The header may be a PE (Portable Executable)
420 * or an NE (New Executable).
422 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
423 unsigned int num_sections;
424 unsigned int section_table_bytes;
426 /* Just skip over optional header to get to section table */
427 pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-
428 (NE_HEADER_SIZE-PE_HEADER_SIZE);
430 oret = SMB_VFS_LSEEK(fsp, pos, SEEK_CUR);
431 if (oret == (off_t)-1) {
432 DBG_NOTICE("File [%s] Windows optional header "
433 "too short, errno = %d\n",
439 /* get the section table */
440 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
441 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
442 if (section_table_bytes == 0) {
447 buf = (char *)SMB_MALLOC(section_table_bytes);
449 DBG_ERR("PE file [%s] section table malloc "
450 "failed bytes = %d\n",
452 section_table_bytes);
456 byte_count = vfs_read_data(fsp, buf, section_table_bytes);
457 if (byte_count < section_table_bytes) {
458 DBG_NOTICE("PE file [%s] "
459 "Section header too short, bytes read = %lu\n",
461 (unsigned long)byte_count);
466 * Iterate the section table looking for
467 * the resource section ".rsrc"
469 for (i = 0; i < num_sections; i++) {
470 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
474 PE_HEADER_SECT_NAME_OFFSET])
476 unsigned int section_pos =
479 PE_HEADER_SECT_PTR_DATA_OFFSET);
480 unsigned int section_bytes =
483 PE_HEADER_SECT_SIZE_DATA_OFFSET);
485 if (section_bytes == 0) {
490 buf=(char *)SMB_MALLOC(section_bytes);
492 DBG_ERR("PE file [%s] version malloc "
493 "failed bytes = %d\n",
500 * Seek to the start of the .rsrc
503 oret = SMB_VFS_LSEEK(fsp,
506 if (oret == (off_t)-1) {
507 DBG_NOTICE("PE file [%s] too short for "
508 "section info, errno = %d\n",
514 byte_count = vfs_read_data(fsp,
517 if (byte_count < section_bytes) {
518 DBG_NOTICE("PE file "
519 "[%s] .rsrc section too short, "
520 "bytes read = %lu\n",
522 (unsigned long)byte_count);
527 VS_VERSION_INFO_UNICODE_SIZE) {
533 VS_VERSION_INFO_UNICODE_SIZE;
536 * Scan for 1st 3 unicoded bytes
537 * followed by word aligned magic
543 /* Align to next long address */
546 sizeof(VS_SIGNATURE)*2 +
549 if (IVAL(buf,mpos) ==
558 DBG_INFO("PE file [%s] "
577 /* Version info not found, fall back to origin date/time */
578 DBG_DEBUG("PE file [%s] has no version info\n", fname);
582 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) ==
583 NE_HEADER_SIGNATURE) {
584 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) !=
585 NE_HEADER_TARGOS_WIN ) {
586 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
588 CVAL(buf,NE_HEADER_TARGET_OS_OFFSET));
590 * At this point, we assume the file is in error.
591 * It still could be something else besides a NE file,
592 * but it unlikely at this point.
597 /* Allocate a bit more space to speed up things */
599 buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE);
601 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
608 * This is a HACK! I got tired of trying to sort through the
609 * messy 'NE' file format. If anyone wants to clean this up
610 * please have at it, but this works. 'NE' files will
611 * eventually fade away. JRR
613 byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE);
614 while (byte_count > 0) {
616 * Cover case that should not occur in a well
617 * formed 'NE' .dll file
619 if (byte_count-VS_VERSION_INFO_SIZE <= 0) {
623 for(i=0; i<byte_count; i++) {
625 * Fast skip past data that can't
629 byte_count = vfs_read_data(fsp,
636 * Potential match data crosses buf boundry,
637 * move it to beginning of buf, and fill the
638 * buf with as much as it will hold.
640 if (i>byte_count-VS_VERSION_INFO_SIZE) {
642 ssize_t amount_unused = byte_count-i;
644 memmove(buf, &buf[i], amount_unused);
645 amount_read = vfs_read_data(fsp,
647 VS_NE_BUF_SIZE- amount_unused);
648 if (amount_read < 0) {
649 DBG_ERR("NE file [%s] Read "
656 if (amount_read + amount_unused <
658 /* Check for integer wrap. */
662 byte_count = amount_read +
664 if (byte_count < VS_VERSION_INFO_SIZE) {
672 * Check that the full signature string and
673 * the magic number that follows exist (not
674 * a perfect solution, but the chances that this
675 * occurs in code is, well, remote. Yes I know
676 * I'm comparing the 'V' twice, as it is
677 * simpler to read the code.
679 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
681 * Compute skip alignment to next
684 off_t cpos = SMB_VFS_LSEEK(fsp,
688 int skip = -(cpos - (byte_count - i) +
689 sizeof(VS_SIGNATURE)) & 3;
691 i+sizeof(VS_SIGNATURE)+skip)
693 byte_count = vfs_read_data(fsp,
700 i+sizeof(VS_SIGNATURE)+
701 skip+VS_MAJOR_OFFSET);
703 i+sizeof(VS_SIGNATURE)+
704 skip+VS_MINOR_OFFSET);
705 DBG_INFO("NE file [%s] Version "
706 "= %08x:%08x (%d.%d.%d.%d)\n",
720 /* Version info not found, fall back to origin date/time */
721 DBG_ERR("NE file [%s] Version info not found\n", fname);
727 * Assume this isn't an error... the file just
728 * looks sort of like a PE/NE file.
730 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
732 IVAL(buf,PE_HEADER_SIGNATURE_OFFSET));
744 /****************************************************************************
745 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
746 share one or more files. During the MS installation process files are checked
747 to insure that only a newer version of a shared file is installed over an
748 older version. There are several possibilities for this comparison. If there
749 is no previous version, the new one is newer (obviously). If either file is
750 missing the version info structure, compare the creation date (on Unix use
751 the modification date). Otherwise chose the numerically larger version number.
752 ****************************************************************************/
754 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
756 bool use_version = true;
760 time_t new_create_time;
764 time_t old_create_time;
766 struct smb_filename *smb_fname = NULL;
767 files_struct *fsp = NULL;
773 SET_STAT_INVALID(st);
774 new_create_time = (time_t)0;
775 old_create_time = (time_t)0;
777 /* Get file version info (if available) for previous file (if it exists) */
778 status = driver_unix_convert(conn, old_file, &smb_fname);
779 if (!NT_STATUS_IS_OK(status)) {
783 status = SMB_VFS_CREATE_FILE(
786 0, /* root_dir_fid */
787 smb_fname, /* fname */
788 FILE_GENERIC_READ, /* access_mask */
789 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
790 FILE_OPEN, /* create_disposition*/
791 0, /* create_options */
792 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
793 INTERNAL_OPEN_ONLY, /* oplock_request */
795 0, /* allocation_size */
796 0, /* private_flags */
801 NULL, NULL); /* create context */
803 if (!NT_STATUS_IS_OK(status)) {
804 /* Old file not found, so by definition new file is in fact newer */
805 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
806 "errno = %d\n", smb_fname_str_dbg(smb_fname),
812 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
818 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
821 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
824 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
825 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
826 (long)old_create_time));
829 close_file(NULL, fsp, NORMAL_CLOSE);
832 /* Get file version info (if available) for new file */
833 status = driver_unix_convert(conn, new_file, &smb_fname);
834 if (!NT_STATUS_IS_OK(status)) {
838 status = SMB_VFS_CREATE_FILE(
841 0, /* root_dir_fid */
842 smb_fname, /* fname */
843 FILE_GENERIC_READ, /* access_mask */
844 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
845 FILE_OPEN, /* create_disposition*/
846 0, /* create_options */
847 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
848 INTERNAL_OPEN_ONLY, /* oplock_request */
850 0, /* allocation_size */
851 0, /* private_flags */
856 NULL, NULL); /* create context */
858 if (!NT_STATUS_IS_OK(status)) {
859 /* New file not found, this shouldn't occur if the caller did its job */
860 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
861 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
865 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
871 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
874 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
877 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
878 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
879 (long)new_create_time));
882 close_file(NULL, fsp, NORMAL_CLOSE);
885 if (use_version && (new_major != old_major || new_minor != old_minor)) {
886 /* Compare versions and choose the larger version number */
887 if (new_major > old_major ||
888 (new_major == old_major && new_minor > old_minor)) {
890 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
895 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
901 /* Compare modification time/dates and choose the newest time/date */
902 if (new_create_time > old_create_time) {
903 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
908 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
916 close_file(NULL, fsp, NORMAL_CLOSE);
919 TALLOC_FREE(smb_fname);
923 /****************************************************************************
924 Determine the correct cVersion associated with an architecture and driver
925 ****************************************************************************/
926 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
927 const char *architecture,
928 const char *driverpath_in,
929 const char *driver_directory,
934 struct smb_filename *smb_fname = NULL;
935 files_struct *fsp = NULL;
936 connection_struct *conn = NULL;
937 struct smb_filename *oldcwd_fname = NULL;
938 char *printdollar = NULL;
939 char *printdollar_path = NULL;
940 char *working_dir = NULL;
941 int printdollar_snum;
943 *perr = WERR_INVALID_PARAMETER;
945 /* If architecture is Windows 95/98/ME, the version is always 0. */
946 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
947 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
952 /* If architecture is Windows x64, the version is always 3. */
953 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
954 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
959 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
961 *perr = WERR_NOT_ENOUGH_MEMORY;
964 if (printdollar_snum == -1) {
965 *perr = WERR_BAD_NET_NAME;
969 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
970 if (printdollar_path == NULL) {
971 *perr = WERR_NOT_ENOUGH_MEMORY;
975 working_dir = talloc_asprintf(talloc_tos(),
980 * If the driver has been uploaded into a temorpary driver
981 * directory, switch to the driver directory.
983 if (driver_directory != NULL) {
984 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
990 nt_status = create_conn_struct_cwd(talloc_tos(),
991 server_event_context(),
992 server_messaging_context(),
996 session_info, &oldcwd_fname);
997 if (!NT_STATUS_IS_OK(nt_status)) {
998 DEBUG(0,("get_correct_cversion: create_conn_struct "
999 "returned %s\n", nt_errstr(nt_status)));
1000 *perr = ntstatus_to_werror(nt_status);
1004 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1005 if (!NT_STATUS_IS_OK(nt_status)) {
1006 DEBUG(0, ("failed set force user / group\n"));
1007 *perr = ntstatus_to_werror(nt_status);
1008 goto error_free_conn;
1011 if (!become_user_by_session(conn, session_info)) {
1012 DEBUG(0, ("failed to become user\n"));
1013 *perr = WERR_ACCESS_DENIED;
1014 goto error_free_conn;
1018 * We switch to the directory where the driver files are located,
1019 * so only work on the file names
1021 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1022 if (!NT_STATUS_IS_OK(nt_status)) {
1023 *perr = ntstatus_to_werror(nt_status);
1027 nt_status = vfs_file_exist(conn, smb_fname);
1028 if (!NT_STATUS_IS_OK(nt_status)) {
1029 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1030 *perr = WERR_FILE_NOT_FOUND;
1034 nt_status = SMB_VFS_CREATE_FILE(
1037 0, /* root_dir_fid */
1038 smb_fname, /* fname */
1039 FILE_GENERIC_READ, /* access_mask */
1040 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1041 FILE_OPEN, /* create_disposition*/
1042 0, /* create_options */
1043 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1044 INTERNAL_OPEN_ONLY, /* oplock_request */
1046 0, /* private_flags */
1047 0, /* allocation_size */
1052 NULL, NULL); /* create context */
1054 if (!NT_STATUS_IS_OK(nt_status)) {
1055 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1056 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1057 *perr = WERR_ACCESS_DENIED;
1064 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1066 *perr = WERR_INVALID_PARAMETER;
1069 DEBUG(6,("get_correct_cversion: Version info not "
1071 smb_fname_str_dbg(smb_fname)));
1072 *perr = WERR_INVALID_PARAMETER;
1077 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1078 * for more details. Version in this case is not just the version of the
1079 * file, but the version in the sense of kernal mode (2) vs. user mode
1080 * (3) drivers. Other bits of the version fields are the version info.
1083 cversion = major & 0x0000ffff;
1085 case 2: /* WinNT drivers */
1086 case 3: /* Win2K drivers */
1090 DEBUG(6,("get_correct_cversion: cversion "
1091 "invalid [%s] cversion = %d\n",
1092 smb_fname_str_dbg(smb_fname),
1097 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1098 " = 0x%x minor = 0x%x\n",
1099 smb_fname_str_dbg(smb_fname), major, minor));
1102 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1103 smb_fname_str_dbg(smb_fname), cversion));
1109 TALLOC_FREE(smb_fname);
1111 close_file(NULL, fsp, NORMAL_CLOSE);
1114 vfs_ChDir(conn, oldcwd_fname);
1115 TALLOC_FREE(oldcwd_fname);
1116 SMB_VFS_DISCONNECT(conn);
1119 if (!W_ERROR_IS_OK(*perr)) {
1126 /****************************************************************************
1127 ****************************************************************************/
1129 #define strip_driver_path(_mem_ctx, _element) do { \
1130 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1131 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1132 W_ERROR_HAVE_NO_MEMORY((_element)); \
1136 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1137 struct auth_session_info *session_info,
1138 const char *architecture,
1139 const char **driver_path,
1140 const char **data_file,
1141 const char **config_file,
1142 const char **help_file,
1143 struct spoolss_StringArray *dependent_files,
1144 enum spoolss_DriverOSVersion *version,
1146 const char **driver_directory)
1148 const char *short_architecture;
1153 if (!*driver_path || !*data_file) {
1154 return WERR_INVALID_PARAMETER;
1157 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1158 return WERR_INVALID_PARAMETER;
1161 if (flags & APD_COPY_FROM_DIRECTORY) {
1166 * driver_path is set to:
1168 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1170 path = talloc_strdup(mem_ctx, *driver_path);
1172 return WERR_NOT_ENOUGH_MEMORY;
1175 /* Remove pscript5.dll */
1176 q = strrchr_m(path, '\\');
1178 return WERR_INVALID_PARAMETER;
1182 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1183 q = strrchr_m(path, '\\');
1185 return WERR_INVALID_PARAMETER;
1189 * Set driver_directory to:
1191 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1193 * This is the directory where all the files have been uploaded
1195 *driver_directory = q + 1;
1198 /* clean up the driver name.
1199 * we can get .\driver.dll
1200 * or worse c:\windows\system\driver.dll !
1202 /* using an intermediate string to not have overlaping memcpy()'s */
1204 strip_driver_path(mem_ctx, *driver_path);
1205 strip_driver_path(mem_ctx, *data_file);
1207 strip_driver_path(mem_ctx, *config_file);
1210 strip_driver_path(mem_ctx, *help_file);
1213 if (dependent_files && dependent_files->string) {
1214 for (i=0; dependent_files->string[i]; i++) {
1215 strip_driver_path(mem_ctx, dependent_files->string[i]);
1219 short_architecture = get_short_archi(architecture);
1220 if (!short_architecture) {
1221 return WERR_UNKNOWN_PRINTER_DRIVER;
1224 /* jfm:7/16/2000 the client always sends the cversion=0.
1225 * The server should check which version the driver is by reading
1226 * the PE header of driver->driverpath.
1228 * For Windows 95/98 the version is 0 (so the value sent is correct)
1229 * For Windows NT (the architecture doesn't matter)
1230 * NT 3.1: cversion=0
1231 * NT 3.5/3.51: cversion=1
1236 *version = get_correct_cversion(session_info,
1241 if (*version == -1) {
1248 /****************************************************************************
1249 ****************************************************************************/
1251 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1252 struct auth_session_info *session_info,
1253 struct spoolss_AddDriverInfoCtr *r,
1255 const char **driver_directory)
1259 return clean_up_driver_struct_level(mem_ctx, session_info,
1260 r->info.info3->architecture,
1261 &r->info.info3->driver_path,
1262 &r->info.info3->data_file,
1263 &r->info.info3->config_file,
1264 &r->info.info3->help_file,
1265 r->info.info3->dependent_files,
1266 &r->info.info3->version,
1270 return clean_up_driver_struct_level(mem_ctx, session_info,
1271 r->info.info6->architecture,
1272 &r->info.info6->driver_path,
1273 &r->info.info6->data_file,
1274 &r->info.info6->config_file,
1275 &r->info.info6->help_file,
1276 r->info.info6->dependent_files,
1277 &r->info.info6->version,
1281 return clean_up_driver_struct_level(mem_ctx, session_info,
1282 r->info.info8->architecture,
1283 &r->info.info8->driver_path,
1284 &r->info.info8->data_file,
1285 &r->info.info8->config_file,
1286 &r->info.info8->help_file,
1287 r->info.info8->dependent_files,
1288 &r->info.info8->version,
1292 return WERR_NOT_SUPPORTED;
1296 /****************************************************************************
1297 This function sucks and should be replaced. JRA.
1298 ****************************************************************************/
1300 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1301 const struct spoolss_AddDriverInfo6 *src)
1303 dst->version = src->version;
1305 dst->driver_name = src->driver_name;
1306 dst->architecture = src->architecture;
1307 dst->driver_path = src->driver_path;
1308 dst->data_file = src->data_file;
1309 dst->config_file = src->config_file;
1310 dst->help_file = src->help_file;
1311 dst->monitor_name = src->monitor_name;
1312 dst->default_datatype = src->default_datatype;
1313 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1314 dst->dependent_files = src->dependent_files;
1317 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1318 const struct spoolss_AddDriverInfo8 *src)
1320 dst->version = src->version;
1322 dst->driver_name = src->driver_name;
1323 dst->architecture = src->architecture;
1324 dst->driver_path = src->driver_path;
1325 dst->data_file = src->data_file;
1326 dst->config_file = src->config_file;
1327 dst->help_file = src->help_file;
1328 dst->monitor_name = src->monitor_name;
1329 dst->default_datatype = src->default_datatype;
1330 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1331 dst->dependent_files = src->dependent_files;
1334 /****************************************************************************
1335 ****************************************************************************/
1337 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1338 connection_struct *conn,
1339 const char *driver_file,
1340 const char *short_architecture,
1341 uint32_t driver_version,
1343 const char *driver_directory)
1345 struct smb_filename *smb_fname_old = NULL;
1346 struct smb_filename *smb_fname_new = NULL;
1347 char *old_name = NULL;
1348 char *new_name = NULL;
1352 if (driver_directory != NULL) {
1353 old_name = talloc_asprintf(mem_ctx,
1359 old_name = talloc_asprintf(mem_ctx,
1364 if (old_name == NULL) {
1365 return WERR_NOT_ENOUGH_MEMORY;
1368 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1369 short_architecture, driver_version, driver_file);
1370 if (new_name == NULL) {
1371 TALLOC_FREE(old_name);
1372 return WERR_NOT_ENOUGH_MEMORY;
1375 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1377 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 ret = WERR_NOT_ENOUGH_MEMORY;
1383 /* Setup a synthetic smb_filename struct */
1384 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1385 if (!smb_fname_new) {
1386 ret = WERR_NOT_ENOUGH_MEMORY;
1390 smb_fname_new->base_name = new_name;
1392 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1393 "'%s'\n", smb_fname_old->base_name,
1394 smb_fname_new->base_name));
1396 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1397 OPENX_FILE_EXISTS_TRUNCATE |
1398 OPENX_FILE_CREATE_IF_NOT_EXIST,
1401 if (!NT_STATUS_IS_OK(status)) {
1402 DEBUG(0,("move_driver_file_to_download_area: Unable "
1403 "to rename [%s] to [%s]: %s\n",
1404 smb_fname_old->base_name, new_name,
1405 nt_errstr(status)));
1406 ret = WERR_APP_INIT_FAILURE;
1413 TALLOC_FREE(smb_fname_old);
1414 TALLOC_FREE(smb_fname_new);
1418 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1419 struct spoolss_AddDriverInfoCtr *r,
1420 const char *driver_directory)
1422 struct spoolss_AddDriverInfo3 *driver;
1423 struct spoolss_AddDriverInfo3 converted_driver;
1424 const char *short_architecture;
1425 struct smb_filename *smb_dname = NULL;
1426 char *new_dir = NULL;
1427 connection_struct *conn = NULL;
1430 TALLOC_CTX *ctx = talloc_tos();
1432 struct smb_filename *oldcwd_fname = NULL;
1433 char *printdollar = NULL;
1434 int printdollar_snum;
1435 WERROR err = WERR_OK;
1439 driver = r->info.info3;
1442 convert_level_6_to_level3(&converted_driver, r->info.info6);
1443 driver = &converted_driver;
1446 convert_level_8_to_level3(&converted_driver, r->info.info8);
1447 driver = &converted_driver;
1450 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1451 return WERR_INVALID_LEVEL;
1454 short_architecture = get_short_archi(driver->architecture);
1455 if (!short_architecture) {
1456 return WERR_UNKNOWN_PRINTER_DRIVER;
1459 printdollar_snum = find_service(ctx, "print$", &printdollar);
1461 return WERR_NOT_ENOUGH_MEMORY;
1463 if (printdollar_snum == -1) {
1464 return WERR_BAD_NET_NAME;
1467 nt_status = create_conn_struct_cwd(talloc_tos(),
1468 server_event_context(),
1469 server_messaging_context(),
1472 lp_path(talloc_tos(), printdollar_snum),
1473 session_info, &oldcwd_fname);
1474 if (!NT_STATUS_IS_OK(nt_status)) {
1475 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1476 "returned %s\n", nt_errstr(nt_status)));
1477 err = ntstatus_to_werror(nt_status);
1481 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1482 if (!NT_STATUS_IS_OK(nt_status)) {
1483 DEBUG(0, ("failed set force user / group\n"));
1484 err = ntstatus_to_werror(nt_status);
1488 if (!become_user_by_session(conn, session_info)) {
1489 DEBUG(0, ("failed to become user\n"));
1490 err = WERR_ACCESS_DENIED;
1494 new_dir = talloc_asprintf(ctx,
1499 err = WERR_NOT_ENOUGH_MEMORY;
1502 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1503 if (!NT_STATUS_IS_OK(nt_status)) {
1504 err = WERR_NOT_ENOUGH_MEMORY;
1508 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1510 nt_status = create_directory(conn, NULL, smb_dname);
1511 if (!NT_STATUS_IS_OK(nt_status)
1512 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1513 DEBUG(0, ("failed to create driver destination directory: %s\n",
1514 nt_errstr(nt_status)));
1515 err = ntstatus_to_werror(nt_status);
1519 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1520 * listed for this driver which has already been moved, skip it (note:
1521 * drivers may list the same file name several times. Then check if the
1522 * file already exists in archi\version\, if so, check that the version
1523 * info (or time stamps if version info is unavailable) is newer (or the
1524 * date is later). If it is, move it to archi\version\filexxx.yyy.
1525 * Otherwise, delete the file.
1527 * If a file is not moved to archi\version\ because of an error, all the
1528 * rest of the 'unmoved' driver files are removed from archi\. If one or
1529 * more of the driver's files was already moved to archi\version\, it
1530 * potentially leaves the driver in a partially updated state. Version
1531 * trauma will most likely occur if an client attempts to use any printer
1532 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1533 * done is appropriate... later JRR
1536 DEBUG(5,("Moving files now !\n"));
1538 if (driver->driver_path && strlen(driver->driver_path)) {
1540 err = move_driver_file_to_download_area(ctx,
1542 driver->driver_path,
1547 if (!W_ERROR_IS_OK(err)) {
1552 if (driver->data_file && strlen(driver->data_file)) {
1553 if (!strequal(driver->data_file, driver->driver_path)) {
1555 err = move_driver_file_to_download_area(ctx,
1562 if (!W_ERROR_IS_OK(err)) {
1568 if (driver->config_file && strlen(driver->config_file)) {
1569 if (!strequal(driver->config_file, driver->driver_path) &&
1570 !strequal(driver->config_file, driver->data_file)) {
1572 err = move_driver_file_to_download_area(ctx,
1574 driver->config_file,
1579 if (!W_ERROR_IS_OK(err)) {
1585 if (driver->help_file && strlen(driver->help_file)) {
1586 if (!strequal(driver->help_file, driver->driver_path) &&
1587 !strequal(driver->help_file, driver->data_file) &&
1588 !strequal(driver->help_file, driver->config_file)) {
1590 err = move_driver_file_to_download_area(ctx,
1597 if (!W_ERROR_IS_OK(err)) {
1603 if (driver->dependent_files && driver->dependent_files->string) {
1604 for (i=0; driver->dependent_files->string[i]; i++) {
1605 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1606 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1607 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1608 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1610 for (j=0; j < i; j++) {
1611 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1616 err = move_driver_file_to_download_area(ctx,
1618 driver->dependent_files->string[i],
1623 if (!W_ERROR_IS_OK(err)) {
1635 TALLOC_FREE(smb_dname);
1638 vfs_ChDir(conn, oldcwd_fname);
1639 TALLOC_FREE(oldcwd_fname);
1640 SMB_VFS_DISCONNECT(conn);
1647 /****************************************************************************
1648 Determine whether or not a particular driver is currently assigned
1650 ****************************************************************************/
1652 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1653 struct dcerpc_binding_handle *b,
1654 const struct spoolss_DriverInfo8 *r)
1657 int n_services = lp_numservices();
1658 bool in_use = false;
1659 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1666 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1668 /* loop through the printers.tdb and check for the drivername */
1670 for (snum=0; snum<n_services && !in_use; snum++) {
1671 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1675 result = winreg_get_printer(mem_ctx, b,
1676 lp_servicename(talloc_tos(), snum),
1678 if (!W_ERROR_IS_OK(result)) {
1679 continue; /* skip */
1682 if (strequal(r->driver_name, pinfo2->drivername)) {
1686 TALLOC_FREE(pinfo2);
1689 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1692 struct spoolss_DriverInfo8 *driver = NULL;
1695 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1697 /* we can still remove the driver if there is one of
1698 "Windows NT x86" version 2 or 3 left */
1700 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1701 if (r->version == 2) {
1702 werr = winreg_get_driver(mem_ctx, b,
1706 } else if (r->version == 3) {
1707 werr = winreg_get_driver(mem_ctx, b,
1712 DBG_ERR("Unknown driver version (%d)\n",
1714 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1716 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1717 werr = winreg_get_driver(mem_ctx, b,
1718 SPOOLSS_ARCHITECTURE_NT_X86,
1723 DBG_ERR("Unknown driver architecture: %s\n",
1725 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1728 /* now check the error code */
1730 if ( W_ERROR_IS_OK(werr) ) {
1731 /* it's ok to remove the driver, we have other architctures left */
1733 talloc_free(driver);
1737 /* report that the driver is not in use by default */
1743 /**********************************************************************
1744 Check to see if a ogiven file is in use by *info
1745 *********************************************************************/
1747 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1754 /* mz: skip files that are in the list but already deleted */
1755 if (!file || !file[0]) {
1759 if (strequal(file, info->driver_path))
1762 if (strequal(file, info->data_file))
1765 if (strequal(file, info->config_file))
1768 if (strequal(file, info->help_file))
1771 /* see of there are any dependent files to examine */
1773 if (!info->dependent_files)
1776 while (info->dependent_files[i] && *info->dependent_files[i]) {
1777 if (strequal(file, info->dependent_files[i]))
1786 /**********************************************************************
1787 Utility function to remove the dependent file pointed to by the
1788 input parameter from the list
1789 *********************************************************************/
1791 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1794 /* bump everything down a slot */
1796 while (files && files[idx+1]) {
1797 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1806 /**********************************************************************
1807 Check if any of the files used by src are also used by drv
1808 *********************************************************************/
1810 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1811 struct spoolss_DriverInfo8 *src,
1812 const struct spoolss_DriverInfo8 *drv)
1814 bool in_use = False;
1820 /* check each file. Remove it from the src structure if it overlaps */
1822 if (drv_file_in_use(src->driver_path, drv)) {
1824 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1825 src->driver_path = talloc_strdup(mem_ctx, "");
1826 if (!src->driver_path) { return false; }
1829 if (drv_file_in_use(src->data_file, drv)) {
1831 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1832 src->data_file = talloc_strdup(mem_ctx, "");
1833 if (!src->data_file) { return false; }
1836 if (drv_file_in_use(src->config_file, drv)) {
1838 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1839 src->config_file = talloc_strdup(mem_ctx, "");
1840 if (!src->config_file) { return false; }
1843 if (drv_file_in_use(src->help_file, drv)) {
1845 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1846 src->help_file = talloc_strdup(mem_ctx, "");
1847 if (!src->help_file) { return false; }
1850 /* are there any dependentfiles to examine? */
1852 if (!src->dependent_files)
1855 while (src->dependent_files[i] && *src->dependent_files[i]) {
1856 if (drv_file_in_use(src->dependent_files[i], drv)) {
1858 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1859 trim_dependent_file(mem_ctx, src->dependent_files, i);
1867 /****************************************************************************
1868 Determine whether or not a particular driver files are currently being
1869 used by any other driver.
1871 Return value is True if any files were in use by other drivers
1872 and False otherwise.
1874 Upon return, *info has been modified to only contain the driver files
1875 which are not in use
1879 This needs to check all drivers to ensure that all files in use
1880 have been removed from *info, not just the ones in the first
1882 ****************************************************************************/
1884 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1885 struct dcerpc_binding_handle *b,
1886 struct spoolss_DriverInfo8 *info)
1890 struct spoolss_DriverInfo8 *driver;
1891 bool in_use = false;
1892 uint32_t num_drivers;
1893 const char **drivers;
1899 version = info->version;
1901 /* loop over all driver versions */
1903 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1905 /* get the list of drivers */
1907 result = winreg_get_driver_list(mem_ctx, b,
1908 info->architecture, version,
1909 &num_drivers, &drivers);
1910 if (!W_ERROR_IS_OK(result)) {
1914 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1915 num_drivers, info->architecture, version));
1917 /* check each driver for overlap in files */
1919 for (i = 0; i < num_drivers; i++) {
1920 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1924 result = winreg_get_driver(mem_ctx, b,
1925 info->architecture, drivers[i],
1927 if (!W_ERROR_IS_OK(result)) {
1928 talloc_free(drivers);
1932 /* check if d2 uses any files from d1 */
1933 /* only if this is a different driver than the one being deleted */
1935 if (!strequal(info->driver_name, driver->driver_name)) {
1936 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1937 /* mz: Do not instantly return -
1938 * we need to ensure this file isn't
1939 * also in use by other drivers. */
1944 talloc_free(driver);
1947 talloc_free(drivers);
1949 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1954 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1955 const char *short_arch,
1959 TALLOC_CTX *tmp_ctx = talloc_new(conn);
1960 struct smb_filename *smb_fname = NULL;
1961 char *print_dlr_path;
1962 NTSTATUS status = NT_STATUS_NO_MEMORY;
1964 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
1965 short_arch, vers, fname);
1966 if (print_dlr_path == NULL) {
1970 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
1971 if (smb_fname == NULL) {
1975 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1977 talloc_free(tmp_ctx);
1981 /****************************************************************************
1982 Actually delete the driver files. Make sure that
1983 printer_driver_files_in_use() return False before calling
1985 ****************************************************************************/
1987 bool delete_driver_files(const struct auth_session_info *session_info,
1988 const struct spoolss_DriverInfo8 *r)
1990 const char *short_arch;
1991 connection_struct *conn;
1993 struct smb_filename *oldcwd_fname = NULL;
1994 char *printdollar = NULL;
1995 int printdollar_snum;
2002 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2003 r->driver_name, r->version));
2005 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
2009 if (printdollar_snum == -1) {
2013 nt_status = create_conn_struct_cwd(talloc_tos(),
2014 server_event_context(),
2015 server_messaging_context(),
2018 lp_path(talloc_tos(), printdollar_snum),
2019 session_info, &oldcwd_fname);
2020 if (!NT_STATUS_IS_OK(nt_status)) {
2021 DEBUG(0,("delete_driver_files: create_conn_struct "
2022 "returned %s\n", nt_errstr(nt_status)));
2026 nt_status = set_conn_force_user_group(conn, printdollar_snum);
2027 if (!NT_STATUS_IS_OK(nt_status)) {
2028 DEBUG(0, ("failed set force user / group\n"));
2033 if (!become_user_by_session(conn, session_info)) {
2034 DEBUG(0, ("failed to become user\n"));
2039 if ( !CAN_WRITE(conn) ) {
2040 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2045 short_arch = get_short_archi(r->architecture);
2046 if (short_arch == NULL) {
2047 DEBUG(0, ("bad architecture %s\n", r->architecture));
2052 /* now delete the files */
2054 if (r->driver_path && r->driver_path[0]) {
2055 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2056 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2059 if (r->config_file && r->config_file[0]) {
2060 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2061 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2064 if (r->data_file && r->data_file[0]) {
2065 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2066 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2069 if (r->help_file && r->help_file[0]) {
2070 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2071 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2074 if (r->dependent_files) {
2076 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2077 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2078 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2088 vfs_ChDir(conn, oldcwd_fname);
2089 TALLOC_FREE(oldcwd_fname);
2090 SMB_VFS_DISCONNECT(conn);
2098 1: level not implemented
2099 2: file doesn't exist
2100 3: can't allocate memory
2101 4: can't free memory
2102 5: non existent struct
2106 A printer and a printer driver are 2 different things.
2107 NT manages them separatelly, Samba does the same.
2108 Why ? Simply because it's easier and it makes sense !
2110 Now explanation: You have 3 printers behind your samba server,
2111 2 of them are the same make and model (laser A and B). But laser B
2112 has an 3000 sheet feeder and laser A doesn't such an option.
2113 Your third printer is an old dot-matrix model for the accounting :-).
2115 If the /usr/local/samba/lib directory (default dir), you will have
2116 5 files to describe all of this.
2118 3 files for the printers (1 by printer):
2121 NTprinter_accounting
2122 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2123 NTdriver_printer model X
2124 NTdriver_printer model Y
2126 jfm: I should use this comment for the text file to explain
2127 same thing for the forms BTW.
2128 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2132 /* Convert generic access rights to printer object specific access rights.
2133 It turns out that NT4 security descriptors use generic access rights and
2134 NT5 the object specific ones. */
2136 void map_printer_permissions(struct security_descriptor *sd)
2140 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2141 se_map_generic(&sd->dacl->aces[i].access_mask,
2142 &printer_generic_mapping);
2146 void map_job_permissions(struct security_descriptor *sd)
2150 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2151 se_map_generic(&sd->dacl->aces[i].access_mask,
2152 &job_generic_mapping);
2157 /****************************************************************************
2158 Check a user has permissions to perform the given operation. We use the
2159 permission constants defined in include/rpc_spoolss.h to check the various
2160 actions we perform when checking printer access.
2162 PRINTER_ACCESS_ADMINISTER:
2163 print_queue_pause, print_queue_resume, update_printer_sec,
2164 update_printer, spoolss_addprinterex_level_2,
2165 _spoolss_setprinterdata
2170 JOB_ACCESS_ADMINISTER:
2171 print_job_delete, print_job_pause, print_job_resume,
2174 Try access control in the following order (for performance reasons):
2175 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2176 2) check security descriptor (bit comparisons in memory)
2177 3) "printer admins" (may result in numerous calls to winbind)
2179 ****************************************************************************/
2180 WERROR print_access_check(const struct auth_session_info *session_info,
2181 struct messaging_context *msg_ctx, int snum,
2184 struct spoolss_security_descriptor *secdesc = NULL;
2185 uint32_t access_granted;
2190 TALLOC_CTX *mem_ctx = NULL;
2192 /* If user is NULL then use the current_user structure */
2194 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2196 if ((session_info->unix_token->uid == sec_initial_uid())
2197 || security_token_has_privilege(session_info->security_token,
2198 SEC_PRIV_PRINT_OPERATOR)) {
2202 /* Get printer name */
2204 pname = lp_printername(talloc_tos(), snum);
2206 if (!pname || !*pname) {
2207 return WERR_ACCESS_DENIED;
2210 /* Get printer security descriptor */
2212 if(!(mem_ctx = talloc_init("print_access_check"))) {
2213 return WERR_NOT_ENOUGH_MEMORY;
2216 result = winreg_get_printer_secdesc_internal(mem_ctx,
2217 get_session_info_system(),
2221 if (!W_ERROR_IS_OK(result)) {
2222 talloc_destroy(mem_ctx);
2223 return WERR_NOT_ENOUGH_MEMORY;
2226 if (access_type == JOB_ACCESS_ADMINISTER) {
2227 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2229 /* Create a child security descriptor to check permissions
2230 against. This is because print jobs are child objects
2231 objects of a printer. */
2232 status = se_create_child_secdesc(mem_ctx,
2236 parent_secdesc->owner_sid,
2237 parent_secdesc->group_sid,
2239 if (!NT_STATUS_IS_OK(status)) {
2240 talloc_destroy(mem_ctx);
2241 return ntstatus_to_werror(status);
2244 map_job_permissions(secdesc);
2246 map_printer_permissions(secdesc);
2250 status = se_access_check(secdesc, session_info->security_token, access_type,
2253 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2255 talloc_destroy(mem_ctx);
2257 return ntstatus_to_werror(status);
2260 /****************************************************************************
2261 Check the time parameters allow a print operation.
2262 *****************************************************************************/
2264 bool print_time_access_check(const struct auth_session_info *session_info,
2265 struct messaging_context *msg_ctx,
2266 const char *servicename)
2268 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2271 time_t now = time(NULL);
2275 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2276 servicename, &pinfo2);
2277 if (!W_ERROR_IS_OK(result)) {
2281 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2286 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2288 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2292 TALLOC_FREE(pinfo2);
2301 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2302 const struct auth_session_info *session_info,
2303 struct messaging_context *msg_ctx,
2304 const char *printer)
2308 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2310 if (!W_ERROR_IS_OK(result)) {
2311 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2312 "%s\n", printer, win_errstr(result)));
2316 void nt_printer_add(TALLOC_CTX *mem_ctx,
2317 const struct auth_session_info *session_info,
2318 struct messaging_context *msg_ctx,
2319 const char *printer)
2323 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2325 if (!W_ERROR_IS_OK(result)) {
2326 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2327 printer, win_errstr(result)));