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 somthing
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
,
673 struct smb_filename
*smb_fname
= NULL
;
674 char *driverpath
= NULL
;
675 files_struct
*fsp
= NULL
;
676 connection_struct
*conn
= NULL
;
678 char *printdollar
= NULL
;
679 int printdollar_snum
;
681 *perr
= WERR_INVALID_PARAMETER
;
683 /* If architecture is Windows 95/98/ME, the version is always 0. */
684 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
685 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
690 /* If architecture is Windows x64, the version is always 3. */
691 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
692 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
697 printdollar_snum
= find_service(talloc_tos(), "print$", &printdollar
);
699 *perr
= WERR_NOT_ENOUGH_MEMORY
;
702 if (printdollar_snum
== -1) {
703 *perr
= WERR_BAD_NET_NAME
;
707 nt_status
= create_conn_struct_cwd(talloc_tos(),
708 server_event_context(),
709 server_messaging_context(),
712 lp_path(talloc_tos(), printdollar_snum
),
713 session_info
, &oldcwd
);
714 if (!NT_STATUS_IS_OK(nt_status
)) {
715 DEBUG(0,("get_correct_cversion: create_conn_struct "
716 "returned %s\n", nt_errstr(nt_status
)));
717 *perr
= ntstatus_to_werror(nt_status
);
721 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
722 if (!NT_STATUS_IS_OK(nt_status
)) {
723 DEBUG(0, ("failed set force user / group\n"));
724 *perr
= ntstatus_to_werror(nt_status
);
725 goto error_free_conn
;
728 if (!become_user_by_session(conn
, session_info
)) {
729 DEBUG(0, ("failed to become user\n"));
730 *perr
= WERR_ACCESS_DENIED
;
731 goto error_free_conn
;
734 /* Open the driver file (Portable Executable format) and determine the
735 * deriver the cversion. */
736 driverpath
= talloc_asprintf(talloc_tos(),
741 *perr
= WERR_NOT_ENOUGH_MEMORY
;
745 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
746 if (!NT_STATUS_IS_OK(nt_status
)) {
747 *perr
= ntstatus_to_werror(nt_status
);
751 nt_status
= vfs_file_exist(conn
, smb_fname
);
752 if (!NT_STATUS_IS_OK(nt_status
)) {
753 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
754 *perr
= WERR_FILE_NOT_FOUND
;
758 nt_status
= SMB_VFS_CREATE_FILE(
761 0, /* root_dir_fid */
762 smb_fname
, /* fname */
763 FILE_GENERIC_READ
, /* access_mask */
764 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
765 FILE_OPEN
, /* create_disposition*/
766 0, /* create_options */
767 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
768 INTERNAL_OPEN_ONLY
, /* oplock_request */
770 0, /* private_flags */
771 0, /* allocation_size */
776 NULL
, NULL
); /* create context */
778 if (!NT_STATUS_IS_OK(nt_status
)) {
779 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
780 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
781 *perr
= WERR_ACCESS_DENIED
;
788 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
790 *perr
= WERR_INVALID_PARAMETER
;
793 DEBUG(6,("get_correct_cversion: Version info not "
795 smb_fname_str_dbg(smb_fname
)));
796 *perr
= WERR_INVALID_PARAMETER
;
801 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
802 * for more details. Version in this case is not just the version of the
803 * file, but the version in the sense of kernal mode (2) vs. user mode
804 * (3) drivers. Other bits of the version fields are the version info.
807 cversion
= major
& 0x0000ffff;
809 case 2: /* WinNT drivers */
810 case 3: /* Win2K drivers */
814 DEBUG(6,("get_correct_cversion: cversion "
815 "invalid [%s] cversion = %d\n",
816 smb_fname_str_dbg(smb_fname
),
821 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
822 " = 0x%x minor = 0x%x\n",
823 smb_fname_str_dbg(smb_fname
), major
, minor
));
826 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
827 smb_fname_str_dbg(smb_fname
), cversion
));
833 TALLOC_FREE(smb_fname
);
835 close_file(NULL
, fsp
, NORMAL_CLOSE
);
838 vfs_ChDir(conn
, oldcwd
);
839 SMB_VFS_DISCONNECT(conn
);
842 if (!W_ERROR_IS_OK(*perr
)) {
849 /****************************************************************************
850 ****************************************************************************/
852 #define strip_driver_path(_mem_ctx, _element) do { \
853 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
854 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
855 W_ERROR_HAVE_NO_MEMORY((_element)); \
859 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
860 struct auth_session_info
*session_info
,
861 const char *architecture
,
862 const char **driver_path
,
863 const char **data_file
,
864 const char **config_file
,
865 const char **help_file
,
866 struct spoolss_StringArray
*dependent_files
,
867 enum spoolss_DriverOSVersion
*version
)
869 const char *short_architecture
;
874 if (!*driver_path
|| !*data_file
) {
875 return WERR_INVALID_PARAMETER
;
878 if (!strequal(architecture
, SPOOLSS_ARCHITECTURE_4_0
) && !*config_file
) {
879 return WERR_INVALID_PARAMETER
;
882 /* clean up the driver name.
883 * we can get .\driver.dll
884 * or worse c:\windows\system\driver.dll !
886 /* using an intermediate string to not have overlaping memcpy()'s */
888 strip_driver_path(mem_ctx
, *driver_path
);
889 strip_driver_path(mem_ctx
, *data_file
);
891 strip_driver_path(mem_ctx
, *config_file
);
894 strip_driver_path(mem_ctx
, *help_file
);
897 if (dependent_files
&& dependent_files
->string
) {
898 for (i
=0; dependent_files
->string
[i
]; i
++) {
899 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
903 short_architecture
= get_short_archi(architecture
);
904 if (!short_architecture
) {
905 return WERR_UNKNOWN_PRINTER_DRIVER
;
908 /* jfm:7/16/2000 the client always sends the cversion=0.
909 * The server should check which version the driver is by reading
910 * the PE header of driver->driverpath.
912 * For Windows 95/98 the version is 0 (so the value sent is correct)
913 * For Windows NT (the architecture doesn't matter)
915 * NT 3.5/3.51: cversion=1
920 *version
= get_correct_cversion(session_info
, short_architecture
,
922 if (*version
== -1) {
929 /****************************************************************************
930 ****************************************************************************/
932 WERROR
clean_up_driver_struct(TALLOC_CTX
*mem_ctx
,
933 struct auth_session_info
*session_info
,
934 struct spoolss_AddDriverInfoCtr
*r
)
938 return clean_up_driver_struct_level(mem_ctx
, session_info
,
939 r
->info
.info3
->architecture
,
940 &r
->info
.info3
->driver_path
,
941 &r
->info
.info3
->data_file
,
942 &r
->info
.info3
->config_file
,
943 &r
->info
.info3
->help_file
,
944 r
->info
.info3
->dependent_files
,
945 &r
->info
.info3
->version
);
947 return clean_up_driver_struct_level(mem_ctx
, session_info
,
948 r
->info
.info6
->architecture
,
949 &r
->info
.info6
->driver_path
,
950 &r
->info
.info6
->data_file
,
951 &r
->info
.info6
->config_file
,
952 &r
->info
.info6
->help_file
,
953 r
->info
.info6
->dependent_files
,
954 &r
->info
.info6
->version
);
956 return clean_up_driver_struct_level(mem_ctx
, session_info
,
957 r
->info
.info8
->architecture
,
958 &r
->info
.info8
->driver_path
,
959 &r
->info
.info8
->data_file
,
960 &r
->info
.info8
->config_file
,
961 &r
->info
.info8
->help_file
,
962 r
->info
.info8
->dependent_files
,
963 &r
->info
.info8
->version
);
965 return WERR_NOT_SUPPORTED
;
969 /****************************************************************************
970 This function sucks and should be replaced. JRA.
971 ****************************************************************************/
973 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
974 const struct spoolss_AddDriverInfo6
*src
)
976 dst
->version
= src
->version
;
978 dst
->driver_name
= src
->driver_name
;
979 dst
->architecture
= src
->architecture
;
980 dst
->driver_path
= src
->driver_path
;
981 dst
->data_file
= src
->data_file
;
982 dst
->config_file
= src
->config_file
;
983 dst
->help_file
= src
->help_file
;
984 dst
->monitor_name
= src
->monitor_name
;
985 dst
->default_datatype
= src
->default_datatype
;
986 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
987 dst
->dependent_files
= src
->dependent_files
;
990 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3
*dst
,
991 const struct spoolss_AddDriverInfo8
*src
)
993 dst
->version
= src
->version
;
995 dst
->driver_name
= src
->driver_name
;
996 dst
->architecture
= src
->architecture
;
997 dst
->driver_path
= src
->driver_path
;
998 dst
->data_file
= src
->data_file
;
999 dst
->config_file
= src
->config_file
;
1000 dst
->help_file
= src
->help_file
;
1001 dst
->monitor_name
= src
->monitor_name
;
1002 dst
->default_datatype
= src
->default_datatype
;
1003 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1004 dst
->dependent_files
= src
->dependent_files
;
1007 /****************************************************************************
1008 ****************************************************************************/
1010 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
1011 connection_struct
*conn
,
1012 const char *driver_file
,
1013 const char *short_architecture
,
1014 uint32_t driver_version
,
1017 struct smb_filename
*smb_fname_old
= NULL
;
1018 struct smb_filename
*smb_fname_new
= NULL
;
1019 char *old_name
= NULL
;
1020 char *new_name
= NULL
;
1024 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
1025 short_architecture
, driver_file
);
1026 W_ERROR_HAVE_NO_MEMORY(old_name
);
1028 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
1029 short_architecture
, driver_version
, driver_file
);
1030 if (new_name
== NULL
) {
1031 TALLOC_FREE(old_name
);
1032 return WERR_NOT_ENOUGH_MEMORY
;
1035 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
1037 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
1038 if (!NT_STATUS_IS_OK(status
)) {
1039 ret
= WERR_NOT_ENOUGH_MEMORY
;
1043 /* Setup a synthetic smb_filename struct */
1044 smb_fname_new
= talloc_zero(mem_ctx
, struct smb_filename
);
1045 if (!smb_fname_new
) {
1046 ret
= WERR_NOT_ENOUGH_MEMORY
;
1050 smb_fname_new
->base_name
= new_name
;
1052 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1053 "'%s'\n", smb_fname_old
->base_name
,
1054 smb_fname_new
->base_name
));
1056 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
1057 OPENX_FILE_EXISTS_TRUNCATE
|
1058 OPENX_FILE_CREATE_IF_NOT_EXIST
,
1061 if (!NT_STATUS_IS_OK(status
)) {
1062 DEBUG(0,("move_driver_file_to_download_area: Unable "
1063 "to rename [%s] to [%s]: %s\n",
1064 smb_fname_old
->base_name
, new_name
,
1065 nt_errstr(status
)));
1066 ret
= WERR_ACCESS_DENIED
;
1073 TALLOC_FREE(smb_fname_old
);
1074 TALLOC_FREE(smb_fname_new
);
1078 WERROR
move_driver_to_download_area(struct auth_session_info
*session_info
,
1079 struct spoolss_AddDriverInfoCtr
*r
)
1081 struct spoolss_AddDriverInfo3
*driver
;
1082 struct spoolss_AddDriverInfo3 converted_driver
;
1083 const char *short_architecture
;
1084 struct smb_filename
*smb_dname
= NULL
;
1085 char *new_dir
= NULL
;
1086 connection_struct
*conn
= NULL
;
1089 TALLOC_CTX
*ctx
= talloc_tos();
1092 char *printdollar
= NULL
;
1093 int printdollar_snum
;
1094 WERROR err
= WERR_OK
;
1098 driver
= r
->info
.info3
;
1101 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
1102 driver
= &converted_driver
;
1105 convert_level_8_to_level3(&converted_driver
, r
->info
.info8
);
1106 driver
= &converted_driver
;
1109 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
1110 return WERR_INVALID_LEVEL
;
1113 short_architecture
= get_short_archi(driver
->architecture
);
1114 if (!short_architecture
) {
1115 return WERR_UNKNOWN_PRINTER_DRIVER
;
1118 printdollar_snum
= find_service(ctx
, "print$", &printdollar
);
1120 return WERR_NOT_ENOUGH_MEMORY
;
1122 if (printdollar_snum
== -1) {
1123 return WERR_BAD_NET_NAME
;
1126 nt_status
= create_conn_struct_cwd(talloc_tos(),
1127 server_event_context(),
1128 server_messaging_context(),
1131 lp_path(talloc_tos(), printdollar_snum
),
1132 session_info
, &oldcwd
);
1133 if (!NT_STATUS_IS_OK(nt_status
)) {
1134 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1135 "returned %s\n", nt_errstr(nt_status
)));
1136 err
= ntstatus_to_werror(nt_status
);
1140 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1141 if (!NT_STATUS_IS_OK(nt_status
)) {
1142 DEBUG(0, ("failed set force user / group\n"));
1143 err
= ntstatus_to_werror(nt_status
);
1147 if (!become_user_by_session(conn
, session_info
)) {
1148 DEBUG(0, ("failed to become user\n"));
1149 err
= WERR_ACCESS_DENIED
;
1153 new_dir
= talloc_asprintf(ctx
,
1158 err
= WERR_NOT_ENOUGH_MEMORY
;
1161 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1162 if (!NT_STATUS_IS_OK(nt_status
)) {
1163 err
= WERR_NOT_ENOUGH_MEMORY
;
1167 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1169 nt_status
= create_directory(conn
, NULL
, smb_dname
);
1170 if (!NT_STATUS_IS_OK(nt_status
)
1171 && !NT_STATUS_EQUAL(nt_status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
1172 DEBUG(0, ("failed to create driver destination directory: %s\n",
1173 nt_errstr(nt_status
)));
1174 err
= ntstatus_to_werror(nt_status
);
1178 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1179 * listed for this driver which has already been moved, skip it (note:
1180 * drivers may list the same file name several times. Then check if the
1181 * file already exists in archi\version\, if so, check that the version
1182 * info (or time stamps if version info is unavailable) is newer (or the
1183 * date is later). If it is, move it to archi\version\filexxx.yyy.
1184 * Otherwise, delete the file.
1186 * If a file is not moved to archi\version\ because of an error, all the
1187 * rest of the 'unmoved' driver files are removed from archi\. If one or
1188 * more of the driver's files was already moved to archi\version\, it
1189 * potentially leaves the driver in a partially updated state. Version
1190 * trauma will most likely occur if an client attempts to use any printer
1191 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1192 * done is appropriate... later JRR
1195 DEBUG(5,("Moving files now !\n"));
1197 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1199 err
= move_driver_file_to_download_area(ctx
,
1201 driver
->driver_path
,
1205 if (!W_ERROR_IS_OK(err
)) {
1210 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1211 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1213 err
= move_driver_file_to_download_area(ctx
,
1219 if (!W_ERROR_IS_OK(err
)) {
1225 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1226 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1227 !strequal(driver
->config_file
, driver
->data_file
)) {
1229 err
= move_driver_file_to_download_area(ctx
,
1231 driver
->config_file
,
1235 if (!W_ERROR_IS_OK(err
)) {
1241 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1242 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1243 !strequal(driver
->help_file
, driver
->data_file
) &&
1244 !strequal(driver
->help_file
, driver
->config_file
)) {
1246 err
= move_driver_file_to_download_area(ctx
,
1252 if (!W_ERROR_IS_OK(err
)) {
1258 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1259 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1260 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1261 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1262 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1263 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1265 for (j
=0; j
< i
; j
++) {
1266 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
1271 err
= move_driver_file_to_download_area(ctx
,
1273 driver
->dependent_files
->string
[i
],
1277 if (!W_ERROR_IS_OK(err
)) {
1289 TALLOC_FREE(smb_dname
);
1292 vfs_ChDir(conn
, oldcwd
);
1293 SMB_VFS_DISCONNECT(conn
);
1300 /****************************************************************************
1301 Determine whether or not a particular driver is currently assigned
1303 ****************************************************************************/
1305 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
1306 struct dcerpc_binding_handle
*b
,
1307 const struct spoolss_DriverInfo8
*r
)
1310 int n_services
= lp_numservices();
1311 bool in_use
= False
;
1312 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1319 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1321 /* loop through the printers.tdb and check for the drivername */
1323 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
1324 if (!lp_snum_ok(snum
) || !lp_printable(snum
)) {
1328 result
= winreg_get_printer(mem_ctx
, b
,
1329 lp_servicename(talloc_tos(), snum
),
1331 if (!W_ERROR_IS_OK(result
)) {
1332 continue; /* skip */
1335 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
1339 TALLOC_FREE(pinfo2
);
1342 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1345 struct spoolss_DriverInfo8
*driver
= NULL
;
1348 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
1350 /* we can still remove the driver if there is one of
1351 "Windows NT x86" version 2 or 3 left */
1353 if (!strequal("Windows NT x86", r
->architecture
)) {
1354 werr
= winreg_get_driver(mem_ctx
, b
,
1359 } else if (r
->version
== 2) {
1360 werr
= winreg_get_driver(mem_ctx
, b
,
1364 } else if (r
->version
== 3) {
1365 werr
= winreg_get_driver(mem_ctx
, b
,
1370 DEBUG(0, ("printer_driver_in_use: ERROR!"
1371 " unknown driver version (%d)\n",
1373 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
1376 /* now check the error code */
1378 if ( W_ERROR_IS_OK(werr
) ) {
1379 /* it's ok to remove the driver, we have other architctures left */
1381 talloc_free(driver
);
1385 /* report that the driver is not in use by default */
1391 /**********************************************************************
1392 Check to see if a ogiven file is in use by *info
1393 *********************************************************************/
1395 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
1402 /* mz: skip files that are in the list but already deleted */
1403 if (!file
|| !file
[0]) {
1407 if (strequal(file
, info
->driver_path
))
1410 if (strequal(file
, info
->data_file
))
1413 if (strequal(file
, info
->config_file
))
1416 if (strequal(file
, info
->help_file
))
1419 /* see of there are any dependent files to examine */
1421 if (!info
->dependent_files
)
1424 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
1425 if (strequal(file
, info
->dependent_files
[i
]))
1434 /**********************************************************************
1435 Utility function to remove the dependent file pointed to by the
1436 input parameter from the list
1437 *********************************************************************/
1439 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
1442 /* bump everything down a slot */
1444 while (files
&& files
[idx
+1]) {
1445 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
1454 /**********************************************************************
1455 Check if any of the files used by src are also used by drv
1456 *********************************************************************/
1458 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
1459 struct spoolss_DriverInfo8
*src
,
1460 const struct spoolss_DriverInfo8
*drv
)
1462 bool in_use
= False
;
1468 /* check each file. Remove it from the src structure if it overlaps */
1470 if (drv_file_in_use(src
->driver_path
, drv
)) {
1472 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
1473 src
->driver_path
= talloc_strdup(mem_ctx
, "");
1474 if (!src
->driver_path
) { return false; }
1477 if (drv_file_in_use(src
->data_file
, drv
)) {
1479 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
1480 src
->data_file
= talloc_strdup(mem_ctx
, "");
1481 if (!src
->data_file
) { return false; }
1484 if (drv_file_in_use(src
->config_file
, drv
)) {
1486 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
1487 src
->config_file
= talloc_strdup(mem_ctx
, "");
1488 if (!src
->config_file
) { return false; }
1491 if (drv_file_in_use(src
->help_file
, drv
)) {
1493 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
1494 src
->help_file
= talloc_strdup(mem_ctx
, "");
1495 if (!src
->help_file
) { return false; }
1498 /* are there any dependentfiles to examine? */
1500 if (!src
->dependent_files
)
1503 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
1504 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
1506 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
1507 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
1515 /****************************************************************************
1516 Determine whether or not a particular driver files are currently being
1517 used by any other driver.
1519 Return value is True if any files were in use by other drivers
1520 and False otherwise.
1522 Upon return, *info has been modified to only contain the driver files
1523 which are not in use
1527 This needs to check all drivers to ensure that all files in use
1528 have been removed from *info, not just the ones in the first
1530 ****************************************************************************/
1532 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
1533 struct dcerpc_binding_handle
*b
,
1534 struct spoolss_DriverInfo8
*info
)
1538 struct spoolss_DriverInfo8
*driver
;
1539 bool in_use
= false;
1540 uint32_t num_drivers
;
1541 const char **drivers
;
1547 version
= info
->version
;
1549 /* loop over all driver versions */
1551 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1553 /* get the list of drivers */
1555 result
= winreg_get_driver_list(mem_ctx
, b
,
1556 info
->architecture
, version
,
1557 &num_drivers
, &drivers
);
1558 if (!W_ERROR_IS_OK(result
)) {
1562 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1563 num_drivers
, info
->architecture
, version
));
1565 /* check each driver for overlap in files */
1567 for (i
= 0; i
< num_drivers
; i
++) {
1568 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
1572 result
= winreg_get_driver(mem_ctx
, b
,
1573 info
->architecture
, drivers
[i
],
1575 if (!W_ERROR_IS_OK(result
)) {
1576 talloc_free(drivers
);
1580 /* check if d2 uses any files from d1 */
1581 /* only if this is a different driver than the one being deleted */
1583 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
1584 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
1585 /* mz: Do not instantly return -
1586 * we need to ensure this file isn't
1587 * also in use by other drivers. */
1592 talloc_free(driver
);
1595 talloc_free(drivers
);
1597 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1602 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
1603 const char *short_arch
,
1607 TALLOC_CTX
*tmp_ctx
= talloc_new(conn
);
1608 struct smb_filename
*smb_fname
= NULL
;
1609 char *print_dlr_path
;
1610 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1612 print_dlr_path
= talloc_asprintf(tmp_ctx
, "%s/%d/%s",
1613 short_arch
, vers
, fname
);
1614 if (print_dlr_path
== NULL
) {
1618 smb_fname
= synthetic_smb_fname(tmp_ctx
, print_dlr_path
, NULL
, NULL
, 0);
1619 if (smb_fname
== NULL
) {
1623 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
1625 talloc_free(tmp_ctx
);
1629 /****************************************************************************
1630 Actually delete the driver files. Make sure that
1631 printer_driver_files_in_use() return False before calling
1633 ****************************************************************************/
1635 bool delete_driver_files(const struct auth_session_info
*session_info
,
1636 const struct spoolss_DriverInfo8
*r
)
1638 const char *short_arch
;
1639 connection_struct
*conn
;
1642 char *printdollar
= NULL
;
1643 int printdollar_snum
;
1650 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1651 r
->driver_name
, r
->version
));
1653 printdollar_snum
= find_service(talloc_tos(), "print$", &printdollar
);
1657 if (printdollar_snum
== -1) {
1661 nt_status
= create_conn_struct_cwd(talloc_tos(),
1662 server_event_context(),
1663 server_messaging_context(),
1666 lp_path(talloc_tos(), printdollar_snum
),
1667 session_info
, &oldcwd
);
1668 if (!NT_STATUS_IS_OK(nt_status
)) {
1669 DEBUG(0,("delete_driver_files: create_conn_struct "
1670 "returned %s\n", nt_errstr(nt_status
)));
1674 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1675 if (!NT_STATUS_IS_OK(nt_status
)) {
1676 DEBUG(0, ("failed set force user / group\n"));
1681 if (!become_user_by_session(conn
, session_info
)) {
1682 DEBUG(0, ("failed to become user\n"));
1687 if ( !CAN_WRITE(conn
) ) {
1688 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1693 short_arch
= get_short_archi(r
->architecture
);
1694 if (short_arch
== NULL
) {
1695 DEBUG(0, ("bad architecture %s\n", r
->architecture
));
1700 /* now delete the files */
1702 if (r
->driver_path
&& r
->driver_path
[0]) {
1703 DEBUG(10,("deleting driverfile [%s]\n", r
->driver_path
));
1704 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->driver_path
);
1707 if (r
->config_file
&& r
->config_file
[0]) {
1708 DEBUG(10,("deleting configfile [%s]\n", r
->config_file
));
1709 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->config_file
);
1712 if (r
->data_file
&& r
->data_file
[0]) {
1713 DEBUG(10,("deleting datafile [%s]\n", r
->data_file
));
1714 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->data_file
);
1717 if (r
->help_file
&& r
->help_file
[0]) {
1718 DEBUG(10,("deleting helpfile [%s]\n", r
->help_file
));
1719 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->help_file
);
1722 if (r
->dependent_files
) {
1724 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
1725 DEBUG(10,("deleting dependent file [%s]\n", r
->dependent_files
[i
]));
1726 driver_unlink_internals(conn
, short_arch
, r
->version
, r
->dependent_files
[i
]);
1736 vfs_ChDir(conn
, oldcwd
);
1737 SMB_VFS_DISCONNECT(conn
);
1745 1: level not implemented
1746 2: file doesn't exist
1747 3: can't allocate memory
1748 4: can't free memory
1749 5: non existent struct
1753 A printer and a printer driver are 2 different things.
1754 NT manages them separatelly, Samba does the same.
1755 Why ? Simply because it's easier and it makes sense !
1757 Now explanation: You have 3 printers behind your samba server,
1758 2 of them are the same make and model (laser A and B). But laser B
1759 has an 3000 sheet feeder and laser A doesn't such an option.
1760 Your third printer is an old dot-matrix model for the accounting :-).
1762 If the /usr/local/samba/lib directory (default dir), you will have
1763 5 files to describe all of this.
1765 3 files for the printers (1 by printer):
1768 NTprinter_accounting
1769 2 files for the drivers (1 for the laser and 1 for the dot matrix)
1770 NTdriver_printer model X
1771 NTdriver_printer model Y
1773 jfm: I should use this comment for the text file to explain
1774 same thing for the forms BTW.
1775 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1779 /* Convert generic access rights to printer object specific access rights.
1780 It turns out that NT4 security descriptors use generic access rights and
1781 NT5 the object specific ones. */
1783 void map_printer_permissions(struct security_descriptor
*sd
)
1787 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
1788 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
1789 &printer_generic_mapping
);
1793 void map_job_permissions(struct security_descriptor
*sd
)
1797 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
1798 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
1799 &job_generic_mapping
);
1804 /****************************************************************************
1805 Check a user has permissions to perform the given operation. We use the
1806 permission constants defined in include/rpc_spoolss.h to check the various
1807 actions we perform when checking printer access.
1809 PRINTER_ACCESS_ADMINISTER:
1810 print_queue_pause, print_queue_resume, update_printer_sec,
1811 update_printer, spoolss_addprinterex_level_2,
1812 _spoolss_setprinterdata
1817 JOB_ACCESS_ADMINISTER:
1818 print_job_delete, print_job_pause, print_job_resume,
1821 Try access control in the following order (for performance reasons):
1822 1) root and SE_PRINT_OPERATOR can do anything (easy check)
1823 2) check security descriptor (bit comparisons in memory)
1824 3) "printer admins" (may result in numerous calls to winbind)
1826 ****************************************************************************/
1827 WERROR
print_access_check(const struct auth_session_info
*session_info
,
1828 struct messaging_context
*msg_ctx
, int snum
,
1831 struct spoolss_security_descriptor
*secdesc
= NULL
;
1832 uint32_t access_granted
;
1837 TALLOC_CTX
*mem_ctx
= NULL
;
1839 /* If user is NULL then use the current_user structure */
1841 /* Always allow root or SE_PRINT_OPERATROR to do anything */
1843 if ((session_info
->unix_token
->uid
== sec_initial_uid())
1844 || security_token_has_privilege(session_info
->security_token
,
1845 SEC_PRIV_PRINT_OPERATOR
)) {
1849 /* Get printer name */
1851 pname
= lp_printername(talloc_tos(), snum
);
1853 if (!pname
|| !*pname
) {
1854 return WERR_ACCESS_DENIED
;
1857 /* Get printer security descriptor */
1859 if(!(mem_ctx
= talloc_init("print_access_check"))) {
1860 return WERR_NOT_ENOUGH_MEMORY
;
1863 result
= winreg_get_printer_secdesc_internal(mem_ctx
,
1864 get_session_info_system(),
1868 if (!W_ERROR_IS_OK(result
)) {
1869 talloc_destroy(mem_ctx
);
1870 return WERR_NOT_ENOUGH_MEMORY
;
1873 if (access_type
== JOB_ACCESS_ADMINISTER
) {
1874 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
1876 /* Create a child security descriptor to check permissions
1877 against. This is because print jobs are child objects
1878 objects of a printer. */
1879 status
= se_create_child_secdesc(mem_ctx
,
1883 parent_secdesc
->owner_sid
,
1884 parent_secdesc
->group_sid
,
1886 if (!NT_STATUS_IS_OK(status
)) {
1887 talloc_destroy(mem_ctx
);
1888 return ntstatus_to_werror(status
);
1891 map_job_permissions(secdesc
);
1893 map_printer_permissions(secdesc
);
1897 status
= se_access_check(secdesc
, session_info
->security_token
, access_type
,
1900 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
1902 talloc_destroy(mem_ctx
);
1904 return ntstatus_to_werror(status
);
1907 /****************************************************************************
1908 Check the time parameters allow a print operation.
1909 *****************************************************************************/
1911 bool print_time_access_check(const struct auth_session_info
*session_info
,
1912 struct messaging_context
*msg_ctx
,
1913 const char *servicename
)
1915 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1918 time_t now
= time(NULL
);
1922 result
= winreg_get_printer_internal(NULL
, session_info
, msg_ctx
,
1923 servicename
, &pinfo2
);
1924 if (!W_ERROR_IS_OK(result
)) {
1928 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
1933 mins
= (uint32_t)t
->tm_hour
*60 + (uint32_t)t
->tm_min
;
1935 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
1939 TALLOC_FREE(pinfo2
);
1948 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
1949 const struct auth_session_info
*session_info
,
1950 struct messaging_context
*msg_ctx
,
1951 const char *printer
)
1955 result
= winreg_delete_printer_key_internal(mem_ctx
, session_info
, msg_ctx
,
1957 if (!W_ERROR_IS_OK(result
)) {
1958 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
1959 "%s\n", printer
, win_errstr(result
)));
1963 void nt_printer_add(TALLOC_CTX
*mem_ctx
,
1964 const struct auth_session_info
*session_info
,
1965 struct messaging_context
*msg_ctx
,
1966 const char *printer
)
1970 result
= winreg_create_printer_internal(mem_ctx
, session_info
, msg_ctx
,
1972 if (!W_ERROR_IS_OK(result
)) {
1973 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
1974 printer
, win_errstr(result
)));