2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "printing/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.h"
38 /* Map generic permissions to printer object specific permissions */
40 const struct generic_mapping printer_generic_mapping = {
47 /* Map generic permissions to print server object specific permissions */
49 const struct generic_mapping printserver_generic_mapping = {
56 /* Map generic permissions to job object specific permissions */
58 const struct generic_mapping job_generic_mapping = {
65 static const struct print_architecture_table_node archi_table[]= {
67 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
68 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
69 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
70 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
71 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
72 {"Windows IA64", SPL_ARCH_IA64, 3 },
73 {"Windows x64", SPL_ARCH_X64, 3 },
77 static bool print_driver_directories_init(void)
82 TALLOC_CTX *mem_ctx = talloc_stackframe();
83 const char *dir_list[] = {
89 service = lp_servicenumber("print$");
91 /* We don't have a print$ share */
92 DEBUG(5, ("No print$ share has been configured.\n"));
97 driver_path = lp_path(mem_ctx, service);
98 if (driver_path == NULL) {
103 ok = directory_create_or_exist(driver_path, 0755);
105 DEBUG(1, ("Failed to create printer driver directory %s\n",
107 talloc_free(mem_ctx);
111 for (i = 0; archi_table[i].long_archi != NULL; i++) {
112 const char *arch_path;
114 arch_path = talloc_asprintf(mem_ctx,
117 archi_table[i].short_archi);
118 if (arch_path == NULL) {
119 talloc_free(mem_ctx);
123 ok = directory_create_or_exist(arch_path, 0755);
125 DEBUG(1, ("Failed to create printer driver "
126 "architecture directory %s\n",
128 talloc_free(mem_ctx);
133 for (i = 0; i < ARRAY_SIZE(dir_list); i++) {
136 path = talloc_asprintf(mem_ctx,
141 talloc_free(mem_ctx);
145 ok = directory_create_or_exist(path, 0755);
147 DEBUG(1, ("Failed to create printer driver "
148 "architecture directory %s\n",
150 talloc_free(mem_ctx);
155 talloc_free(mem_ctx);
159 /****************************************************************************
160 Forward a MSG_PRINTER_DRVUPGRADE message from another smbd to the
161 background lpq updater.
162 ****************************************************************************/
164 static void forward_drv_upgrade_printer_msg(struct messaging_context *msg,
167 struct server_id server_id,
170 extern pid_t background_lpq_updater_pid;
172 if (background_lpq_updater_pid == -1) {
173 DEBUG(3,("no background lpq queue updater\n"));
177 messaging_send_buf(msg,
178 pid_to_procid(background_lpq_updater_pid),
179 MSG_PRINTER_DRVUPGRADE,
184 /****************************************************************************
185 Open the NT printing tdbs. Done once before fork().
186 ****************************************************************************/
188 bool nt_printing_init(struct messaging_context *msg_ctx)
192 if (!print_driver_directories_init()) {
196 if (!nt_printing_tdb_upgrade()) {
201 * register callback to handle updating printers as new
202 * drivers are installed. Forwards to background lpq updater.
204 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
205 forward_drv_upgrade_printer_msg);
207 /* of course, none of the message callbacks matter if you don't
208 tell messages.c that you interested in receiving PRINT_GENERAL
209 msgs. This is done in serverid_register() */
211 if ( lp_security() == SEC_ADS ) {
212 win_rc = check_published_printers(msg_ctx);
213 if (!W_ERROR_IS_OK(win_rc))
214 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
220 /*******************************************************************
221 Function to allow filename parsing "the old way".
222 ********************************************************************/
224 static NTSTATUS driver_unix_convert(connection_struct *conn,
225 const char *old_name,
226 struct smb_filename **smb_fname)
229 TALLOC_CTX *ctx = talloc_tos();
230 char *name = talloc_strdup(ctx, old_name);
233 return NT_STATUS_NO_MEMORY;
236 name = unix_clean_name(ctx, name);
238 return NT_STATUS_NO_MEMORY;
240 trim_string(name,"/","/");
242 status = unix_convert(ctx, conn, name, smb_fname, 0);
243 if (!NT_STATUS_IS_OK(status)) {
244 return NT_STATUS_NO_MEMORY;
250 /****************************************************************************
251 Function to do the mapping between the long architecture name and
253 ****************************************************************************/
255 const char *get_short_archi(const char *long_archi)
259 DEBUG(107,("Getting architecture dependent directory\n"));
262 } while ( (archi_table[i].long_archi!=NULL ) &&
263 strcasecmp_m(long_archi, archi_table[i].long_archi) );
265 if (archi_table[i].long_archi==NULL) {
266 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
270 /* this might be client code - but shouldn't this be an fstrcpy etc? */
272 DEBUGADD(108,("index: [%d]\n", i));
273 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
274 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
276 return archi_table[i].short_archi;
279 /****************************************************************************
280 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
281 There are two case to be covered here: PE (Portable Executable) and NE (New
282 Executable) files. Both files support the same INFO structure, but PE files
283 store the signature in unicode, and NE files store it as !unicode.
284 returns -1 on error, 1 on version info found, and 0 on no version info found.
285 ****************************************************************************/
287 static int get_file_version(files_struct *fsp, char *fname,uint32_t *major, uint32_t *minor)
293 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
294 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
295 fname, DOS_HEADER_SIZE));
299 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
300 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
301 fname, (unsigned long)byte_count));
302 goto no_version_info;
305 /* Is this really a DOS header? */
306 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
307 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
308 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
309 goto no_version_info;
312 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
313 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (off_t)-1) {
314 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
316 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
317 goto no_version_info;
320 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
321 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
322 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
323 fname, (unsigned long)byte_count));
324 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
325 goto no_version_info;
328 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
329 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
330 unsigned int num_sections;
331 unsigned int section_table_bytes;
333 /* Just skip over optional header to get to section table */
334 if (SMB_VFS_LSEEK(fsp,
335 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
336 SEEK_CUR) == (off_t)-1) {
337 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
342 /* get the section table */
343 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
344 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
345 if (section_table_bytes == 0)
349 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
350 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
351 fname, section_table_bytes));
355 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
356 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
357 fname, (unsigned long)byte_count));
361 /* Iterate the section table looking for the resource section ".rsrc" */
362 for (i = 0; i < num_sections; i++) {
363 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
365 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
366 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
367 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
369 if (section_bytes == 0)
373 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
374 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
375 fname, section_bytes));
379 /* Seek to the start of the .rsrc section info */
380 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (off_t)-1) {
381 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
386 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
387 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
388 fname, (unsigned long)byte_count));
392 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
395 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
396 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
397 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
398 /* Align to next long address */
399 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
401 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
402 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
403 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
405 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
406 fname, *major, *minor,
407 (*major>>16)&0xffff, *major&0xffff,
408 (*minor>>16)&0xffff, *minor&0xffff));
417 /* Version info not found, fall back to origin date/time */
418 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
422 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
423 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
424 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
425 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
426 /* At this point, we assume the file is in error. It still could be something
427 * else besides a NE file, but it unlikely at this point. */
431 /* Allocate a bit more space to speed up things */
433 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
434 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
435 fname, PE_HEADER_SIZE));
439 /* This is a HACK! I got tired of trying to sort through the messy
440 * 'NE' file format. If anyone wants to clean this up please have at
441 * it, but this works. 'NE' files will eventually fade away. JRR */
442 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
443 /* Cover case that should not occur in a well formed 'NE' .dll file */
444 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
446 for(i=0; i<byte_count; i++) {
447 /* Fast skip past data that can't possibly match */
448 if (buf[i] != 'V') continue;
450 /* Potential match data crosses buf boundry, move it to beginning
451 * of buf, and fill the buf with as much as it will hold. */
452 if (i>byte_count-VS_VERSION_INFO_SIZE) {
455 memcpy(buf, &buf[i], byte_count-i);
456 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
457 (byte_count-i))) < 0) {
459 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
464 byte_count = bc + (byte_count - i);
465 if (byte_count<VS_VERSION_INFO_SIZE) break;
470 /* Check that the full signature string and the magic number that
471 * follows exist (not a perfect solution, but the chances that this
472 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
473 * twice, as it is simpler to read the code. */
474 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
475 /* Compute skip alignment to next long address */
476 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
477 sizeof(VS_SIGNATURE)) & 3;
478 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
480 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
481 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
482 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
483 fname, *major, *minor,
484 (*major>>16)&0xffff, *major&0xffff,
485 (*minor>>16)&0xffff, *minor&0xffff));
492 /* Version info not found, fall back to origin date/time */
493 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
498 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
499 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
500 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
511 /****************************************************************************
512 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
513 share one or more files. During the MS installation process files are checked
514 to insure that only a newer version of a shared file is installed over an
515 older version. There are several possibilities for this comparison. If there
516 is no previous version, the new one is newer (obviously). If either file is
517 missing the version info structure, compare the creation date (on Unix use
518 the modification date). Otherwise chose the numerically larger version number.
519 ****************************************************************************/
521 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
523 bool use_version = true;
527 time_t new_create_time;
531 time_t old_create_time;
533 struct smb_filename *smb_fname = NULL;
534 files_struct *fsp = NULL;
540 SET_STAT_INVALID(st);
541 new_create_time = (time_t)0;
542 old_create_time = (time_t)0;
544 /* Get file version info (if available) for previous file (if it exists) */
545 status = driver_unix_convert(conn, old_file, &smb_fname);
546 if (!NT_STATUS_IS_OK(status)) {
550 status = SMB_VFS_CREATE_FILE(
553 0, /* root_dir_fid */
554 smb_fname, /* fname */
555 FILE_GENERIC_READ, /* access_mask */
556 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
557 FILE_OPEN, /* create_disposition*/
558 0, /* create_options */
559 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
560 INTERNAL_OPEN_ONLY, /* oplock_request */
562 0, /* allocation_size */
563 0, /* private_flags */
568 NULL, NULL); /* create context */
570 if (!NT_STATUS_IS_OK(status)) {
571 /* Old file not found, so by definition new file is in fact newer */
572 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
573 "errno = %d\n", smb_fname_str_dbg(smb_fname),
579 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
585 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
588 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
591 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
592 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
593 (long)old_create_time));
596 close_file(NULL, fsp, NORMAL_CLOSE);
599 /* Get file version info (if available) for new file */
600 status = driver_unix_convert(conn, new_file, &smb_fname);
601 if (!NT_STATUS_IS_OK(status)) {
605 status = SMB_VFS_CREATE_FILE(
608 0, /* root_dir_fid */
609 smb_fname, /* fname */
610 FILE_GENERIC_READ, /* access_mask */
611 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
612 FILE_OPEN, /* create_disposition*/
613 0, /* create_options */
614 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
615 INTERNAL_OPEN_ONLY, /* oplock_request */
617 0, /* allocation_size */
618 0, /* private_flags */
623 NULL, NULL); /* create context */
625 if (!NT_STATUS_IS_OK(status)) {
626 /* New file not found, this shouldn't occur if the caller did its job */
627 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
628 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
632 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
638 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
641 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
644 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
645 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
646 (long)new_create_time));
649 close_file(NULL, fsp, NORMAL_CLOSE);
652 if (use_version && (new_major != old_major || new_minor != old_minor)) {
653 /* Compare versions and choose the larger version number */
654 if (new_major > old_major ||
655 (new_major == old_major && new_minor > old_minor)) {
657 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
662 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
668 /* Compare modification time/dates and choose the newest time/date */
669 if (new_create_time > old_create_time) {
670 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
675 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
683 close_file(NULL, fsp, NORMAL_CLOSE);
686 TALLOC_FREE(smb_fname);
690 /****************************************************************************
691 Determine the correct cVersion associated with an architecture and driver
692 ****************************************************************************/
693 static uint32_t get_correct_cversion(struct auth_session_info *session_info,
694 const char *architecture,
695 const char *driverpath_in,
696 const char *driver_directory,
701 struct smb_filename *smb_fname = NULL;
702 files_struct *fsp = NULL;
703 connection_struct *conn = NULL;
704 struct smb_filename *oldcwd_fname = NULL;
705 char *printdollar = NULL;
706 char *printdollar_path = NULL;
707 char *working_dir = NULL;
708 int printdollar_snum;
710 *perr = WERR_INVALID_PARAMETER;
712 /* If architecture is Windows 95/98/ME, the version is always 0. */
713 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
714 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
719 /* If architecture is Windows x64, the version is always 3. */
720 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
721 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
726 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
728 *perr = WERR_NOT_ENOUGH_MEMORY;
731 if (printdollar_snum == -1) {
732 *perr = WERR_BAD_NET_NAME;
736 printdollar_path = lp_path(talloc_tos(), printdollar_snum);
737 if (printdollar_path == NULL) {
738 *perr = WERR_NOT_ENOUGH_MEMORY;
742 working_dir = talloc_asprintf(talloc_tos(),
747 * If the driver has been uploaded into a temorpary driver
748 * directory, switch to the driver directory.
750 if (driver_directory != NULL) {
751 working_dir = talloc_asprintf(talloc_tos(), "%s/%s/%s",
757 nt_status = create_conn_struct_cwd(talloc_tos(),
758 server_event_context(),
759 server_messaging_context(),
763 session_info, &oldcwd_fname);
764 if (!NT_STATUS_IS_OK(nt_status)) {
765 DEBUG(0,("get_correct_cversion: create_conn_struct "
766 "returned %s\n", nt_errstr(nt_status)));
767 *perr = ntstatus_to_werror(nt_status);
771 nt_status = set_conn_force_user_group(conn, printdollar_snum);
772 if (!NT_STATUS_IS_OK(nt_status)) {
773 DEBUG(0, ("failed set force user / group\n"));
774 *perr = ntstatus_to_werror(nt_status);
775 goto error_free_conn;
778 if (!become_user_by_session(conn, session_info)) {
779 DEBUG(0, ("failed to become user\n"));
780 *perr = WERR_ACCESS_DENIED;
781 goto error_free_conn;
785 * We switch to the directory where the driver files are located,
786 * so only work on the file names
788 nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
789 if (!NT_STATUS_IS_OK(nt_status)) {
790 *perr = ntstatus_to_werror(nt_status);
794 nt_status = vfs_file_exist(conn, smb_fname);
795 if (!NT_STATUS_IS_OK(nt_status)) {
796 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
797 *perr = WERR_FILE_NOT_FOUND;
801 nt_status = SMB_VFS_CREATE_FILE(
804 0, /* root_dir_fid */
805 smb_fname, /* fname */
806 FILE_GENERIC_READ, /* access_mask */
807 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
808 FILE_OPEN, /* create_disposition*/
809 0, /* create_options */
810 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
811 INTERNAL_OPEN_ONLY, /* oplock_request */
813 0, /* private_flags */
814 0, /* allocation_size */
819 NULL, NULL); /* create context */
821 if (!NT_STATUS_IS_OK(nt_status)) {
822 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
823 "%d\n", smb_fname_str_dbg(smb_fname), errno));
824 *perr = WERR_ACCESS_DENIED;
831 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
833 *perr = WERR_INVALID_PARAMETER;
836 DEBUG(6,("get_correct_cversion: Version info not "
838 smb_fname_str_dbg(smb_fname)));
839 *perr = WERR_INVALID_PARAMETER;
844 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
845 * for more details. Version in this case is not just the version of the
846 * file, but the version in the sense of kernal mode (2) vs. user mode
847 * (3) drivers. Other bits of the version fields are the version info.
850 cversion = major & 0x0000ffff;
852 case 2: /* WinNT drivers */
853 case 3: /* Win2K drivers */
857 DEBUG(6,("get_correct_cversion: cversion "
858 "invalid [%s] cversion = %d\n",
859 smb_fname_str_dbg(smb_fname),
864 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
865 " = 0x%x minor = 0x%x\n",
866 smb_fname_str_dbg(smb_fname), major, minor));
869 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
870 smb_fname_str_dbg(smb_fname), cversion));
876 TALLOC_FREE(smb_fname);
878 close_file(NULL, fsp, NORMAL_CLOSE);
881 vfs_ChDir(conn, oldcwd_fname);
882 TALLOC_FREE(oldcwd_fname);
883 SMB_VFS_DISCONNECT(conn);
886 if (!W_ERROR_IS_OK(*perr)) {
893 /****************************************************************************
894 ****************************************************************************/
896 #define strip_driver_path(_mem_ctx, _element) do { \
897 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
898 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
899 W_ERROR_HAVE_NO_MEMORY((_element)); \
903 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
904 struct auth_session_info *session_info,
905 const char *architecture,
906 const char **driver_path,
907 const char **data_file,
908 const char **config_file,
909 const char **help_file,
910 struct spoolss_StringArray *dependent_files,
911 enum spoolss_DriverOSVersion *version,
913 const char **driver_directory)
915 const char *short_architecture;
920 if (!*driver_path || !*data_file) {
921 return WERR_INVALID_PARAMETER;
924 if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
925 return WERR_INVALID_PARAMETER;
928 if (flags & APD_COPY_FROM_DIRECTORY) {
933 * driver_path is set to:
935 * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
937 path = talloc_strdup(mem_ctx, *driver_path);
939 return WERR_NOT_ENOUGH_MEMORY;
942 /* Remove pscript5.dll */
943 q = strrchr_m(path, '\\');
945 return WERR_INVALID_PARAMETER;
949 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
950 q = strrchr_m(path, '\\');
952 return WERR_INVALID_PARAMETER;
956 * Set driver_directory to:
958 * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
960 * This is the directory where all the files have been uploaded
962 *driver_directory = q + 1;
965 /* clean up the driver name.
966 * we can get .\driver.dll
967 * or worse c:\windows\system\driver.dll !
969 /* using an intermediate string to not have overlaping memcpy()'s */
971 strip_driver_path(mem_ctx, *driver_path);
972 strip_driver_path(mem_ctx, *data_file);
974 strip_driver_path(mem_ctx, *config_file);
977 strip_driver_path(mem_ctx, *help_file);
980 if (dependent_files && dependent_files->string) {
981 for (i=0; dependent_files->string[i]; i++) {
982 strip_driver_path(mem_ctx, dependent_files->string[i]);
986 short_architecture = get_short_archi(architecture);
987 if (!short_architecture) {
988 return WERR_UNKNOWN_PRINTER_DRIVER;
991 /* jfm:7/16/2000 the client always sends the cversion=0.
992 * The server should check which version the driver is by reading
993 * the PE header of driver->driverpath.
995 * For Windows 95/98 the version is 0 (so the value sent is correct)
996 * For Windows NT (the architecture doesn't matter)
998 * NT 3.5/3.51: cversion=1
1003 *version = get_correct_cversion(session_info,
1008 if (*version == -1) {
1015 /****************************************************************************
1016 ****************************************************************************/
1018 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1019 struct auth_session_info *session_info,
1020 struct spoolss_AddDriverInfoCtr *r,
1022 const char **driver_directory)
1026 return clean_up_driver_struct_level(mem_ctx, session_info,
1027 r->info.info3->architecture,
1028 &r->info.info3->driver_path,
1029 &r->info.info3->data_file,
1030 &r->info.info3->config_file,
1031 &r->info.info3->help_file,
1032 r->info.info3->dependent_files,
1033 &r->info.info3->version,
1037 return clean_up_driver_struct_level(mem_ctx, session_info,
1038 r->info.info6->architecture,
1039 &r->info.info6->driver_path,
1040 &r->info.info6->data_file,
1041 &r->info.info6->config_file,
1042 &r->info.info6->help_file,
1043 r->info.info6->dependent_files,
1044 &r->info.info6->version,
1048 return clean_up_driver_struct_level(mem_ctx, session_info,
1049 r->info.info8->architecture,
1050 &r->info.info8->driver_path,
1051 &r->info.info8->data_file,
1052 &r->info.info8->config_file,
1053 &r->info.info8->help_file,
1054 r->info.info8->dependent_files,
1055 &r->info.info8->version,
1059 return WERR_NOT_SUPPORTED;
1063 /****************************************************************************
1064 This function sucks and should be replaced. JRA.
1065 ****************************************************************************/
1067 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1068 const struct spoolss_AddDriverInfo6 *src)
1070 dst->version = src->version;
1072 dst->driver_name = src->driver_name;
1073 dst->architecture = src->architecture;
1074 dst->driver_path = src->driver_path;
1075 dst->data_file = src->data_file;
1076 dst->config_file = src->config_file;
1077 dst->help_file = src->help_file;
1078 dst->monitor_name = src->monitor_name;
1079 dst->default_datatype = src->default_datatype;
1080 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1081 dst->dependent_files = src->dependent_files;
1084 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1085 const struct spoolss_AddDriverInfo8 *src)
1087 dst->version = src->version;
1089 dst->driver_name = src->driver_name;
1090 dst->architecture = src->architecture;
1091 dst->driver_path = src->driver_path;
1092 dst->data_file = src->data_file;
1093 dst->config_file = src->config_file;
1094 dst->help_file = src->help_file;
1095 dst->monitor_name = src->monitor_name;
1096 dst->default_datatype = src->default_datatype;
1097 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1098 dst->dependent_files = src->dependent_files;
1101 /****************************************************************************
1102 ****************************************************************************/
1104 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1105 connection_struct *conn,
1106 const char *driver_file,
1107 const char *short_architecture,
1108 uint32_t driver_version,
1110 const char *driver_directory)
1112 struct smb_filename *smb_fname_old = NULL;
1113 struct smb_filename *smb_fname_new = NULL;
1114 char *old_name = NULL;
1115 char *new_name = NULL;
1119 if (driver_directory != NULL) {
1120 old_name = talloc_asprintf(mem_ctx,
1126 old_name = talloc_asprintf(mem_ctx,
1131 if (old_name == NULL) {
1132 return WERR_NOT_ENOUGH_MEMORY;
1135 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1136 short_architecture, driver_version, driver_file);
1137 if (new_name == NULL) {
1138 TALLOC_FREE(old_name);
1139 return WERR_NOT_ENOUGH_MEMORY;
1142 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1144 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1145 if (!NT_STATUS_IS_OK(status)) {
1146 ret = WERR_NOT_ENOUGH_MEMORY;
1150 /* Setup a synthetic smb_filename struct */
1151 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1152 if (!smb_fname_new) {
1153 ret = WERR_NOT_ENOUGH_MEMORY;
1157 smb_fname_new->base_name = new_name;
1159 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1160 "'%s'\n", smb_fname_old->base_name,
1161 smb_fname_new->base_name));
1163 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1164 OPENX_FILE_EXISTS_TRUNCATE |
1165 OPENX_FILE_CREATE_IF_NOT_EXIST,
1168 if (!NT_STATUS_IS_OK(status)) {
1169 DEBUG(0,("move_driver_file_to_download_area: Unable "
1170 "to rename [%s] to [%s]: %s\n",
1171 smb_fname_old->base_name, new_name,
1172 nt_errstr(status)));
1173 ret = WERR_ACCESS_DENIED;
1180 TALLOC_FREE(smb_fname_old);
1181 TALLOC_FREE(smb_fname_new);
1185 WERROR move_driver_to_download_area(struct auth_session_info *session_info,
1186 struct spoolss_AddDriverInfoCtr *r,
1187 const char *driver_directory)
1189 struct spoolss_AddDriverInfo3 *driver;
1190 struct spoolss_AddDriverInfo3 converted_driver;
1191 const char *short_architecture;
1192 struct smb_filename *smb_dname = NULL;
1193 char *new_dir = NULL;
1194 connection_struct *conn = NULL;
1197 TALLOC_CTX *ctx = talloc_tos();
1199 struct smb_filename *oldcwd_fname = NULL;
1200 char *printdollar = NULL;
1201 int printdollar_snum;
1202 WERROR err = WERR_OK;
1206 driver = r->info.info3;
1209 convert_level_6_to_level3(&converted_driver, r->info.info6);
1210 driver = &converted_driver;
1213 convert_level_8_to_level3(&converted_driver, r->info.info8);
1214 driver = &converted_driver;
1217 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1218 return WERR_INVALID_LEVEL;
1221 short_architecture = get_short_archi(driver->architecture);
1222 if (!short_architecture) {
1223 return WERR_UNKNOWN_PRINTER_DRIVER;
1226 printdollar_snum = find_service(ctx, "print$", &printdollar);
1228 return WERR_NOT_ENOUGH_MEMORY;
1230 if (printdollar_snum == -1) {
1231 return WERR_BAD_NET_NAME;
1234 nt_status = create_conn_struct_cwd(talloc_tos(),
1235 server_event_context(),
1236 server_messaging_context(),
1239 lp_path(talloc_tos(), printdollar_snum),
1240 session_info, &oldcwd_fname);
1241 if (!NT_STATUS_IS_OK(nt_status)) {
1242 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1243 "returned %s\n", nt_errstr(nt_status)));
1244 err = ntstatus_to_werror(nt_status);
1248 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1249 if (!NT_STATUS_IS_OK(nt_status)) {
1250 DEBUG(0, ("failed set force user / group\n"));
1251 err = ntstatus_to_werror(nt_status);
1255 if (!become_user_by_session(conn, session_info)) {
1256 DEBUG(0, ("failed to become user\n"));
1257 err = WERR_ACCESS_DENIED;
1261 new_dir = talloc_asprintf(ctx,
1266 err = WERR_NOT_ENOUGH_MEMORY;
1269 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1270 if (!NT_STATUS_IS_OK(nt_status)) {
1271 err = WERR_NOT_ENOUGH_MEMORY;
1275 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1277 nt_status = create_directory(conn, NULL, smb_dname);
1278 if (!NT_STATUS_IS_OK(nt_status)
1279 && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1280 DEBUG(0, ("failed to create driver destination directory: %s\n",
1281 nt_errstr(nt_status)));
1282 err = ntstatus_to_werror(nt_status);
1286 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1287 * listed for this driver which has already been moved, skip it (note:
1288 * drivers may list the same file name several times. Then check if the
1289 * file already exists in archi\version\, if so, check that the version
1290 * info (or time stamps if version info is unavailable) is newer (or the
1291 * date is later). If it is, move it to archi\version\filexxx.yyy.
1292 * Otherwise, delete the file.
1294 * If a file is not moved to archi\version\ because of an error, all the
1295 * rest of the 'unmoved' driver files are removed from archi\. If one or
1296 * more of the driver's files was already moved to archi\version\, it
1297 * potentially leaves the driver in a partially updated state. Version
1298 * trauma will most likely occur if an client attempts to use any printer
1299 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1300 * done is appropriate... later JRR
1303 DEBUG(5,("Moving files now !\n"));
1305 if (driver->driver_path && strlen(driver->driver_path)) {
1307 err = move_driver_file_to_download_area(ctx,
1309 driver->driver_path,
1314 if (!W_ERROR_IS_OK(err)) {
1319 if (driver->data_file && strlen(driver->data_file)) {
1320 if (!strequal(driver->data_file, driver->driver_path)) {
1322 err = move_driver_file_to_download_area(ctx,
1329 if (!W_ERROR_IS_OK(err)) {
1335 if (driver->config_file && strlen(driver->config_file)) {
1336 if (!strequal(driver->config_file, driver->driver_path) &&
1337 !strequal(driver->config_file, driver->data_file)) {
1339 err = move_driver_file_to_download_area(ctx,
1341 driver->config_file,
1346 if (!W_ERROR_IS_OK(err)) {
1352 if (driver->help_file && strlen(driver->help_file)) {
1353 if (!strequal(driver->help_file, driver->driver_path) &&
1354 !strequal(driver->help_file, driver->data_file) &&
1355 !strequal(driver->help_file, driver->config_file)) {
1357 err = move_driver_file_to_download_area(ctx,
1364 if (!W_ERROR_IS_OK(err)) {
1370 if (driver->dependent_files && driver->dependent_files->string) {
1371 for (i=0; driver->dependent_files->string[i]; i++) {
1372 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1373 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1374 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1375 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1377 for (j=0; j < i; j++) {
1378 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1383 err = move_driver_file_to_download_area(ctx,
1385 driver->dependent_files->string[i],
1390 if (!W_ERROR_IS_OK(err)) {
1402 TALLOC_FREE(smb_dname);
1405 vfs_ChDir(conn, oldcwd_fname);
1406 TALLOC_FREE(oldcwd_fname);
1407 SMB_VFS_DISCONNECT(conn);
1414 /****************************************************************************
1415 Determine whether or not a particular driver is currently assigned
1417 ****************************************************************************/
1419 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1420 struct dcerpc_binding_handle *b,
1421 const struct spoolss_DriverInfo8 *r)
1424 int n_services = lp_numservices();
1425 bool in_use = false;
1426 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1433 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1435 /* loop through the printers.tdb and check for the drivername */
1437 for (snum=0; snum<n_services && !in_use; snum++) {
1438 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1442 result = winreg_get_printer(mem_ctx, b,
1443 lp_servicename(talloc_tos(), snum),
1445 if (!W_ERROR_IS_OK(result)) {
1446 continue; /* skip */
1449 if (strequal(r->driver_name, pinfo2->drivername)) {
1453 TALLOC_FREE(pinfo2);
1456 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1459 struct spoolss_DriverInfo8 *driver = NULL;
1462 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1464 /* we can still remove the driver if there is one of
1465 "Windows NT x86" version 2 or 3 left */
1467 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1468 if (r->version == 2) {
1469 werr = winreg_get_driver(mem_ctx, b,
1473 } else if (r->version == 3) {
1474 werr = winreg_get_driver(mem_ctx, b,
1479 DBG_ERR("Unknown driver version (%d)\n",
1481 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1483 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1484 werr = winreg_get_driver(mem_ctx, b,
1485 SPOOLSS_ARCHITECTURE_NT_X86,
1490 DBG_ERR("Unknown driver architecture: %s\n",
1492 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1495 /* now check the error code */
1497 if ( W_ERROR_IS_OK(werr) ) {
1498 /* it's ok to remove the driver, we have other architctures left */
1500 talloc_free(driver);
1504 /* report that the driver is not in use by default */
1510 /**********************************************************************
1511 Check to see if a ogiven file is in use by *info
1512 *********************************************************************/
1514 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1521 /* mz: skip files that are in the list but already deleted */
1522 if (!file || !file[0]) {
1526 if (strequal(file, info->driver_path))
1529 if (strequal(file, info->data_file))
1532 if (strequal(file, info->config_file))
1535 if (strequal(file, info->help_file))
1538 /* see of there are any dependent files to examine */
1540 if (!info->dependent_files)
1543 while (info->dependent_files[i] && *info->dependent_files[i]) {
1544 if (strequal(file, info->dependent_files[i]))
1553 /**********************************************************************
1554 Utility function to remove the dependent file pointed to by the
1555 input parameter from the list
1556 *********************************************************************/
1558 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1561 /* bump everything down a slot */
1563 while (files && files[idx+1]) {
1564 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1573 /**********************************************************************
1574 Check if any of the files used by src are also used by drv
1575 *********************************************************************/
1577 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1578 struct spoolss_DriverInfo8 *src,
1579 const struct spoolss_DriverInfo8 *drv)
1581 bool in_use = False;
1587 /* check each file. Remove it from the src structure if it overlaps */
1589 if (drv_file_in_use(src->driver_path, drv)) {
1591 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1592 src->driver_path = talloc_strdup(mem_ctx, "");
1593 if (!src->driver_path) { return false; }
1596 if (drv_file_in_use(src->data_file, drv)) {
1598 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1599 src->data_file = talloc_strdup(mem_ctx, "");
1600 if (!src->data_file) { return false; }
1603 if (drv_file_in_use(src->config_file, drv)) {
1605 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1606 src->config_file = talloc_strdup(mem_ctx, "");
1607 if (!src->config_file) { return false; }
1610 if (drv_file_in_use(src->help_file, drv)) {
1612 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1613 src->help_file = talloc_strdup(mem_ctx, "");
1614 if (!src->help_file) { return false; }
1617 /* are there any dependentfiles to examine? */
1619 if (!src->dependent_files)
1622 while (src->dependent_files[i] && *src->dependent_files[i]) {
1623 if (drv_file_in_use(src->dependent_files[i], drv)) {
1625 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1626 trim_dependent_file(mem_ctx, src->dependent_files, i);
1634 /****************************************************************************
1635 Determine whether or not a particular driver files are currently being
1636 used by any other driver.
1638 Return value is True if any files were in use by other drivers
1639 and False otherwise.
1641 Upon return, *info has been modified to only contain the driver files
1642 which are not in use
1646 This needs to check all drivers to ensure that all files in use
1647 have been removed from *info, not just the ones in the first
1649 ****************************************************************************/
1651 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1652 struct dcerpc_binding_handle *b,
1653 struct spoolss_DriverInfo8 *info)
1657 struct spoolss_DriverInfo8 *driver;
1658 bool in_use = false;
1659 uint32_t num_drivers;
1660 const char **drivers;
1666 version = info->version;
1668 /* loop over all driver versions */
1670 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1672 /* get the list of drivers */
1674 result = winreg_get_driver_list(mem_ctx, b,
1675 info->architecture, version,
1676 &num_drivers, &drivers);
1677 if (!W_ERROR_IS_OK(result)) {
1681 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1682 num_drivers, info->architecture, version));
1684 /* check each driver for overlap in files */
1686 for (i = 0; i < num_drivers; i++) {
1687 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1691 result = winreg_get_driver(mem_ctx, b,
1692 info->architecture, drivers[i],
1694 if (!W_ERROR_IS_OK(result)) {
1695 talloc_free(drivers);
1699 /* check if d2 uses any files from d1 */
1700 /* only if this is a different driver than the one being deleted */
1702 if (!strequal(info->driver_name, driver->driver_name)) {
1703 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1704 /* mz: Do not instantly return -
1705 * we need to ensure this file isn't
1706 * also in use by other drivers. */
1711 talloc_free(driver);
1714 talloc_free(drivers);
1716 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1721 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1722 const char *short_arch,
1726 TALLOC_CTX *tmp_ctx = talloc_new(conn);
1727 struct smb_filename *smb_fname = NULL;
1728 char *print_dlr_path;
1729 NTSTATUS status = NT_STATUS_NO_MEMORY;
1731 print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
1732 short_arch, vers, fname);
1733 if (print_dlr_path == NULL) {
1737 smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
1738 if (smb_fname == NULL) {
1742 status = unlink_internals(conn, NULL, 0, smb_fname, false);
1744 talloc_free(tmp_ctx);
1748 /****************************************************************************
1749 Actually delete the driver files. Make sure that
1750 printer_driver_files_in_use() return False before calling
1752 ****************************************************************************/
1754 bool delete_driver_files(const struct auth_session_info *session_info,
1755 const struct spoolss_DriverInfo8 *r)
1757 const char *short_arch;
1758 connection_struct *conn;
1760 struct smb_filename *oldcwd_fname = NULL;
1761 char *printdollar = NULL;
1762 int printdollar_snum;
1769 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1770 r->driver_name, r->version));
1772 printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1776 if (printdollar_snum == -1) {
1780 nt_status = create_conn_struct_cwd(talloc_tos(),
1781 server_event_context(),
1782 server_messaging_context(),
1785 lp_path(talloc_tos(), printdollar_snum),
1786 session_info, &oldcwd_fname);
1787 if (!NT_STATUS_IS_OK(nt_status)) {
1788 DEBUG(0,("delete_driver_files: create_conn_struct "
1789 "returned %s\n", nt_errstr(nt_status)));
1793 nt_status = set_conn_force_user_group(conn, printdollar_snum);
1794 if (!NT_STATUS_IS_OK(nt_status)) {
1795 DEBUG(0, ("failed set force user / group\n"));
1800 if (!become_user_by_session(conn, session_info)) {
1801 DEBUG(0, ("failed to become user\n"));
1806 if ( !CAN_WRITE(conn) ) {
1807 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1812 short_arch = get_short_archi(r->architecture);
1813 if (short_arch == NULL) {
1814 DEBUG(0, ("bad architecture %s\n", r->architecture));
1819 /* now delete the files */
1821 if (r->driver_path && r->driver_path[0]) {
1822 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
1823 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
1826 if (r->config_file && r->config_file[0]) {
1827 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
1828 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
1831 if (r->data_file && r->data_file[0]) {
1832 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
1833 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
1836 if (r->help_file && r->help_file[0]) {
1837 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
1838 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
1841 if (r->dependent_files) {
1843 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1844 DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
1845 driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
1855 vfs_ChDir(conn, oldcwd_fname);
1856 TALLOC_FREE(oldcwd_fname);
1857 SMB_VFS_DISCONNECT(conn);
1865 1: level not implemented
1866 2: file doesn't exist
1867 3: can't allocate memory
1868 4: can't free memory
1869 5: non existent struct
1873 A printer and a printer driver are 2 different things.
1874 NT manages them separatelly, Samba does the same.
1875 Why ? Simply because it's easier and it makes sense !
1877 Now explanation: You have 3 printers behind your samba server,
1878 2 of them are the same make and model (laser A and B). But laser B
1879 has an 3000 sheet feeder and laser A doesn't such an option.
1880 Your third printer is an old dot-matrix model for the accounting :-).
1882 If the /usr/local/samba/lib directory (default dir), you will have
1883 5 files to describe all of this.
1885 3 files for the printers (1 by printer):
1888 NTprinter_accounting
1889 2 files for the drivers (1 for the laser and 1 for the dot matrix)
1890 NTdriver_printer model X
1891 NTdriver_printer model Y
1893 jfm: I should use this comment for the text file to explain
1894 same thing for the forms BTW.
1895 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1899 /* Convert generic access rights to printer object specific access rights.
1900 It turns out that NT4 security descriptors use generic access rights and
1901 NT5 the object specific ones. */
1903 void map_printer_permissions(struct security_descriptor *sd)
1907 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1908 se_map_generic(&sd->dacl->aces[i].access_mask,
1909 &printer_generic_mapping);
1913 void map_job_permissions(struct security_descriptor *sd)
1917 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1918 se_map_generic(&sd->dacl->aces[i].access_mask,
1919 &job_generic_mapping);
1924 /****************************************************************************
1925 Check a user has permissions to perform the given operation. We use the
1926 permission constants defined in include/rpc_spoolss.h to check the various
1927 actions we perform when checking printer access.
1929 PRINTER_ACCESS_ADMINISTER:
1930 print_queue_pause, print_queue_resume, update_printer_sec,
1931 update_printer, spoolss_addprinterex_level_2,
1932 _spoolss_setprinterdata
1937 JOB_ACCESS_ADMINISTER:
1938 print_job_delete, print_job_pause, print_job_resume,
1941 Try access control in the following order (for performance reasons):
1942 1) root and SE_PRINT_OPERATOR can do anything (easy check)
1943 2) check security descriptor (bit comparisons in memory)
1944 3) "printer admins" (may result in numerous calls to winbind)
1946 ****************************************************************************/
1947 WERROR print_access_check(const struct auth_session_info *session_info,
1948 struct messaging_context *msg_ctx, int snum,
1951 struct spoolss_security_descriptor *secdesc = NULL;
1952 uint32_t access_granted;
1957 TALLOC_CTX *mem_ctx = NULL;
1959 /* If user is NULL then use the current_user structure */
1961 /* Always allow root or SE_PRINT_OPERATROR to do anything */
1963 if ((session_info->unix_token->uid == sec_initial_uid())
1964 || security_token_has_privilege(session_info->security_token,
1965 SEC_PRIV_PRINT_OPERATOR)) {
1969 /* Get printer name */
1971 pname = lp_printername(talloc_tos(), snum);
1973 if (!pname || !*pname) {
1974 return WERR_ACCESS_DENIED;
1977 /* Get printer security descriptor */
1979 if(!(mem_ctx = talloc_init("print_access_check"))) {
1980 return WERR_NOT_ENOUGH_MEMORY;
1983 result = winreg_get_printer_secdesc_internal(mem_ctx,
1984 get_session_info_system(),
1988 if (!W_ERROR_IS_OK(result)) {
1989 talloc_destroy(mem_ctx);
1990 return WERR_NOT_ENOUGH_MEMORY;
1993 if (access_type == JOB_ACCESS_ADMINISTER) {
1994 struct spoolss_security_descriptor *parent_secdesc = secdesc;
1996 /* Create a child security descriptor to check permissions
1997 against. This is because print jobs are child objects
1998 objects of a printer. */
1999 status = se_create_child_secdesc(mem_ctx,
2003 parent_secdesc->owner_sid,
2004 parent_secdesc->group_sid,
2006 if (!NT_STATUS_IS_OK(status)) {
2007 talloc_destroy(mem_ctx);
2008 return ntstatus_to_werror(status);
2011 map_job_permissions(secdesc);
2013 map_printer_permissions(secdesc);
2017 status = se_access_check(secdesc, session_info->security_token, access_type,
2020 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2022 talloc_destroy(mem_ctx);
2024 return ntstatus_to_werror(status);
2027 /****************************************************************************
2028 Check the time parameters allow a print operation.
2029 *****************************************************************************/
2031 bool print_time_access_check(const struct auth_session_info *session_info,
2032 struct messaging_context *msg_ctx,
2033 const char *servicename)
2035 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2038 time_t now = time(NULL);
2042 result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2043 servicename, &pinfo2);
2044 if (!W_ERROR_IS_OK(result)) {
2048 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2053 mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2055 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2059 TALLOC_FREE(pinfo2);
2068 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2069 const struct auth_session_info *session_info,
2070 struct messaging_context *msg_ctx,
2071 const char *printer)
2075 result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2077 if (!W_ERROR_IS_OK(result)) {
2078 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2079 "%s\n", printer, win_errstr(result)));
2083 void nt_printer_add(TALLOC_CTX *mem_ctx,
2084 const struct auth_session_info *session_info,
2085 struct messaging_context *msg_ctx,
2086 const char *printer)
2090 result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2092 if (!W_ERROR_IS_OK(result)) {
2093 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2094 printer, win_errstr(result)));