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();
84 service = lp_servicenumber("print$");
86 /* We don't have a print$ share */
87 DEBUG(5, ("No print$ share has been configured.\n"));
92 driver_path = lp_path(mem_ctx, service);
93 if (driver_path == NULL) {
98 ok = directory_create_or_exist(driver_path, 0755);
100 DEBUG(1, ("Failed to create printer driver directory %s\n",
102 talloc_free(mem_ctx);
106 for (i = 0; archi_table[i].long_archi != NULL; i++) {
107 const char *arch_path;
109 arch_path = talloc_asprintf(mem_ctx,
112 archi_table[i].short_archi);
113 if (arch_path == NULL) {
114 talloc_free(mem_ctx);
118 ok = directory_create_or_exist(arch_path, 0755);
120 DEBUG(1, ("Failed to create printer driver "
121 "architecture directory %s\n",
123 talloc_free(mem_ctx);
128 talloc_free(mem_ctx);
132 /****************************************************************************
133 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
134 background lpq updater.
135 ****************************************************************************/
137 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
140 struct server_id server_id,
143 extern pid_t background_lpq_updater_pid;
145 if (background_lpq_updater_pid == -1) {
146 DEBUG(3,("no background lpq queue updater\n"));
150 messaging_send_buf(msg,
151 pid_to_procid(background_lpq_updater_pid),
152 MSG_PRINTER_DRVUPGRADE,
157 /****************************************************************************
158 Open the NT printing tdbs. Done once before fork().
159 ****************************************************************************/
161 bool nt_printing_init(struct messaging_context *msg_ctx)
165 if (!print_driver_directories_init()) {
169 if (!nt_printing_tdb_upgrade()) {
174 * register callback to handle updating printers as new
175 * drivers are installed. Forwards to background lpq updater.
177 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
178 forward_drv_upgrade_printer_msg);
180 /* of course, none of the message callbacks matter if you don't
181 tell messages.c that you interested in receiving PRINT_GENERAL
182 msgs. This is done in serverid_register() */
184 if ( lp_security() == SEC_ADS ) {
185 win_rc = check_published_printers(msg_ctx);
186 if (!W_ERROR_IS_OK(win_rc))
187 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
193 /*******************************************************************
194 Function to allow filename parsing "the old way".
195 ********************************************************************/
197 static NTSTATUS driver_unix_convert(connection_struct *conn,
198 const char *old_name,
199 struct smb_filename **smb_fname)
202 TALLOC_CTX *ctx = talloc_tos();
203 char *name = talloc_strdup(ctx, old_name);
206 return NT_STATUS_NO_MEMORY;
209 name = unix_clean_name(ctx, name);
211 return NT_STATUS_NO_MEMORY;
213 trim_string(name,"/","/");
215 status = unix_convert(ctx, conn, name, smb_fname, 0);
216 if (!NT_STATUS_IS_OK(status)) {
217 return NT_STATUS_NO_MEMORY;
223 /****************************************************************************
224 Function to do the mapping between the long architecture name and
226 ****************************************************************************/
228 const char *get_short_archi(const char *long_archi)
232 DEBUG(107,("Getting architecture dependent directory\n"));
235 } while ( (archi_table[i].long_archi!=NULL ) &&
236 strcasecmp_m(long_archi, archi_table[i].long_archi) );
238 if (archi_table[i].long_archi==NULL) {
239 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
243 /* this might be client code - but shouldn't this be an fstrcpy etc? */
245 DEBUGADD(108,("index: [%d]\n", i));
246 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
247 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
249 return archi_table[i].short_archi;
252 /****************************************************************************
253 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
254 There are two case to be covered here: PE (Portable Executable) and NE (New
255 Executable) files. Both files support the same INFO structure, but PE files
256 store the signature in unicode, and NE files store it as !unicode.
257 returns -1 on error, 1 on version info found, and 0 on no version info found.
258 ****************************************************************************/
260 static int get_file_version(files_struct *fsp, char *fname,uint32_t *major, uint32_t *minor)
266 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
267 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
268 fname, DOS_HEADER_SIZE));
272 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
273 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
274 fname, (unsigned long)byte_count));
275 goto no_version_info;
278 /* Is this really a DOS header? */
279 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
280 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
281 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
282 goto no_version_info;
285 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
286 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (off_t)-1) {
287 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
289 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
290 goto no_version_info;
293 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
294 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
295 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
296 fname, (unsigned long)byte_count));
297 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
298 goto no_version_info;
301 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
302 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
303 unsigned int num_sections;
304 unsigned int section_table_bytes;
306 /* Just skip over optional header to get to section table */
307 if (SMB_VFS_LSEEK(fsp,
308 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
309 SEEK_CUR) == (off_t)-1) {
310 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
315 /* get the section table */
316 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
317 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
318 if (section_table_bytes == 0)
322 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
323 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
324 fname, section_table_bytes));
328 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
329 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
330 fname, (unsigned long)byte_count));
334 /* Iterate the section table looking for the resource section ".rsrc" */
335 for (i = 0; i < num_sections; i++) {
336 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
338 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
339 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
340 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
342 if (section_bytes == 0)
346 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
347 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
348 fname, section_bytes));
352 /* Seek to the start of the .rsrc section info */
353 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (off_t)-1) {
354 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
359 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
360 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
361 fname, (unsigned long)byte_count));
365 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
368 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
369 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
370 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
371 /* Align to next long address */
372 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
374 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
375 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
376 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
378 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
379 fname, *major, *minor,
380 (*major>>16)&0xffff, *major&0xffff,
381 (*minor>>16)&0xffff, *minor&0xffff));
390 /* Version info not found, fall back to origin date/time */
391 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
395 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
396 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
397 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
398 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
399 /* At this point, we assume the file is in error. It still could be something
400 * else besides a NE file, but it unlikely at this point. */
404 /* Allocate a bit more space to speed up things */
406 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
407 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
408 fname, PE_HEADER_SIZE));
412 /* This is a HACK! I got tired of trying to sort through the messy
413 * 'NE' file format. If anyone wants to clean this up please have at
414 * it, but this works. 'NE' files will eventually fade away. JRR */
415 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
416 /* Cover case that should not occur in a well formed 'NE' .dll file */
417 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
419 for(i=0; i<byte_count; i++) {
420 /* Fast skip past data that can't possibly match */
421 if (buf[i] != 'V') continue;
423 /* Potential match data crosses buf boundry, move it to beginning
424 * of buf, and fill the buf with as much as it will hold. */
425 if (i>byte_count-VS_VERSION_INFO_SIZE) {
428 memcpy(buf, &buf[i], byte_count-i);
429 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
430 (byte_count-i))) < 0) {
432 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
437 byte_count = bc + (byte_count - i);
438 if (byte_count<VS_VERSION_INFO_SIZE) break;
443 /* Check that the full signature string and the magic number that
444 * follows exist (not a perfect solution, but the chances that this
445 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
446 * twice, as it is simpler to read the code. */
447 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
448 /* Compute skip alignment to next long address */
449 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
450 sizeof(VS_SIGNATURE)) & 3;
451 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
453 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
454 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
455 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
456 fname, *major, *minor,
457 (*major>>16)&0xffff, *major&0xffff,
458 (*minor>>16)&0xffff, *minor&0xffff));
465 /* Version info not found, fall back to origin date/time */
466 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
471 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
472 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
473 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
484 /****************************************************************************
485 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
486 share one or more files. During the MS installation process files are checked
487 to insure that only a newer version of a shared file is installed over an
488 older version. There are several possibilities for this comparison. If there
489 is no previous version, the new one is newer (obviously). If either file is
490 missing the version info structure, compare the creation date (on Unix use
491 the modification date). Otherwise chose the numerically larger version number.
492 ****************************************************************************/
494 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
496 bool use_version = true;
500 time_t new_create_time;
504 time_t old_create_time;
506 struct smb_filename *smb_fname = NULL;
507 files_struct *fsp = NULL;
513 SET_STAT_INVALID(st);
514 new_create_time = (time_t)0;
515 old_create_time = (time_t)0;
517 /* Get file version info (if available) for previous file (if it exists) */
518 status = driver_unix_convert(conn, old_file, &smb_fname);
519 if (!NT_STATUS_IS_OK(status)) {
523 status = SMB_VFS_CREATE_FILE(
526 0, /* root_dir_fid */
527 smb_fname, /* fname */
528 FILE_GENERIC_READ, /* access_mask */
529 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
530 FILE_OPEN, /* create_disposition*/
531 0, /* create_options */
532 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
533 INTERNAL_OPEN_ONLY, /* oplock_request */
535 0, /* allocation_size */
536 0, /* private_flags */
541 NULL, NULL); /* create context */
543 if (!NT_STATUS_IS_OK(status)) {
544 /* Old file not found, so by definition new file is in fact newer */
545 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
546 "errno = %d\n", smb_fname_str_dbg(smb_fname),
552 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
558 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
561 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
564 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
565 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
566 (long)old_create_time));
569 close_file(NULL, fsp, NORMAL_CLOSE);
572 /* Get file version info (if available) for new file */
573 status = driver_unix_convert(conn, new_file, &smb_fname);
574 if (!NT_STATUS_IS_OK(status)) {
578 status = SMB_VFS_CREATE_FILE(
581 0, /* root_dir_fid */
582 smb_fname, /* fname */
583 FILE_GENERIC_READ, /* access_mask */
584 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
585 FILE_OPEN, /* create_disposition*/
586 0, /* create_options */
587 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
588 INTERNAL_OPEN_ONLY, /* oplock_request */
590 0, /* allocation_size */
591 0, /* private_flags */
596 NULL, NULL); /* create context */
598 if (!NT_STATUS_IS_OK(status)) {
599 /* New file not found, this shouldn't occur if the caller did its job */
600 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
601 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
605 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
611 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
614 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
617 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
618 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
619 (long)new_create_time));
622 close_file(NULL, fsp, NORMAL_CLOSE);
625 if (use_version && (new_major != old_major || new_minor != old_minor)) {
626 /* Compare versions and choose the larger version number */
627 if (new_major > old_major ||
628 (new_major == old_major && new_minor > old_minor)) {
630 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
635 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
641 /* Compare modification time/dates and choose the newest time/date */
642 if (new_create_time > old_create_time) {
643 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
648 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
656 close_file(NULL, fsp, NORMAL_CLOSE);
659 TALLOC_FREE(smb_fname);
663 /****************************************************************************
664 Determine the correct cVersion associated with an architecture and driver
665 ****************************************************************************/
666 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
667 const char *architecture,
668 const char *driverpath_in,
669 const char *driver_directory,
674 struct smb_filename *smb_fname = NULL;
675 files_struct *fsp = NULL;
676 connection_struct *conn = NULL;
677 struct smb_filename *oldcwd_fname = NULL;
678 char *printdollar = NULL;
679 char *printdollar_path = NULL;
680 char *working_dir = NULL;
681 int printdollar_snum;
683 *perr = WERR_INVALID_PARAMETER;
685 /* If architecture is Windows 95/98/ME, the version is always 0. */
686 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
687 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
692 /* If architecture is Windows x64, the version is always 3. */
693 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
694 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
699 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
701 *perr = WERR_NOT_ENOUGH_MEMORY;
704 if (printdollar_snum == -1) {
705 *perr = WERR_BAD_NET_NAME;
709 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
710 if (printdollar_path == NULL) {
711 *perr = WERR_NOT_ENOUGH_MEMORY;
715 working_dir = talloc_asprintf(talloc_tos(),
720 * If the driver has been uploaded into a temorpary driver
721 * directory, switch to the driver directory.
723 if (driver_directory != NULL) {
724 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
730 nt_status = create_conn_struct_cwd(talloc_tos(),
731 server_event_context(),
732 server_messaging_context(),
736 session_info, &oldcwd_fname);
737 if (!NT_STATUS_IS_OK(nt_status)) {
738 DEBUG(0,("get_correct_cversion: create_conn_struct "
739 "returned %s\n", nt_errstr(nt_status)));
740 *perr = ntstatus_to_werror(nt_status);
744 nt_status = set_conn_force_user_group(conn, printdollar_snum);
745 if (!NT_STATUS_IS_OK(nt_status)) {
746 DEBUG(0, ("failed set force user / group\n"));
747 *perr = ntstatus_to_werror(nt_status);
748 goto error_free_conn;
751 if (!become_user_by_session(conn, session_info)) {
752 DEBUG(0, ("failed to become user\n"));
753 *perr = WERR_ACCESS_DENIED;
754 goto error_free_conn;
758 * We switch to the directory where the driver files are located,
759 * so only work on the file names
761 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
762 if (!NT_STATUS_IS_OK(nt_status)) {
763 *perr = ntstatus_to_werror(nt_status);
767 nt_status = vfs_file_exist(conn, smb_fname);
768 if (!NT_STATUS_IS_OK(nt_status)) {
769 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
770 *perr = WERR_FILE_NOT_FOUND;
774 nt_status = SMB_VFS_CREATE_FILE(
777 0, /* root_dir_fid */
778 smb_fname, /* fname */
779 FILE_GENERIC_READ, /* access_mask */
780 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
781 FILE_OPEN, /* create_disposition*/
782 0, /* create_options */
783 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
784 INTERNAL_OPEN_ONLY, /* oplock_request */
786 0, /* private_flags */
787 0, /* allocation_size */
792 NULL, NULL); /* create context */
794 if (!NT_STATUS_IS_OK(nt_status)) {
795 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
796 "%d\n", smb_fname_str_dbg(smb_fname), errno));
797 *perr = WERR_ACCESS_DENIED;
804 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
806 *perr = WERR_INVALID_PARAMETER;
809 DEBUG(6,("get_correct_cversion: Version info not "
811 smb_fname_str_dbg(smb_fname)));
812 *perr = WERR_INVALID_PARAMETER;
817 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
818 * for more details. Version in this case is not just the version of the
819 * file, but the version in the sense of kernal mode (2) vs. user mode
820 * (3) drivers. Other bits of the version fields are the version info.
823 cversion = major & 0x0000ffff;
825 case 2: /* WinNT drivers */
826 case 3: /* Win2K drivers */
830 DEBUG(6,("get_correct_cversion: cversion "
831 "invalid [%s] cversion = %d\n",
832 smb_fname_str_dbg(smb_fname),
837 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
838 " = 0x%x minor = 0x%x\n",
839 smb_fname_str_dbg(smb_fname), major, minor));
842 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
843 smb_fname_str_dbg(smb_fname), cversion));
849 TALLOC_FREE(smb_fname);
851 close_file(NULL, fsp, NORMAL_CLOSE);
854 vfs_ChDir(conn, oldcwd_fname);
855 TALLOC_FREE(oldcwd_fname);
856 SMB_VFS_DISCONNECT(conn);
859 if (!W_ERROR_IS_OK(*perr)) {
866 /****************************************************************************
867 ****************************************************************************/
869 #define strip_driver_path(_mem_ctx, _element) do { \
870 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
871 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
872 W_ERROR_HAVE_NO_MEMORY((_element)); \
876 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
877 struct auth_session_info *session_info,
878 const char *architecture,
879 const char **driver_path,
880 const char **data_file,
881 const char **config_file,
882 const char **help_file,
883 struct spoolss_StringArray *dependent_files,
884 enum spoolss_DriverOSVersion *version,
886 const char **driver_directory)
888 const char *short_architecture;
893 if (!*driver_path || !*data_file) {
894 return WERR_INVALID_PARAMETER;
897 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
898 return WERR_INVALID_PARAMETER;
901 if (flags & APD_COPY_FROM_DIRECTORY) {
906 * driver_path is set to:
908 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
910 path = talloc_strdup(mem_ctx, *driver_path);
912 return WERR_NOT_ENOUGH_MEMORY;
915 /* Remove pscript5.dll */
916 q = strrchr_m(path, '\\');
918 return WERR_INVALID_PARAMETER;
922 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
923 q = strrchr_m(path, '\\');
925 return WERR_INVALID_PARAMETER;
929 * Set driver_directory to:
931 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
933 * This is the directory where all the files have been uploaded
935 *driver_directory = q + 1;
938 /* clean up the driver name.
939 * we can get .\driver.dll
940 * or worse c:\windows\system\driver.dll !
942 /* using an intermediate string to not have overlaping memcpy()'s */
944 strip_driver_path(mem_ctx, *driver_path);
945 strip_driver_path(mem_ctx, *data_file);
947 strip_driver_path(mem_ctx, *config_file);
950 strip_driver_path(mem_ctx, *help_file);
953 if (dependent_files && dependent_files->string) {
954 for (i=0; dependent_files->string[i]; i++) {
955 strip_driver_path(mem_ctx, dependent_files->string[i]);
959 short_architecture = get_short_archi(architecture);
960 if (!short_architecture) {
961 return WERR_UNKNOWN_PRINTER_DRIVER;
964 /* jfm:7/16/2000 the client always sends the cversion=0.
965 * The server should check which version the driver is by reading
966 * the PE header of driver->driverpath.
968 * For Windows 95/98 the version is 0 (so the value sent is correct)
969 * For Windows NT (the architecture doesn't matter)
971 * NT 3.5/3.51: cversion=1
976 *version = get_correct_cversion(session_info,
981 if (*version == -1) {
988 /****************************************************************************
989 ****************************************************************************/
991 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
992 struct auth_session_info *session_info,
993 struct spoolss_AddDriverInfoCtr *r,
995 const char **driver_directory)
999 return clean_up_driver_struct_level(mem_ctx, session_info,
1000 r->info.info3->architecture,
1001 &r->info.info3->driver_path,
1002 &r->info.info3->data_file,
1003 &r->info.info3->config_file,
1004 &r->info.info3->help_file,
1005 r->info.info3->dependent_files,
1006 &r->info.info3->version,
1010 return clean_up_driver_struct_level(mem_ctx, session_info,
1011 r->info.info6->architecture,
1012 &r->info.info6->driver_path,
1013 &r->info.info6->data_file,
1014 &r->info.info6->config_file,
1015 &r->info.info6->help_file,
1016 r->info.info6->dependent_files,
1017 &r->info.info6->version,
1021 return clean_up_driver_struct_level(mem_ctx, session_info,
1022 r->info.info8->architecture,
1023 &r->info.info8->driver_path,
1024 &r->info.info8->data_file,
1025 &r->info.info8->config_file,
1026 &r->info.info8->help_file,
1027 r->info.info8->dependent_files,
1028 &r->info.info8->version,
1032 return WERR_NOT_SUPPORTED;
1036 /****************************************************************************
1037 This function sucks and should be replaced. JRA.
1038 ****************************************************************************/
1040 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1041 const struct spoolss_AddDriverInfo6 *src)
1043 dst->version = src->version;
1045 dst->driver_name = src->driver_name;
1046 dst->architecture = src->architecture;
1047 dst->driver_path = src->driver_path;
1048 dst->data_file = src->data_file;
1049 dst->config_file = src->config_file;
1050 dst->help_file = src->help_file;
1051 dst->monitor_name = src->monitor_name;
1052 dst->default_datatype = src->default_datatype;
1053 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1054 dst->dependent_files = src->dependent_files;
1057 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1058 const struct spoolss_AddDriverInfo8 *src)
1060 dst->version = src->version;
1062 dst->driver_name = src->driver_name;
1063 dst->architecture = src->architecture;
1064 dst->driver_path = src->driver_path;
1065 dst->data_file = src->data_file;
1066 dst->config_file = src->config_file;
1067 dst->help_file = src->help_file;
1068 dst->monitor_name = src->monitor_name;
1069 dst->default_datatype = src->default_datatype;
1070 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1071 dst->dependent_files = src->dependent_files;
1074 /****************************************************************************
1075 ****************************************************************************/
1077 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1078 connection_struct *conn,
1079 const char *driver_file,
1080 const char *short_architecture,
1081 uint32_t driver_version,
1083 const char *driver_directory)
1085 struct smb_filename *smb_fname_old = NULL;
1086 struct smb_filename *smb_fname_new = NULL;
1087 char *old_name = NULL;
1088 char *new_name = NULL;
1092 if (driver_directory != NULL) {
1093 old_name = talloc_asprintf(mem_ctx,
1099 old_name = talloc_asprintf(mem_ctx,
1104 if (old_name == NULL) {
1105 return WERR_NOT_ENOUGH_MEMORY;
1108 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1109 short_architecture, driver_version, driver_file);
1110 if (new_name == NULL) {
1111 TALLOC_FREE(old_name);
1112 return WERR_NOT_ENOUGH_MEMORY;
1115 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1117 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 ret = WERR_NOT_ENOUGH_MEMORY;
1123 /* Setup a synthetic smb_filename struct */
1124 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1125 if (!smb_fname_new) {
1126 ret = WERR_NOT_ENOUGH_MEMORY;
1130 smb_fname_new->base_name = new_name;
1132 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1133 "'%s'\n", smb_fname_old->base_name,
1134 smb_fname_new->base_name));
1136 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1137 OPENX_FILE_EXISTS_TRUNCATE |
1138 OPENX_FILE_CREATE_IF_NOT_EXIST,
1141 if (!NT_STATUS_IS_OK(status)) {
1142 DEBUG(0,("move_driver_file_to_download_area: Unable "
1143 "to rename [%s] to [%s]: %s\n",
1144 smb_fname_old->base_name, new_name,
1145 nt_errstr(status)));
1146 ret = WERR_ACCESS_DENIED;
1153 TALLOC_FREE(smb_fname_old);
1154 TALLOC_FREE(smb_fname_new);
1158 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1159 struct spoolss_AddDriverInfoCtr *r,
1160 const char *driver_directory)
1162 struct spoolss_AddDriverInfo3 *driver;
1163 struct spoolss_AddDriverInfo3 converted_driver;
1164 const char *short_architecture;
1165 struct smb_filename *smb_dname = NULL;
1166 char *new_dir = NULL;
1167 connection_struct *conn = NULL;
1170 TALLOC_CTX *ctx = talloc_tos();
1172 struct smb_filename *oldcwd_fname = NULL;
1173 char *printdollar = NULL;
1174 int printdollar_snum;
1175 WERROR err = WERR_OK;
1179 driver = r->info.info3;
1182 convert_level_6_to_level3(&converted_driver, r->info.info6);
1183 driver = &converted_driver;
1186 convert_level_8_to_level3(&converted_driver, r->info.info8);
1187 driver = &converted_driver;
1190 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1191 return WERR_INVALID_LEVEL;
1194 short_architecture = get_short_archi(driver->architecture);
1195 if (!short_architecture) {
1196 return WERR_UNKNOWN_PRINTER_DRIVER;
1199 printdollar_snum = find_service(ctx, "print$", &printdollar);
1201 return WERR_NOT_ENOUGH_MEMORY;
1203 if (printdollar_snum == -1) {
1204 return WERR_BAD_NET_NAME;
1207 nt_status = create_conn_struct_cwd(talloc_tos(),
1208 server_event_context(),
1209 server_messaging_context(),
1212 lp_path(talloc_tos(), printdollar_snum),
1213 session_info, &oldcwd_fname);
1214 if (!NT_STATUS_IS_OK(nt_status)) {
1215 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1216 "returned %s\n", nt_errstr(nt_status)));
1217 err = ntstatus_to_werror(nt_status);
1221 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1222 if (!NT_STATUS_IS_OK(nt_status)) {
1223 DEBUG(0, ("failed set force user / group\n"));
1224 err = ntstatus_to_werror(nt_status);
1228 if (!become_user_by_session(conn, session_info)) {
1229 DEBUG(0, ("failed to become user\n"));
1230 err = WERR_ACCESS_DENIED;
1234 new_dir = talloc_asprintf(ctx,
1239 err = WERR_NOT_ENOUGH_MEMORY;
1242 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1243 if (!NT_STATUS_IS_OK(nt_status)) {
1244 err = WERR_NOT_ENOUGH_MEMORY;
1248 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1250 nt_status = create_directory(conn, NULL, smb_dname);
1251 if (!NT_STATUS_IS_OK(nt_status)
1252 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1253 DEBUG(0, ("failed to create driver destination directory: %s\n",
1254 nt_errstr(nt_status)));
1255 err = ntstatus_to_werror(nt_status);
1259 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1260 * listed for this driver which has already been moved, skip it (note:
1261 * drivers may list the same file name several times. Then check if the
1262 * file already exists in archi\version\, if so, check that the version
1263 * info (or time stamps if version info is unavailable) is newer (or the
1264 * date is later). If it is, move it to archi\version\filexxx.yyy.
1265 * Otherwise, delete the file.
1267 * If a file is not moved to archi\version\ because of an error, all the
1268 * rest of the 'unmoved' driver files are removed from archi\. If one or
1269 * more of the driver's files was already moved to archi\version\, it
1270 * potentially leaves the driver in a partially updated state. Version
1271 * trauma will most likely occur if an client attempts to use any printer
1272 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1273 * done is appropriate... later JRR
1276 DEBUG(5,("Moving files now !\n"));
1278 if (driver->driver_path && strlen(driver->driver_path)) {
1280 err = move_driver_file_to_download_area(ctx,
1282 driver->driver_path,
1287 if (!W_ERROR_IS_OK(err)) {
1292 if (driver->data_file && strlen(driver->data_file)) {
1293 if (!strequal(driver->data_file, driver->driver_path)) {
1295 err = move_driver_file_to_download_area(ctx,
1302 if (!W_ERROR_IS_OK(err)) {
1308 if (driver->config_file && strlen(driver->config_file)) {
1309 if (!strequal(driver->config_file, driver->driver_path) &&
1310 !strequal(driver->config_file, driver->data_file)) {
1312 err = move_driver_file_to_download_area(ctx,
1314 driver->config_file,
1319 if (!W_ERROR_IS_OK(err)) {
1325 if (driver->help_file && strlen(driver->help_file)) {
1326 if (!strequal(driver->help_file, driver->driver_path) &&
1327 !strequal(driver->help_file, driver->data_file) &&
1328 !strequal(driver->help_file, driver->config_file)) {
1330 err = move_driver_file_to_download_area(ctx,
1337 if (!W_ERROR_IS_OK(err)) {
1343 if (driver->dependent_files && driver->dependent_files->string) {
1344 for (i=0; driver->dependent_files->string[i]; i++) {
1345 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1346 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1347 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1348 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1350 for (j=0; j < i; j++) {
1351 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1356 err = move_driver_file_to_download_area(ctx,
1358 driver->dependent_files->string[i],
1363 if (!W_ERROR_IS_OK(err)) {
1375 TALLOC_FREE(smb_dname);
1378 vfs_ChDir(conn, oldcwd_fname);
1379 TALLOC_FREE(oldcwd_fname);
1380 SMB_VFS_DISCONNECT(conn);
1387 /****************************************************************************
1388 Determine whether or not a particular driver is currently assigned
1390 ****************************************************************************/
1392 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1393 struct dcerpc_binding_handle *b,
1394 const struct spoolss_DriverInfo8 *r)
1397 int n_services = lp_numservices();
1398 bool in_use = false;
1399 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1406 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1408 /* loop through the printers.tdb and check for the drivername */
1410 for (snum=0; snum<n_services && !in_use; snum++) {
1411 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1415 result = winreg_get_printer(mem_ctx, b,
1416 lp_servicename(talloc_tos(), snum),
1418 if (!W_ERROR_IS_OK(result)) {
1419 continue; /* skip */
1422 if (strequal(r->driver_name, pinfo2->drivername)) {
1426 TALLOC_FREE(pinfo2);
1429 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1432 struct spoolss_DriverInfo8 *driver = NULL;
1435 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1437 /* we can still remove the driver if there is one of
1438 "Windows NT x86" version 2 or 3 left */
1440 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1441 if (r->version == 2) {
1442 werr = winreg_get_driver(mem_ctx, b,
1446 } else if (r->version == 3) {
1447 werr = winreg_get_driver(mem_ctx, b,
1452 DBG_ERR("Unknown driver version (%d)\n",
1454 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1456 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1457 werr = winreg_get_driver(mem_ctx, b,
1458 SPOOLSS_ARCHITECTURE_NT_X86,
1463 DBG_ERR("Unknown driver architecture: %s\n",
1465 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1468 /* now check the error code */
1470 if ( W_ERROR_IS_OK(werr) ) {
1471 /* it's ok to remove the driver, we have other architctures left */
1473 talloc_free(driver);
1477 /* report that the driver is not in use by default */
1483 /**********************************************************************
1484 Check to see if a ogiven file is in use by *info
1485 *********************************************************************/
1487 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1494 /* mz: skip files that are in the list but already deleted */
1495 if (!file || !file[0]) {
1499 if (strequal(file, info->driver_path))
1502 if (strequal(file, info->data_file))
1505 if (strequal(file, info->config_file))
1508 if (strequal(file, info->help_file))
1511 /* see of there are any dependent files to examine */
1513 if (!info->dependent_files)
1516 while (info->dependent_files[i] && *info->dependent_files[i]) {
1517 if (strequal(file, info->dependent_files[i]))
1526 /**********************************************************************
1527 Utility function to remove the dependent file pointed to by the
1528 input parameter from the list
1529 *********************************************************************/
1531 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1534 /* bump everything down a slot */
1536 while (files && files[idx+1]) {
1537 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1546 /**********************************************************************
1547 Check if any of the files used by src are also used by drv
1548 *********************************************************************/
1550 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1551 struct spoolss_DriverInfo8 *src,
1552 const struct spoolss_DriverInfo8 *drv)
1554 bool in_use = False;
1560 /* check each file. Remove it from the src structure if it overlaps */
1562 if (drv_file_in_use(src->driver_path, drv)) {
1564 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1565 src->driver_path = talloc_strdup(mem_ctx, "");
1566 if (!src->driver_path) { return false; }
1569 if (drv_file_in_use(src->data_file, drv)) {
1571 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1572 src->data_file = talloc_strdup(mem_ctx, "");
1573 if (!src->data_file) { return false; }
1576 if (drv_file_in_use(src->config_file, drv)) {
1578 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1579 src->config_file = talloc_strdup(mem_ctx, "");
1580 if (!src->config_file) { return false; }
1583 if (drv_file_in_use(src->help_file, drv)) {
1585 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1586 src->help_file = talloc_strdup(mem_ctx, "");
1587 if (!src->help_file) { return false; }
1590 /* are there any dependentfiles to examine? */
1592 if (!src->dependent_files)
1595 while (src->dependent_files[i] && *src->dependent_files[i]) {
1596 if (drv_file_in_use(src->dependent_files[i], drv)) {
1598 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1599 trim_dependent_file(mem_ctx, src->dependent_files, i);
1607 /****************************************************************************
1608 Determine whether or not a particular driver files are currently being
1609 used by any other driver.
1611 Return value is True if any files were in use by other drivers
1612 and False otherwise.
1614 Upon return, *info has been modified to only contain the driver files
1615 which are not in use
1619 This needs to check all drivers to ensure that all files in use
1620 have been removed from *info, not just the ones in the first
1622 ****************************************************************************/
1624 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1625 struct dcerpc_binding_handle *b,
1626 struct spoolss_DriverInfo8 *info)
1630 struct spoolss_DriverInfo8 *driver;
1631 bool in_use = false;
1632 uint32_t num_drivers;
1633 const char **drivers;
1639 version = info->version;
1641 /* loop over all driver versions */
1643 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1645 /* get the list of drivers */
1647 result = winreg_get_driver_list(mem_ctx, b,
1648 info->architecture, version,
1649 &num_drivers, &drivers);
1650 if (!W_ERROR_IS_OK(result)) {
1654 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1655 num_drivers, info->architecture, version));
1657 /* check each driver for overlap in files */
1659 for (i = 0; i < num_drivers; i++) {
1660 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1664 result = winreg_get_driver(mem_ctx, b,
1665 info->architecture, drivers[i],
1667 if (!W_ERROR_IS_OK(result)) {
1668 talloc_free(drivers);
1672 /* check if d2 uses any files from d1 */
1673 /* only if this is a different driver than the one being deleted */
1675 if (!strequal(info->driver_name, driver->driver_name)) {
1676 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1677 /* mz: Do not instantly return -
1678 * we need to ensure this file isn't
1679 * also in use by other drivers. */
1684 talloc_free(driver);
1687 talloc_free(drivers);
1689 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1694 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1695 const char *short_arch,
1699 TALLOC_CTX *tmp_ctx = talloc_new(conn);
1700 struct smb_filename *smb_fname = NULL;
1701 char *print_dlr_path;
1702 NTSTATUS status = NT_STATUS_NO_MEMORY;
1704 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
1705 short_arch, vers, fname);
1706 if (print_dlr_path == NULL) {
1710 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
1711 if (smb_fname == NULL) {
1715 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1717 talloc_free(tmp_ctx);
1721 /****************************************************************************
1722 Actually delete the driver files. Make sure that
1723 printer_driver_files_in_use() return False before calling
1725 ****************************************************************************/
1727 bool delete_driver_files(const struct auth_session_info *session_info,
1728 const struct spoolss_DriverInfo8 *r)
1730 const char *short_arch;
1731 connection_struct *conn;
1733 struct smb_filename *oldcwd_fname = NULL;
1734 char *printdollar = NULL;
1735 int printdollar_snum;
1742 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1743 r->driver_name, r->version));
1745 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1749 if (printdollar_snum == -1) {
1753 nt_status = create_conn_struct_cwd(talloc_tos(),
1754 server_event_context(),
1755 server_messaging_context(),
1758 lp_path(talloc_tos(), printdollar_snum),
1759 session_info, &oldcwd_fname);
1760 if (!NT_STATUS_IS_OK(nt_status)) {
1761 DEBUG(0,("delete_driver_files: create_conn_struct "
1762 "returned %s\n", nt_errstr(nt_status)));
1766 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1767 if (!NT_STATUS_IS_OK(nt_status)) {
1768 DEBUG(0, ("failed set force user / group\n"));
1773 if (!become_user_by_session(conn, session_info)) {
1774 DEBUG(0, ("failed to become user\n"));
1779 if ( !CAN_WRITE(conn) ) {
1780 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1785 short_arch = get_short_archi(r->architecture);
1786 if (short_arch == NULL) {
1787 DEBUG(0, ("bad architecture %s\n", r->architecture));
1792 /* now delete the files */
1794 if (r->driver_path && r->driver_path[0]) {
1795 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
1796 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
1799 if (r->config_file && r->config_file[0]) {
1800 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
1801 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
1804 if (r->data_file && r->data_file[0]) {
1805 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
1806 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
1809 if (r->help_file && r->help_file[0]) {
1810 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
1811 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
1814 if (r->dependent_files) {
1816 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1817 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
1818 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
1828 vfs_ChDir(conn, oldcwd_fname);
1829 TALLOC_FREE(oldcwd_fname);
1830 SMB_VFS_DISCONNECT(conn);
1838 1: level not implemented
1839 2: file doesn't exist
1840 3: can't allocate memory
1841 4: can't free memory
1842 5: non existent struct
1846 A printer and a printer driver are 2 different things.
1847 NT manages them separatelly, Samba does the same.
1848 Why ? Simply because it's easier and it makes sense !
1850 Now explanation: You have 3 printers behind your samba server,
1851 2 of them are the same make and model (laser A and B). But laser B
1852 has an 3000 sheet feeder and laser A doesn't such an option.
1853 Your third printer is an old dot-matrix model for the accounting :-).
1855 If the /usr/local/samba/lib directory (default dir), you will have
1856 5 files to describe all of this.
1858 3 files for the printers (1 by printer):
1861 NTprinter_accounting
1862 2 files for the drivers (1 for the laser and 1 for the dot matrix)
1863 NTdriver_printer model X
1864 NTdriver_printer model Y
1866 jfm: I should use this comment for the text file to explain
1867 same thing for the forms BTW.
1868 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1872 /* Convert generic access rights to printer object specific access rights.
1873 It turns out that NT4 security descriptors use generic access rights and
1874 NT5 the object specific ones. */
1876 void map_printer_permissions(struct security_descriptor *sd)
1880 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1881 se_map_generic(&sd->dacl->aces[i].access_mask,
1882 &printer_generic_mapping);
1886 void map_job_permissions(struct security_descriptor *sd)
1890 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1891 se_map_generic(&sd->dacl->aces[i].access_mask,
1892 &job_generic_mapping);
1897 /****************************************************************************
1898 Check a user has permissions to perform the given operation. We use the
1899 permission constants defined in include/rpc_spoolss.h to check the various
1900 actions we perform when checking printer access.
1902 PRINTER_ACCESS_ADMINISTER:
1903 print_queue_pause, print_queue_resume, update_printer_sec,
1904 update_printer, spoolss_addprinterex_level_2,
1905 _spoolss_setprinterdata
1910 JOB_ACCESS_ADMINISTER:
1911 print_job_delete, print_job_pause, print_job_resume,
1914 Try access control in the following order (for performance reasons):
1915 1) root and SE_PRINT_OPERATOR can do anything (easy check)
1916 2) check security descriptor (bit comparisons in memory)
1917 3) "printer admins" (may result in numerous calls to winbind)
1919 ****************************************************************************/
1920 WERROR print_access_check(const struct auth_session_info *session_info,
1921 struct messaging_context *msg_ctx, int snum,
1924 struct spoolss_security_descriptor *secdesc = NULL;
1925 uint32_t access_granted;
1930 TALLOC_CTX *mem_ctx = NULL;
1932 /* If user is NULL then use the current_user structure */
1934 /* Always allow root or SE_PRINT_OPERATROR to do anything */
1936 if ((session_info->unix_token->uid == sec_initial_uid())
1937 || security_token_has_privilege(session_info->security_token,
1938 SEC_PRIV_PRINT_OPERATOR)) {
1942 /* Get printer name */
1944 pname = lp_printername(talloc_tos(), snum);
1946 if (!pname || !*pname) {
1947 return WERR_ACCESS_DENIED;
1950 /* Get printer security descriptor */
1952 if(!(mem_ctx = talloc_init("print_access_check"))) {
1953 return WERR_NOT_ENOUGH_MEMORY;
1956 result = winreg_get_printer_secdesc_internal(mem_ctx,
1957 get_session_info_system(),
1961 if (!W_ERROR_IS_OK(result)) {
1962 talloc_destroy(mem_ctx);
1963 return WERR_NOT_ENOUGH_MEMORY;
1966 if (access_type == JOB_ACCESS_ADMINISTER) {
1967 struct spoolss_security_descriptor *parent_secdesc = secdesc;
1969 /* Create a child security descriptor to check permissions
1970 against. This is because print jobs are child objects
1971 objects of a printer. */
1972 status = se_create_child_secdesc(mem_ctx,
1976 parent_secdesc->owner_sid,
1977 parent_secdesc->group_sid,
1979 if (!NT_STATUS_IS_OK(status)) {
1980 talloc_destroy(mem_ctx);
1981 return ntstatus_to_werror(status);
1984 map_job_permissions(secdesc);
1986 map_printer_permissions(secdesc);
1990 status = se_access_check(secdesc, session_info->security_token, access_type,
1993 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
1995 talloc_destroy(mem_ctx);
1997 return ntstatus_to_werror(status);
2000 /****************************************************************************
2001 Check the time parameters allow a print operation.
2002 *****************************************************************************/
2004 bool print_time_access_check(const struct auth_session_info *session_info,
2005 struct messaging_context *msg_ctx,
2006 const char *servicename)
2008 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2011 time_t now = time(NULL);
2015 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2016 servicename, &pinfo2);
2017 if (!W_ERROR_IS_OK(result)) {
2021 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2026 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2028 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2032 TALLOC_FREE(pinfo2);
2041 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2042 const struct auth_session_info *session_info,
2043 struct messaging_context *msg_ctx,
2044 const char *printer)
2048 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2050 if (!W_ERROR_IS_OK(result)) {
2051 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2052 "%s\n", printer, win_errstr(result)));
2056 void nt_printer_add(TALLOC_CTX *mem_ctx,
2057 const struct auth_session_info *session_info,
2058 struct messaging_context *msg_ctx,
2059 const char *printer)
2063 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2065 if (!W_ERROR_IS_OK(result)) {
2066 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2067 printer, win_errstr(result)));