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 struct loadparm_substitution
*lp_sub
=
84 loadparm_s3_global_substitution();
86 const char *dir_list
[] = {
92 service
= lp_servicenumber("print$");
94 /* We don't have a print$ share */
95 DEBUG(5, ("No print$ share has been configured.\n"));
100 driver_path
= lp_path(mem_ctx
, lp_sub
, service
);
101 if (driver_path
== NULL
) {
102 talloc_free(mem_ctx
);
106 ok
= directory_create_or_exist(driver_path
, 0755);
108 DEBUG(1, ("Failed to create printer driver directory %s\n",
110 talloc_free(mem_ctx
);
114 for (i
= 0; archi_table
[i
].long_archi
!= NULL
; i
++) {
115 const char *arch_path
;
117 arch_path
= talloc_asprintf(mem_ctx
,
120 archi_table
[i
].short_archi
);
121 if (arch_path
== NULL
) {
122 talloc_free(mem_ctx
);
126 ok
= directory_create_or_exist(arch_path
, 0755);
128 DEBUG(1, ("Failed to create printer driver "
129 "architecture directory %s\n",
131 talloc_free(mem_ctx
);
136 for (i
= 0; i
< ARRAY_SIZE(dir_list
); i
++) {
139 path
= talloc_asprintf(mem_ctx
,
144 talloc_free(mem_ctx
);
148 ok
= directory_create_or_exist(path
, 0755);
150 DEBUG(1, ("Failed to create printer driver "
151 "architecture directory %s\n",
153 talloc_free(mem_ctx
);
158 driver_path
= state_path(talloc_tos(), "DriverStore");
159 if (driver_path
== NULL
) {
160 talloc_free(mem_ctx
);
164 ok
= directory_create_or_exist(driver_path
, 0755);
166 DEBUG(1,("failed to create path %s\n", driver_path
));
167 talloc_free(mem_ctx
);
171 driver_path
= state_path(talloc_tos(), "DriverStore/FileRepository");
172 if (driver_path
== NULL
) {
173 talloc_free(mem_ctx
);
177 ok
= directory_create_or_exist(driver_path
, 0755);
179 DEBUG(1,("failed to create path %s\n", driver_path
));
180 talloc_free(mem_ctx
);
184 driver_path
= state_path(talloc_tos(), "DriverStore/Temp");
185 if (driver_path
== NULL
) {
186 talloc_free(mem_ctx
);
190 ok
= directory_create_or_exist(driver_path
, 0755);
192 DEBUG(1,("failed to create path %s\n", driver_path
));
193 talloc_free(mem_ctx
);
197 talloc_free(mem_ctx
);
201 /****************************************************************************
202 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
203 background lpq updater.
204 ****************************************************************************/
206 static void forward_drv_upgrade_printer_msg(struct messaging_context
*msg
,
209 struct server_id server_id
,
212 extern pid_t background_lpq_updater_pid
;
214 if (background_lpq_updater_pid
== -1) {
215 DEBUG(3,("no background lpq queue updater\n"));
219 messaging_send_buf(msg
,
220 pid_to_procid(background_lpq_updater_pid
),
221 MSG_PRINTER_DRVUPGRADE
,
226 /****************************************************************************
227 Open the NT printing tdbs. Done once before fork().
228 ****************************************************************************/
230 bool nt_printing_init(struct messaging_context
*msg_ctx
)
234 if (!print_driver_directories_init()) {
238 if (!nt_printing_tdb_upgrade()) {
243 * register callback to handle updating printers as new
244 * drivers are installed. Forwards to background lpq updater.
246 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
247 forward_drv_upgrade_printer_msg
);
249 if ( lp_security() == SEC_ADS
) {
250 win_rc
= check_published_printers(msg_ctx
);
251 if (!W_ERROR_IS_OK(win_rc
))
252 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
258 /*******************************************************************
259 Function to allow filename parsing "the old way".
260 ********************************************************************/
262 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
263 const char *old_name
,
264 struct smb_filename
**smb_fname
)
267 TALLOC_CTX
*ctx
= talloc_tos();
268 char *name
= talloc_strdup(ctx
, old_name
);
271 return NT_STATUS_NO_MEMORY
;
274 name
= unix_clean_name(ctx
, name
);
276 return NT_STATUS_NO_MEMORY
;
278 trim_string(name
,"/","/");
280 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
281 if (!NT_STATUS_IS_OK(status
)) {
282 return NT_STATUS_NO_MEMORY
;
288 /****************************************************************************
289 Function to do the mapping between the long architecture name and
291 ****************************************************************************/
293 const char *get_short_archi(const char *long_archi
)
297 DEBUG(107,("Getting architecture dependent directory\n"));
300 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
301 strcasecmp_m(long_archi
, archi_table
[i
].long_archi
) );
303 if (archi_table
[i
].long_archi
==NULL
) {
304 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
308 /* this might be client code - but shouldn't this be an fstrcpy etc? */
310 DEBUGADD(108,("index: [%d]\n", i
));
311 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
312 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
314 return archi_table
[i
].short_archi
;
317 /****************************************************************************
318 Read data from fsp on the vfs.
319 ****************************************************************************/
321 static ssize_t
printing_pread_data(files_struct
*fsp
,
327 off_t in_pos
= *poff
;
329 /* Don't allow integer wrap on read. */
330 if (in_pos
+ byte_count
< in_pos
) {
334 while (total
< byte_count
) {
335 ssize_t ret
= read_file(fsp
,
345 if (errno
== EINTR
) {
355 return (ssize_t
)total
;
358 /****************************************************************************
359 Detect the major and minor version of a PE file.
362 1 if file is a PE file and we got version numbers,
363 0 if this file is a PE file and we couldn't get the version numbers,
366 NB. buf is passed into and freed inside this function. This is a
367 bad API design, but fixing this is a task for another day.
368 ****************************************************************************/
370 static int handle_pe_file(files_struct
*fsp
,
378 unsigned int num_sections
;
379 unsigned int section_table_bytes
;
384 /* Just skip over optional header to get to section table */
385 rel_pos
= SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-
386 (NE_HEADER_SIZE
-PE_HEADER_SIZE
);
388 if (in_pos
+ rel_pos
< in_pos
) {
392 in_pos
= rel_pos
+ in_pos
;
394 /* get the section table */
395 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
397 if (num_sections
>= (UINT_MAX
/ PE_HEADER_SECT_HEADER_SIZE
)) {
402 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
403 if (section_table_bytes
== 0) {
408 buf
= (char *)SMB_MALLOC(section_table_bytes
);
410 DBG_ERR("PE file [%s] section table malloc "
411 "failed bytes = %d\n",
413 section_table_bytes
);
417 byte_count
= printing_pread_data(fsp
, buf
, &in_pos
, section_table_bytes
);
418 if (byte_count
< section_table_bytes
) {
419 DBG_NOTICE("PE file [%s] Section header too short, "
420 "bytes read = %lu\n",
422 (unsigned long)byte_count
);
427 * Iterate the section table looking for
428 * the resource section ".rsrc"
430 for (i
= 0; i
< num_sections
; i
++) {
431 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
434 &buf
[sec_offset
+ PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
435 unsigned int section_pos
= IVAL(buf
,
437 PE_HEADER_SECT_PTR_DATA_OFFSET
);
438 unsigned int section_bytes
= IVAL(buf
,
440 PE_HEADER_SECT_SIZE_DATA_OFFSET
);
442 if (section_bytes
== 0) {
447 buf
=(char *)SMB_MALLOC(section_bytes
);
449 DBG_ERR("PE file [%s] version malloc "
450 "failed bytes = %d\n",
457 * Read from the start of the .rsrc
460 in_pos
= section_pos
;
462 byte_count
= printing_pread_data(fsp
,
466 if (byte_count
< section_bytes
) {
467 DBG_NOTICE("PE file "
468 "[%s] .rsrc section too short, "
469 "bytes read = %lu\n",
471 (unsigned long)byte_count
);
475 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
) {
480 i
< section_bytes
- VS_VERSION_INFO_UNICODE_SIZE
;
483 * Scan for 1st 3 unicoded bytes
484 * followed by word aligned magic
488 bool magic_match
= false;
496 if (magic_match
== false) {
500 /* Align to next long address */
501 mpos
= (i
+ sizeof(VS_SIGNATURE
)*2 +
504 if (IVAL(buf
,mpos
) == VS_MAGIC_VALUE
) {
506 mpos
+ VS_MAJOR_OFFSET
);
508 mpos
+ VS_MINOR_OFFSET
);
510 DBG_INFO("PE file [%s] Version = "
511 "%08x:%08x (%d.%d.%d.%d)\n",
526 /* Version info not found, fall back to origin date/time */
527 DBG_DEBUG("PE file [%s] has no version info\n", fname
);
536 /****************************************************************************
537 Detect the major and minor version of an NE file.
540 1 if file is an NE file and we got version numbers,
541 0 if this file is an NE file and we couldn't get the version numbers,
544 NB. buf is passed into and freed inside this function. This is a
545 bad API design, but fixing this is a task for another day.
546 ****************************************************************************/
548 static int handle_ne_file(files_struct
*fsp
,
559 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
560 DBG_NOTICE("NE file [%s] wrong target OS = 0x%x\n",
562 CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
));
564 * At this point, we assume the file is in error.
565 * It still could be something else besides a NE file,
566 * but it unlikely at this point.
571 /* Allocate a bit more space to speed up things */
573 buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
);
575 DBG_ERR("NE file [%s] malloc failed bytes = %d\n",
582 * This is a HACK! I got tired of trying to sort through the
583 * messy 'NE' file format. If anyone wants to clean this up
584 * please have at it, but this works. 'NE' files will
585 * eventually fade away. JRR
587 byte_count
= printing_pread_data(fsp
, buf
, &in_pos
, VS_NE_BUF_SIZE
);
588 while (byte_count
> 0) {
590 * Cover case that should not occur in a well
591 * formed 'NE' .dll file
593 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) {
597 for(i
=0; i
<byte_count
; i
++) {
599 * Fast skip past data that can't
603 byte_count
= printing_pread_data(fsp
,
611 * Potential match data crosses buf boundry,
612 * move it to beginning of buf, and fill the
613 * buf with as much as it will hold.
615 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
617 ssize_t amount_unused
= byte_count
-i
;
619 memmove(buf
, &buf
[i
], amount_unused
);
620 amount_read
= printing_pread_data(fsp
,
623 VS_NE_BUF_SIZE
- amount_unused
);
624 if (amount_read
< 0) {
625 DBG_ERR("NE file [%s] Read "
632 if (amount_read
+ amount_unused
<
634 /* Check for integer wrap. */
638 byte_count
= amount_read
+
640 if (byte_count
< VS_VERSION_INFO_SIZE
) {
648 * Check that the full signature string and
649 * the magic number that follows exist (not
650 * a perfect solution, but the chances that this
651 * occurs in code is, well, remote. Yes I know
652 * I'm comparing the 'V' twice, as it is
653 * simpler to read the code.
655 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
657 * Compute skip alignment to next
661 int skip
= -(cpos
- (byte_count
- i
) +
662 sizeof(VS_SIGNATURE
)) & 3;
664 i
+sizeof(VS_SIGNATURE
)+skip
)
666 byte_count
= printing_pread_data(fsp
,
674 i
+sizeof(VS_SIGNATURE
)+
675 skip
+VS_MAJOR_OFFSET
);
677 i
+sizeof(VS_SIGNATURE
)+
678 skip
+VS_MINOR_OFFSET
);
679 DBG_INFO("NE file [%s] Version "
680 "= %08x:%08x (%d.%d.%d.%d)\n",
694 /* Version info not found, fall back to origin date/time */
695 DBG_ERR("NE file [%s] Version info not found\n", fname
);
704 /****************************************************************************
705 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
706 There are two case to be covered here: PE (Portable Executable) and NE (New
707 Executable) files. Both files support the same INFO structure, but PE files
708 store the signature in unicode, and NE files store it as !unicode.
709 returns -1 on error, 1 on version info found, and 0 on no version info found.
710 ****************************************************************************/
712 static int get_file_version(files_struct
*fsp
,
719 off_t in_pos
= fsp
->fh
->pos
;
721 buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
);
723 DBG_ERR("PE file [%s] DOS Header malloc failed bytes = %d\n",
729 byte_count
= printing_pread_data(fsp
, buf
, &in_pos
, DOS_HEADER_SIZE
);
730 if (byte_count
< DOS_HEADER_SIZE
) {
731 DBG_NOTICE("File [%s] DOS header too short, bytes read = %lu\n",
733 (unsigned long)byte_count
);
734 goto no_version_info
;
737 /* Is this really a DOS header? */
738 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
739 DBG_INFO("File [%s] bad DOS magic = 0x%x\n",
741 SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
));
742 goto no_version_info
;
746 * Skip OEM header (if any) and the
747 * DOS stub to start of Windows header.
749 in_pos
= SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
);
751 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
752 byte_count
= printing_pread_data(fsp
, buf
, &in_pos
, NE_HEADER_SIZE
);
753 if (byte_count
< NE_HEADER_SIZE
) {
754 DBG_NOTICE("File [%s] Windows header too short, "
755 "bytes read = %lu\n",
757 (unsigned long)byte_count
);
759 * Assume this isn't an error...
760 * the file just looks sort of like a PE/NE file
762 goto no_version_info
;
766 * The header may be a PE (Portable Executable)
767 * or an NE (New Executable).
769 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
770 return handle_pe_file(fsp
,
776 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) ==
777 NE_HEADER_SIGNATURE
) {
778 return handle_ne_file(fsp
,
786 * Assume this isn't an error... the file just
787 * looks sort of like a PE/NE file.
789 DBG_NOTICE("File [%s] unknown file format, signature = 0x%x\n",
791 IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
));
792 /* Fallthrough into no_version_info: */
804 /****************************************************************************
805 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
806 share one or more files. During the MS installation process files are checked
807 to insure that only a newer version of a shared file is installed over an
808 older version. There are several possibilities for this comparison. If there
809 is no previous version, the new one is newer (obviously). If either file is
810 missing the version info structure, compare the creation date (on Unix use
811 the modification date). Otherwise chose the numerically larger version number.
812 ****************************************************************************/
814 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
816 bool use_version
= true;
820 time_t new_create_time
;
824 time_t old_create_time
;
826 struct smb_filename
*smb_fname
= NULL
;
827 files_struct
*fsp
= NULL
;
833 SET_STAT_INVALID(st
);
834 new_create_time
= (time_t)0;
835 old_create_time
= (time_t)0;
837 /* Get file version info (if available) for previous file (if it exists) */
838 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
839 if (!NT_STATUS_IS_OK(status
)) {
843 status
= SMB_VFS_CREATE_FILE(
846 0, /* root_dir_fid */
847 smb_fname
, /* fname */
848 FILE_GENERIC_READ
, /* access_mask */
849 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
850 FILE_OPEN
, /* create_disposition*/
851 0, /* create_options */
852 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
853 INTERNAL_OPEN_ONLY
, /* oplock_request */
855 0, /* allocation_size */
856 0, /* private_flags */
861 NULL
, NULL
); /* create context */
863 if (!NT_STATUS_IS_OK(status
)) {
864 /* Old file not found, so by definition new file is in fact newer */
865 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
866 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
872 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
878 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
881 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
884 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
885 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
886 (long)old_create_time
));
889 close_file(NULL
, fsp
, NORMAL_CLOSE
);
892 /* Get file version info (if available) for new file */
893 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
894 if (!NT_STATUS_IS_OK(status
)) {
898 status
= SMB_VFS_CREATE_FILE(
901 0, /* root_dir_fid */
902 smb_fname
, /* fname */
903 FILE_GENERIC_READ
, /* access_mask */
904 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
905 FILE_OPEN
, /* create_disposition*/
906 0, /* create_options */
907 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
908 INTERNAL_OPEN_ONLY
, /* oplock_request */
910 0, /* allocation_size */
911 0, /* private_flags */
916 NULL
, NULL
); /* create context */
918 if (!NT_STATUS_IS_OK(status
)) {
919 /* New file not found, this shouldn't occur if the caller did its job */
920 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
921 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
925 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
931 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
934 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
937 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
938 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
939 (long)new_create_time
));
942 close_file(NULL
, fsp
, NORMAL_CLOSE
);
945 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
946 /* Compare versions and choose the larger version number */
947 if (new_major
> old_major
||
948 (new_major
== old_major
&& new_minor
> old_minor
)) {
950 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
955 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
961 /* Compare modification time/dates and choose the newest time/date */
962 if (new_create_time
> old_create_time
) {
963 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
968 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
976 close_file(NULL
, fsp
, NORMAL_CLOSE
);
979 TALLOC_FREE(smb_fname
);
983 /****************************************************************************
984 Determine the correct cVersion associated with an architecture and driver
985 ****************************************************************************/
986 static uint32_t get_correct_cversion(const struct auth_session_info
*session_info
,
987 const char *architecture
,
988 const char *driverpath_in
,
989 const char *driver_directory
,
992 TALLOC_CTX
*frame
= talloc_stackframe();
993 const struct loadparm_substitution
*lp_sub
=
994 loadparm_s3_global_substitution();
997 struct smb_filename
*smb_fname
= NULL
;
998 files_struct
*fsp
= NULL
;
999 struct conn_struct_tos
*c
= NULL
;
1000 connection_struct
*conn
= NULL
;
1001 char *printdollar
= NULL
;
1002 char *printdollar_path
= NULL
;
1003 char *working_dir
= NULL
;
1004 int printdollar_snum
;
1006 *perr
= WERR_INVALID_PARAMETER
;
1008 /* If architecture is Windows 95/98/ME, the version is always 0. */
1009 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1010 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1016 /* If architecture is Windows x64, the version is always 3. */
1017 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1018 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1024 printdollar_snum
= find_service(frame
, "print$", &printdollar
);
1026 *perr
= WERR_NOT_ENOUGH_MEMORY
;
1030 if (printdollar_snum
== -1) {
1031 *perr
= WERR_BAD_NET_NAME
;
1036 printdollar_path
= lp_path(frame
, lp_sub
, printdollar_snum
);
1037 if (printdollar_path
== NULL
) {
1038 *perr
= WERR_NOT_ENOUGH_MEMORY
;
1043 working_dir
= talloc_asprintf(frame
,
1048 * If the driver has been uploaded into a temorpary driver
1049 * directory, switch to the driver directory.
1051 if (driver_directory
!= NULL
) {
1052 working_dir
= talloc_asprintf(frame
, "%s/%s/%s",
1058 nt_status
= create_conn_struct_tos_cwd(global_messaging_context(),
1063 if (!NT_STATUS_IS_OK(nt_status
)) {
1064 DEBUG(0,("get_correct_cversion: create_conn_struct "
1065 "returned %s\n", nt_errstr(nt_status
)));
1066 *perr
= ntstatus_to_werror(nt_status
);
1072 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1073 if (!NT_STATUS_IS_OK(nt_status
)) {
1074 DEBUG(0, ("failed set force user / group\n"));
1075 *perr
= ntstatus_to_werror(nt_status
);
1076 goto error_free_conn
;
1079 if (!become_user_without_service_by_session(conn
, session_info
)) {
1080 DEBUG(0, ("failed to become user\n"));
1081 *perr
= WERR_ACCESS_DENIED
;
1082 goto error_free_conn
;
1086 * We switch to the directory where the driver files are located,
1087 * so only work on the file names
1089 nt_status
= driver_unix_convert(conn
, driverpath_in
, &smb_fname
);
1090 if (!NT_STATUS_IS_OK(nt_status
)) {
1091 *perr
= ntstatus_to_werror(nt_status
);
1095 nt_status
= vfs_file_exist(conn
, smb_fname
);
1096 if (!NT_STATUS_IS_OK(nt_status
)) {
1097 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1098 *perr
= WERR_FILE_NOT_FOUND
;
1102 nt_status
= SMB_VFS_CREATE_FILE(
1105 0, /* root_dir_fid */
1106 smb_fname
, /* fname */
1107 FILE_GENERIC_READ
, /* access_mask */
1108 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1109 FILE_OPEN
, /* create_disposition*/
1110 0, /* create_options */
1111 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1112 INTERNAL_OPEN_ONLY
, /* oplock_request */
1114 0, /* private_flags */
1115 0, /* allocation_size */
1120 NULL
, NULL
); /* create context */
1122 if (!NT_STATUS_IS_OK(nt_status
)) {
1123 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1124 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
1125 *perr
= WERR_ACCESS_DENIED
;
1132 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
1134 *perr
= WERR_INVALID_PARAMETER
;
1137 DEBUG(6,("get_correct_cversion: Version info not "
1139 smb_fname_str_dbg(smb_fname
)));
1140 *perr
= WERR_INVALID_PARAMETER
;
1145 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1146 * for more details. Version in this case is not just the version of the
1147 * file, but the version in the sense of kernal mode (2) vs. user mode
1148 * (3) drivers. Other bits of the version fields are the version info.
1151 cversion
= major
& 0x0000ffff;
1153 case 2: /* WinNT drivers */
1154 case 3: /* Win2K drivers */
1158 DEBUG(6,("get_correct_cversion: cversion "
1159 "invalid [%s] cversion = %d\n",
1160 smb_fname_str_dbg(smb_fname
),
1165 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1166 " = 0x%x minor = 0x%x\n",
1167 smb_fname_str_dbg(smb_fname
), major
, minor
));
1170 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1171 smb_fname_str_dbg(smb_fname
), cversion
));
1175 unbecome_user_without_service();
1178 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1180 if (!W_ERROR_IS_OK(*perr
)) {
1188 /****************************************************************************
1189 ****************************************************************************/
1191 #define strip_driver_path(_mem_ctx, _element) do { \
1192 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1193 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1194 W_ERROR_HAVE_NO_MEMORY((_element)); \
1198 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
1199 const struct auth_session_info
*session_info
,
1200 const char *architecture
,
1201 const char **driver_path
,
1202 const char **data_file
,
1203 const char **config_file
,
1204 const char **help_file
,
1205 struct spoolss_StringArray
*dependent_files
,
1206 enum spoolss_DriverOSVersion
*version
,
1208 const char **driver_directory
)
1210 const char *short_architecture
;
1215 if (!*driver_path
|| !*data_file
) {
1216 return WERR_INVALID_PARAMETER
;
1219 if (!strequal(architecture
, SPOOLSS_ARCHITECTURE_4_0
) && !*config_file
) {
1220 return WERR_INVALID_PARAMETER
;
1223 if (flags
& APD_COPY_FROM_DIRECTORY
) {
1228 * driver_path is set to:
1230 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1232 path
= talloc_strdup(mem_ctx
, *driver_path
);
1234 return WERR_NOT_ENOUGH_MEMORY
;
1237 /* Remove pscript5.dll */
1238 q
= strrchr_m(path
, '\\');
1240 return WERR_INVALID_PARAMETER
;
1244 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1245 q
= strrchr_m(path
, '\\');
1247 return WERR_INVALID_PARAMETER
;
1251 * Set driver_directory to:
1253 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1255 * This is the directory where all the files have been uploaded
1257 *driver_directory
= q
+ 1;
1260 /* clean up the driver name.
1261 * we can get .\driver.dll
1262 * or worse c:\windows\system\driver.dll !
1264 /* using an intermediate string to not have overlaping memcpy()'s */
1266 strip_driver_path(mem_ctx
, *driver_path
);
1267 strip_driver_path(mem_ctx
, *data_file
);
1269 strip_driver_path(mem_ctx
, *config_file
);
1272 strip_driver_path(mem_ctx
, *help_file
);
1275 if (dependent_files
&& dependent_files
->string
) {
1276 for (i
=0; dependent_files
->string
[i
]; i
++) {
1277 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
1281 short_architecture
= get_short_archi(architecture
);
1282 if (!short_architecture
) {
1283 return WERR_UNKNOWN_PRINTER_DRIVER
;
1286 /* jfm:7/16/2000 the client always sends the cversion=0.
1287 * The server should check which version the driver is by reading
1288 * the PE header of driver->driverpath.
1290 * For Windows 95/98 the version is 0 (so the value sent is correct)
1291 * For Windows NT (the architecture doesn't matter)
1292 * NT 3.1: cversion=0
1293 * NT 3.5/3.51: cversion=1
1298 *version
= get_correct_cversion(session_info
,
1303 if (*version
== -1) {
1310 /****************************************************************************
1311 ****************************************************************************/
1313 WERROR
clean_up_driver_struct(TALLOC_CTX
*mem_ctx
,
1314 const struct auth_session_info
*session_info
,
1315 const struct spoolss_AddDriverInfoCtr
*r
,
1317 const char **driver_directory
)
1321 return clean_up_driver_struct_level(mem_ctx
, session_info
,
1322 r
->info
.info3
->architecture
,
1323 &r
->info
.info3
->driver_path
,
1324 &r
->info
.info3
->data_file
,
1325 &r
->info
.info3
->config_file
,
1326 &r
->info
.info3
->help_file
,
1327 r
->info
.info3
->dependent_files
,
1328 &r
->info
.info3
->version
,
1332 return clean_up_driver_struct_level(mem_ctx
, session_info
,
1333 r
->info
.info6
->architecture
,
1334 &r
->info
.info6
->driver_path
,
1335 &r
->info
.info6
->data_file
,
1336 &r
->info
.info6
->config_file
,
1337 &r
->info
.info6
->help_file
,
1338 r
->info
.info6
->dependent_files
,
1339 &r
->info
.info6
->version
,
1343 return clean_up_driver_struct_level(mem_ctx
, session_info
,
1344 r
->info
.info8
->architecture
,
1345 &r
->info
.info8
->driver_path
,
1346 &r
->info
.info8
->data_file
,
1347 &r
->info
.info8
->config_file
,
1348 &r
->info
.info8
->help_file
,
1349 r
->info
.info8
->dependent_files
,
1350 &r
->info
.info8
->version
,
1354 return WERR_NOT_SUPPORTED
;
1358 /****************************************************************************
1359 This function sucks and should be replaced. JRA.
1360 ****************************************************************************/
1362 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1363 const struct spoolss_AddDriverInfo6
*src
)
1365 dst
->version
= src
->version
;
1367 dst
->driver_name
= src
->driver_name
;
1368 dst
->architecture
= src
->architecture
;
1369 dst
->driver_path
= src
->driver_path
;
1370 dst
->data_file
= src
->data_file
;
1371 dst
->config_file
= src
->config_file
;
1372 dst
->help_file
= src
->help_file
;
1373 dst
->monitor_name
= src
->monitor_name
;
1374 dst
->default_datatype
= src
->default_datatype
;
1375 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1376 dst
->dependent_files
= src
->dependent_files
;
1379 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1380 const struct spoolss_AddDriverInfo8
*src
)
1382 dst
->version
= src
->version
;
1384 dst
->driver_name
= src
->driver_name
;
1385 dst
->architecture
= src
->architecture
;
1386 dst
->driver_path
= src
->driver_path
;
1387 dst
->data_file
= src
->data_file
;
1388 dst
->config_file
= src
->config_file
;
1389 dst
->help_file
= src
->help_file
;
1390 dst
->monitor_name
= src
->monitor_name
;
1391 dst
->default_datatype
= src
->default_datatype
;
1392 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1393 dst
->dependent_files
= src
->dependent_files
;
1396 /****************************************************************************
1397 ****************************************************************************/
1399 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
1400 connection_struct
*conn
,
1401 const char *driver_file
,
1402 const char *short_architecture
,
1403 uint32_t driver_version
,
1405 const char *driver_directory
)
1407 struct smb_filename
*smb_fname_old
= NULL
;
1408 struct smb_filename
*smb_fname_new
= NULL
;
1409 char *old_name
= NULL
;
1410 char *new_name
= NULL
;
1414 if (driver_directory
!= NULL
) {
1415 old_name
= talloc_asprintf(mem_ctx
,
1421 old_name
= talloc_asprintf(mem_ctx
,
1426 if (old_name
== NULL
) {
1427 return WERR_NOT_ENOUGH_MEMORY
;
1430 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
1431 short_architecture
, driver_version
, driver_file
);
1432 if (new_name
== NULL
) {
1433 TALLOC_FREE(old_name
);
1434 return WERR_NOT_ENOUGH_MEMORY
;
1437 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
1439 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
1440 if (!NT_STATUS_IS_OK(status
)) {
1441 ret
= WERR_NOT_ENOUGH_MEMORY
;
1445 /* Setup a synthetic smb_filename struct */
1446 smb_fname_new
= talloc_zero(mem_ctx
, struct smb_filename
);
1447 if (!smb_fname_new
) {
1448 ret
= WERR_NOT_ENOUGH_MEMORY
;
1452 smb_fname_new
->base_name
= new_name
;
1454 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1455 "'%s'\n", smb_fname_old
->base_name
,
1456 smb_fname_new
->base_name
));
1458 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
1459 OPENX_FILE_EXISTS_TRUNCATE
|
1460 OPENX_FILE_CREATE_IF_NOT_EXIST
,
1463 if (!NT_STATUS_IS_OK(status
)) {
1464 DEBUG(0,("move_driver_file_to_download_area: Unable "
1465 "to rename [%s] to [%s]: %s\n",
1466 smb_fname_old
->base_name
, new_name
,
1467 nt_errstr(status
)));
1468 ret
= WERR_APP_INIT_FAILURE
;
1475 TALLOC_FREE(smb_fname_old
);
1476 TALLOC_FREE(smb_fname_new
);
1480 WERROR
move_driver_to_download_area(const struct auth_session_info
*session_info
,
1481 const struct spoolss_AddDriverInfoCtr
*r
,
1482 const char *driver_directory
)
1484 TALLOC_CTX
*frame
= talloc_stackframe();
1485 const struct loadparm_substitution
*lp_sub
=
1486 loadparm_s3_global_substitution();
1487 struct spoolss_AddDriverInfo3
*driver
;
1488 struct spoolss_AddDriverInfo3 converted_driver
;
1489 const char *short_architecture
;
1490 struct smb_filename
*smb_dname
= NULL
;
1491 char *new_dir
= NULL
;
1492 struct conn_struct_tos
*c
= NULL
;
1493 connection_struct
*conn
= NULL
;
1497 char *printdollar
= NULL
;
1498 int printdollar_snum
;
1499 WERROR err
= WERR_OK
;
1503 driver
= r
->info
.info3
;
1506 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
1507 driver
= &converted_driver
;
1510 convert_level_8_to_level3(&converted_driver
, r
->info
.info8
);
1511 driver
= &converted_driver
;
1514 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
1516 return WERR_INVALID_LEVEL
;
1519 short_architecture
= get_short_archi(driver
->architecture
);
1520 if (!short_architecture
) {
1522 return WERR_UNKNOWN_PRINTER_DRIVER
;
1525 printdollar_snum
= find_service(frame
, "print$", &printdollar
);
1528 return WERR_NOT_ENOUGH_MEMORY
;
1530 if (printdollar_snum
== -1) {
1532 return WERR_BAD_NET_NAME
;
1535 nt_status
= create_conn_struct_tos_cwd(global_messaging_context(),
1537 lp_path(frame
, lp_sub
, printdollar_snum
),
1540 if (!NT_STATUS_IS_OK(nt_status
)) {
1541 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1542 "returned %s\n", nt_errstr(nt_status
)));
1543 err
= ntstatus_to_werror(nt_status
);
1549 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1550 if (!NT_STATUS_IS_OK(nt_status
)) {
1551 DEBUG(0, ("failed set force user / group\n"));
1552 err
= ntstatus_to_werror(nt_status
);
1556 if (!become_user_without_service_by_session(conn
, session_info
)) {
1557 DEBUG(0, ("failed to become user\n"));
1558 err
= WERR_ACCESS_DENIED
;
1562 new_dir
= talloc_asprintf(frame
,
1567 err
= WERR_NOT_ENOUGH_MEMORY
;
1570 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1571 if (!NT_STATUS_IS_OK(nt_status
)) {
1572 err
= WERR_NOT_ENOUGH_MEMORY
;
1576 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1578 nt_status
= create_directory(conn
, NULL
, smb_dname
);
1579 if (!NT_STATUS_IS_OK(nt_status
)
1580 && !NT_STATUS_EQUAL(nt_status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
1581 DEBUG(0, ("failed to create driver destination directory: %s\n",
1582 nt_errstr(nt_status
)));
1583 err
= ntstatus_to_werror(nt_status
);
1587 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1588 * listed for this driver which has already been moved, skip it (note:
1589 * drivers may list the same file name several times. Then check if the
1590 * file already exists in archi\version\, if so, check that the version
1591 * info (or time stamps if version info is unavailable) is newer (or the
1592 * date is later). If it is, move it to archi\version\filexxx.yyy.
1593 * Otherwise, delete the file.
1595 * If a file is not moved to archi\version\ because of an error, all the
1596 * rest of the 'unmoved' driver files are removed from archi\. If one or
1597 * more of the driver's files was already moved to archi\version\, it
1598 * potentially leaves the driver in a partially updated state. Version
1599 * trauma will most likely occur if an client attempts to use any printer
1600 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1601 * done is appropriate... later JRR
1604 DEBUG(5,("Moving files now !\n"));
1606 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1608 err
= move_driver_file_to_download_area(frame
,
1610 driver
->driver_path
,
1615 if (!W_ERROR_IS_OK(err
)) {
1620 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1621 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1623 err
= move_driver_file_to_download_area(frame
,
1630 if (!W_ERROR_IS_OK(err
)) {
1636 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1637 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1638 !strequal(driver
->config_file
, driver
->data_file
)) {
1640 err
= move_driver_file_to_download_area(frame
,
1642 driver
->config_file
,
1647 if (!W_ERROR_IS_OK(err
)) {
1653 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1654 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1655 !strequal(driver
->help_file
, driver
->data_file
) &&
1656 !strequal(driver
->help_file
, driver
->config_file
)) {
1658 err
= move_driver_file_to_download_area(frame
,
1665 if (!W_ERROR_IS_OK(err
)) {
1671 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1672 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1673 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1674 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1675 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1676 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1678 for (j
=0; j
< i
; j
++) {
1679 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
1684 err
= move_driver_file_to_download_area(frame
,
1686 driver
->dependent_files
->string
[i
],
1691 if (!W_ERROR_IS_OK(err
)) {
1701 unbecome_user_without_service();
1707 /****************************************************************************
1708 Determine whether or not a particular driver is currently assigned
1710 ****************************************************************************/
1712 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
1713 struct dcerpc_binding_handle
*b
,
1714 const struct spoolss_DriverInfo8
*r
)
1716 const struct loadparm_substitution
*lp_sub
=
1717 loadparm_s3_global_substitution();
1719 int n_services
= lp_numservices();
1720 bool in_use
= false;
1721 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1728 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1730 /* loop through the printers.tdb and check for the drivername */
1732 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
1733 if (!lp_snum_ok(snum
) || !lp_printable(snum
)) {
1737 result
= winreg_get_printer(mem_ctx
, b
,
1738 lp_servicename(talloc_tos(), lp_sub
, snum
),
1740 if (!W_ERROR_IS_OK(result
)) {
1741 continue; /* skip */
1744 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
1748 TALLOC_FREE(pinfo2
);
1751 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1754 struct spoolss_DriverInfo8
*driver
= NULL
;
1757 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
1759 /* we can still remove the driver if there is one of
1760 "Windows NT x86" version 2 or 3 left */
1762 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86
, r
->architecture
)) {
1763 if (r
->version
== 2) {
1764 werr
= winreg_get_driver(mem_ctx
, b
,
1768 } else if (r
->version
== 3) {
1769 werr
= winreg_get_driver(mem_ctx
, b
,
1774 DBG_ERR("Unknown driver version (%d)\n",
1776 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
1778 } else if (strequal(SPOOLSS_ARCHITECTURE_x64
, r
->architecture
)) {
1779 werr
= winreg_get_driver(mem_ctx
, b
,
1780 SPOOLSS_ARCHITECTURE_NT_X86
,
1785 DBG_ERR("Unknown driver architecture: %s\n",
1787 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
1790 /* now check the error code */
1792 if ( W_ERROR_IS_OK(werr
) ) {
1793 /* it's ok to remove the driver, we have other architctures left */
1795 talloc_free(driver
);
1799 /* report that the driver is not in use by default */
1805 /**********************************************************************
1806 Check to see if a ogiven file is in use by *info
1807 *********************************************************************/
1809 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
1816 /* mz: skip files that are in the list but already deleted */
1817 if (!file
|| !file
[0]) {
1821 if (strequal(file
, info
->driver_path
))
1824 if (strequal(file
, info
->data_file
))
1827 if (strequal(file
, info
->config_file
))
1830 if (strequal(file
, info
->help_file
))
1833 /* see of there are any dependent files to examine */
1835 if (!info
->dependent_files
)
1838 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
1839 if (strequal(file
, info
->dependent_files
[i
]))
1848 /**********************************************************************
1849 Utility function to remove the dependent file pointed to by the
1850 input parameter from the list
1851 *********************************************************************/
1853 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
1856 /* bump everything down a slot */
1858 while (files
&& files
[idx
+1]) {
1859 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
1868 /**********************************************************************
1869 Check if any of the files used by src are also used by drv
1870 *********************************************************************/
1872 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
1873 struct spoolss_DriverInfo8
*src
,
1874 const struct spoolss_DriverInfo8
*drv
)
1876 bool in_use
= False
;
1882 /* check each file. Remove it from the src structure if it overlaps */
1884 if (drv_file_in_use(src
->driver_path
, drv
)) {
1886 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
1887 src
->driver_path
= talloc_strdup(mem_ctx
, "");
1888 if (!src
->driver_path
) { return false; }
1891 if (drv_file_in_use(src
->data_file
, drv
)) {
1893 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
1894 src
->data_file
= talloc_strdup(mem_ctx
, "");
1895 if (!src
->data_file
) { return false; }
1898 if (drv_file_in_use(src
->config_file
, drv
)) {
1900 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
1901 src
->config_file
= talloc_strdup(mem_ctx
, "");
1902 if (!src
->config_file
) { return false; }
1905 if (drv_file_in_use(src
->help_file
, drv
)) {
1907 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
1908 src
->help_file
= talloc_strdup(mem_ctx
, "");
1909 if (!src
->help_file
) { return false; }
1912 /* are there any dependentfiles to examine? */
1914 if (!src
->dependent_files
)
1917 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
1918 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
1920 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
1921 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
1929 /****************************************************************************
1930 Determine whether or not a particular driver files are currently being
1931 used by any other driver.
1933 Return value is True if any files were in use by other drivers
1934 and False otherwise.
1936 Upon return, *info has been modified to only contain the driver files
1937 which are not in use
1941 This needs to check all drivers to ensure that all files in use
1942 have been removed from *info, not just the ones in the first
1944 ****************************************************************************/
1946 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
1947 struct dcerpc_binding_handle
*b
,
1948 struct spoolss_DriverInfo8
*info
)
1952 struct spoolss_DriverInfo8
*driver
;
1953 bool in_use
= false;
1954 uint32_t num_drivers
;
1955 const char **drivers
;
1961 version
= info
->version
;
1963 /* loop over all driver versions */
1965 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1967 /* get the list of drivers */
1969 result
= winreg_get_driver_list(mem_ctx
, b
,
1970 info
->architecture
, version
,
1971 &num_drivers
, &drivers
);
1972 if (!W_ERROR_IS_OK(result
)) {
1976 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1977 num_drivers
, info
->architecture
, version
));
1979 /* check each driver for overlap in files */
1981 for (i
= 0; i
< num_drivers
; i
++) {
1982 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
1986 result
= winreg_get_driver(mem_ctx
, b
,
1987 info
->architecture
, drivers
[i
],
1989 if (!W_ERROR_IS_OK(result
)) {
1990 talloc_free(drivers
);
1994 /* check if d2 uses any files from d1 */
1995 /* only if this is a different driver than the one being deleted */
1997 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
1998 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
1999 /* mz: Do not instantly return -
2000 * we need to ensure this file isn't
2001 * also in use by other drivers. */
2006 talloc_free(driver
);
2009 talloc_free(drivers
);
2011 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2016 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
2017 const char *short_arch
,
2021 TALLOC_CTX
*tmp_ctx
= talloc_new(conn
);
2022 struct smb_filename
*smb_fname
= NULL
;
2023 char *print_dlr_path
;
2024 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2026 print_dlr_path
= talloc_asprintf(tmp_ctx
, "%s/%d/%s",
2027 short_arch
, vers
, fname
);
2028 if (print_dlr_path
== NULL
) {
2032 smb_fname
= synthetic_smb_fname(tmp_ctx
, print_dlr_path
, NULL
, NULL
, 0);
2033 if (smb_fname
== NULL
) {
2037 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
2039 talloc_free(tmp_ctx
);
2043 /****************************************************************************
2044 Actually delete the driver files. Make sure that
2045 printer_driver_files_in_use() return False before calling
2047 ****************************************************************************/
2049 bool delete_driver_files(const struct auth_session_info
*session_info
,
2050 const struct spoolss_DriverInfo8
*r
)
2052 TALLOC_CTX
*frame
= talloc_stackframe();
2053 const struct loadparm_substitution
*lp_sub
=
2054 loadparm_s3_global_substitution();
2055 const char *short_arch
;
2056 struct conn_struct_tos
*c
= NULL
;
2057 connection_struct
*conn
= NULL
;
2059 char *printdollar
= NULL
;
2060 int printdollar_snum
;
2068 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2069 r
->driver_name
, r
->version
));
2071 printdollar_snum
= find_service(frame
, "print$", &printdollar
);
2076 if (printdollar_snum
== -1) {
2081 nt_status
= create_conn_struct_tos_cwd(global_messaging_context(),
2083 lp_path(frame
, lp_sub
, printdollar_snum
),
2086 if (!NT_STATUS_IS_OK(nt_status
)) {
2087 DEBUG(0,("delete_driver_files: create_conn_struct "
2088 "returned %s\n", nt_errstr(nt_status
)));
2094 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
2095 if (!NT_STATUS_IS_OK(nt_status
)) {
2096 DEBUG(0, ("failed set force user / group\n"));
2101 if (!become_user_without_service_by_session(conn
, session_info
)) {
2102 DEBUG(0, ("failed to become user\n"));
2107 if ( !CAN_WRITE(conn
) ) {
2108 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2113 short_arch
= get_short_archi(r
->architecture
);
2114 if (short_arch
== NULL
) {
2115 DEBUG(0, ("bad architecture %s\n", r
->architecture
));
2120 /* now delete the files */
2122 if (r
->driver_path
&& r
->driver_path
[0]) {
2123 DEBUG(10,("deleting driverfile [%s]\n", r
->driver_path
));
2124 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->driver_path
);
2127 if (r
->config_file
&& r
->config_file
[0]) {
2128 DEBUG(10,("deleting configfile [%s]\n", r
->config_file
));
2129 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->config_file
);
2132 if (r
->data_file
&& r
->data_file
[0]) {
2133 DEBUG(10,("deleting datafile [%s]\n", r
->data_file
));
2134 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->data_file
);
2137 if (r
->help_file
&& r
->help_file
[0]) {
2138 DEBUG(10,("deleting helpfile [%s]\n", r
->help_file
));
2139 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->help_file
);
2142 if (r
->dependent_files
) {
2144 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
2145 DEBUG(10,("deleting dependent file [%s]\n", r
->dependent_files
[i
]));
2146 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->dependent_files
[i
]);
2153 unbecome_user_without_service();
2161 1: level not implemented
2162 2: file doesn't exist
2163 3: can't allocate memory
2164 4: can't free memory
2165 5: non existent struct
2169 A printer and a printer driver are 2 different things.
2170 NT manages them separatelly, Samba does the same.
2171 Why ? Simply because it's easier and it makes sense !
2173 Now explanation: You have 3 printers behind your samba server,
2174 2 of them are the same make and model (laser A and B). But laser B
2175 has an 3000 sheet feeder and laser A doesn't such an option.
2176 Your third printer is an old dot-matrix model for the accounting :-).
2178 If the /usr/local/samba/lib directory (default dir), you will have
2179 5 files to describe all of this.
2181 3 files for the printers (1 by printer):
2184 NTprinter_accounting
2185 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2186 NTdriver_printer model X
2187 NTdriver_printer model Y
2189 jfm: I should use this comment for the text file to explain
2190 same thing for the forms BTW.
2191 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2195 /* Convert generic access rights to printer object specific access rights.
2196 It turns out that NT4 security descriptors use generic access rights and
2197 NT5 the object specific ones. */
2199 void map_printer_permissions(struct security_descriptor
*sd
)
2203 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2204 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2205 &printer_generic_mapping
);
2209 void map_job_permissions(struct security_descriptor
*sd
)
2213 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2214 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2215 &job_generic_mapping
);
2220 /****************************************************************************
2221 Check a user has permissions to perform the given operation. We use the
2222 permission constants defined in include/rpc_spoolss.h to check the various
2223 actions we perform when checking printer access.
2225 PRINTER_ACCESS_ADMINISTER:
2226 print_queue_pause, print_queue_resume, update_printer_sec,
2227 update_printer, spoolss_addprinterex_level_2,
2228 _spoolss_setprinterdata
2233 JOB_ACCESS_ADMINISTER:
2234 print_job_delete, print_job_pause, print_job_resume,
2237 Try access control in the following order (for performance reasons):
2238 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2239 2) check security descriptor (bit comparisons in memory)
2240 3) "printer admins" (may result in numerous calls to winbind)
2242 ****************************************************************************/
2243 WERROR
print_access_check(const struct auth_session_info
*session_info
,
2244 struct messaging_context
*msg_ctx
, int snum
,
2247 struct spoolss_security_descriptor
*secdesc
= NULL
;
2248 const struct loadparm_substitution
*lp_sub
=
2249 loadparm_s3_global_substitution();
2250 uint32_t access_granted
;
2255 TALLOC_CTX
*mem_ctx
= NULL
;
2257 /* If user is NULL then use the current_user structure */
2259 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2261 if ((session_info
->unix_token
->uid
== sec_initial_uid())
2262 || security_token_has_privilege(session_info
->security_token
,
2263 SEC_PRIV_PRINT_OPERATOR
)) {
2267 /* Get printer name */
2269 pname
= lp_printername(talloc_tos(), lp_sub
, snum
);
2271 if (!pname
|| !*pname
) {
2272 return WERR_ACCESS_DENIED
;
2275 /* Get printer security descriptor */
2277 if(!(mem_ctx
= talloc_init("print_access_check"))) {
2278 return WERR_NOT_ENOUGH_MEMORY
;
2281 result
= winreg_get_printer_secdesc_internal(mem_ctx
,
2282 get_session_info_system(),
2286 if (!W_ERROR_IS_OK(result
)) {
2287 talloc_destroy(mem_ctx
);
2288 return WERR_NOT_ENOUGH_MEMORY
;
2291 if (access_type
== JOB_ACCESS_ADMINISTER
) {
2292 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
2294 /* Create a child security descriptor to check permissions
2295 against. This is because print jobs are child objects
2296 objects of a printer. */
2297 status
= se_create_child_secdesc(mem_ctx
,
2301 parent_secdesc
->owner_sid
,
2302 parent_secdesc
->group_sid
,
2304 if (!NT_STATUS_IS_OK(status
)) {
2305 talloc_destroy(mem_ctx
);
2306 return ntstatus_to_werror(status
);
2309 map_job_permissions(secdesc
);
2311 map_printer_permissions(secdesc
);
2315 status
= se_access_check(secdesc
, session_info
->security_token
, access_type
,
2318 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
2320 talloc_destroy(mem_ctx
);
2322 return ntstatus_to_werror(status
);
2325 /****************************************************************************
2326 Check the time parameters allow a print operation.
2327 *****************************************************************************/
2329 bool print_time_access_check(const struct auth_session_info
*session_info
,
2330 struct messaging_context
*msg_ctx
,
2331 const char *servicename
)
2333 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2336 time_t now
= time(NULL
);
2340 result
= winreg_get_printer_internal(NULL
, session_info
, msg_ctx
,
2341 servicename
, &pinfo2
);
2342 if (!W_ERROR_IS_OK(result
)) {
2346 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
2351 mins
= (uint32_t)t
->tm_hour
*60 + (uint32_t)t
->tm_min
;
2353 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
2357 TALLOC_FREE(pinfo2
);
2366 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
2367 const struct auth_session_info
*session_info
,
2368 struct messaging_context
*msg_ctx
,
2369 const char *printer
)
2373 result
= winreg_delete_printer_key_internal(mem_ctx
, session_info
, msg_ctx
,
2375 if (!W_ERROR_IS_OK(result
)) {
2376 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2377 "%s\n", printer
, win_errstr(result
)));
2381 void nt_printer_add(TALLOC_CTX
*mem_ctx
,
2382 const struct auth_session_info
*session_info
,
2383 struct messaging_context
*msg_ctx
,
2384 const char *printer
)
2388 result
= winreg_create_printer_internal(mem_ctx
, session_info
, msg_ctx
,
2390 if (!W_ERROR_IS_OK(result
)) {
2391 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2392 printer
, win_errstr(result
)));