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 "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
25 #include "printing/nt_printing_tdb.h"
26 #include "printing/nt_printing_migrate.h"
28 #include "registry/reg_objects.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "../librpc/gen_ndr/ndr_spoolss.h"
31 #include "rpc_server/srv_spoolss_util.h"
32 #include "nt_printing.h"
34 #include "../librpc/gen_ndr/netlogon.h"
36 /* Map generic permissions to printer object specific permissions */
38 const struct generic_mapping printer_generic_mapping
= {
45 /* Map generic permissions to print server object specific permissions */
47 const struct generic_mapping printserver_generic_mapping
= {
54 /* Map generic permissions to job object specific permissions */
56 const struct generic_mapping job_generic_mapping
= {
63 static const struct print_architecture_table_node archi_table
[]= {
65 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
66 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
67 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
68 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
69 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
70 {"Windows IA64", SPL_ARCH_IA64
, 3 },
71 {"Windows x64", SPL_ARCH_X64
, 3 },
75 /****************************************************************************
76 Open the NT printing tdbs. Done once before fork().
77 ****************************************************************************/
79 bool nt_printing_init(struct messaging_context
*msg_ctx
)
83 if (!nt_printing_tdb_upgrade()) {
88 * register callback to handle updating printers as new
89 * drivers are installed
91 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
92 do_drv_upgrade_printer
);
94 /* of course, none of the message callbacks matter if you don't
95 tell messages.c that you interested in receiving PRINT_GENERAL
96 msgs. This is done in serverid_register() */
98 if ( lp_security() == SEC_ADS
) {
99 win_rc
= check_published_printers(msg_ctx
);
100 if (!W_ERROR_IS_OK(win_rc
))
101 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
107 /*******************************************************************
108 Function to allow filename parsing "the old way".
109 ********************************************************************/
111 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
112 const char *old_name
,
113 struct smb_filename
**smb_fname
)
116 TALLOC_CTX
*ctx
= talloc_tos();
117 char *name
= talloc_strdup(ctx
, old_name
);
120 return NT_STATUS_NO_MEMORY
;
123 name
= unix_clean_name(ctx
, name
);
125 return NT_STATUS_NO_MEMORY
;
127 trim_string(name
,"/","/");
129 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
130 if (!NT_STATUS_IS_OK(status
)) {
131 return NT_STATUS_NO_MEMORY
;
137 /****************************************************************************
138 Function to do the mapping between the long architecture name and
140 ****************************************************************************/
142 const char *get_short_archi(const char *long_archi
)
146 DEBUG(107,("Getting architecture dependant directory\n"));
149 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
150 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
152 if (archi_table
[i
].long_archi
==NULL
) {
153 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
157 /* this might be client code - but shouldn't this be an fstrcpy etc? */
159 DEBUGADD(108,("index: [%d]\n", i
));
160 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
161 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
163 return archi_table
[i
].short_archi
;
166 /****************************************************************************
167 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
168 There are two case to be covered here: PE (Portable Executable) and NE (New
169 Executable) files. Both files support the same INFO structure, but PE files
170 store the signature in unicode, and NE files store it as !unicode.
171 returns -1 on error, 1 on version info found, and 0 on no version info found.
172 ****************************************************************************/
174 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
180 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
181 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
182 fname
, DOS_HEADER_SIZE
));
186 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
187 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
188 fname
, (unsigned long)byte_count
));
189 goto no_version_info
;
192 /* Is this really a DOS header? */
193 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
194 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
195 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
196 goto no_version_info
;
199 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
200 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
201 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
203 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
204 goto no_version_info
;
207 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
208 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
209 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
210 fname
, (unsigned long)byte_count
));
211 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
212 goto no_version_info
;
215 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
216 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
217 unsigned int num_sections
;
218 unsigned int section_table_bytes
;
220 /* Just skip over optional header to get to section table */
221 if (SMB_VFS_LSEEK(fsp
,
222 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
223 SEEK_CUR
) == (SMB_OFF_T
)-1) {
224 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
229 /* get the section table */
230 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
231 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
232 if (section_table_bytes
== 0)
236 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
237 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
238 fname
, section_table_bytes
));
242 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
243 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
244 fname
, (unsigned long)byte_count
));
248 /* Iterate the section table looking for the resource section ".rsrc" */
249 for (i
= 0; i
< num_sections
; i
++) {
250 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
252 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
253 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
254 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
256 if (section_bytes
== 0)
260 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
261 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
262 fname
, section_bytes
));
266 /* Seek to the start of the .rsrc section info */
267 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
268 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
273 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
274 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
275 fname
, (unsigned long)byte_count
));
279 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
282 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
283 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
284 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
285 /* Align to next long address */
286 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
288 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
289 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
290 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
292 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
293 fname
, *major
, *minor
,
294 (*major
>>16)&0xffff, *major
&0xffff,
295 (*minor
>>16)&0xffff, *minor
&0xffff));
304 /* Version info not found, fall back to origin date/time */
305 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
309 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
310 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
311 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
312 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
313 /* At this point, we assume the file is in error. It still could be somthing
314 * else besides a NE file, but it unlikely at this point. */
318 /* Allocate a bit more space to speed up things */
320 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
321 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
322 fname
, PE_HEADER_SIZE
));
326 /* This is a HACK! I got tired of trying to sort through the messy
327 * 'NE' file format. If anyone wants to clean this up please have at
328 * it, but this works. 'NE' files will eventually fade away. JRR */
329 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
330 /* Cover case that should not occur in a well formed 'NE' .dll file */
331 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
333 for(i
=0; i
<byte_count
; i
++) {
334 /* Fast skip past data that can't possibly match */
335 if (buf
[i
] != 'V') continue;
337 /* Potential match data crosses buf boundry, move it to beginning
338 * of buf, and fill the buf with as much as it will hold. */
339 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
342 memcpy(buf
, &buf
[i
], byte_count
-i
);
343 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
344 (byte_count
-i
))) < 0) {
346 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
351 byte_count
= bc
+ (byte_count
- i
);
352 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
357 /* Check that the full signature string and the magic number that
358 * follows exist (not a perfect solution, but the chances that this
359 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
360 * twice, as it is simpler to read the code. */
361 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
362 /* Compute skip alignment to next long address */
363 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
364 sizeof(VS_SIGNATURE
)) & 3;
365 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
367 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
368 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
369 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
370 fname
, *major
, *minor
,
371 (*major
>>16)&0xffff, *major
&0xffff,
372 (*minor
>>16)&0xffff, *minor
&0xffff));
379 /* Version info not found, fall back to origin date/time */
380 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
385 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
386 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
387 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
398 /****************************************************************************
399 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
400 share one or more files. During the MS installation process files are checked
401 to insure that only a newer version of a shared file is installed over an
402 older version. There are several possibilities for this comparison. If there
403 is no previous version, the new one is newer (obviously). If either file is
404 missing the version info structure, compare the creation date (on Unix use
405 the modification date). Otherwise chose the numerically larger version number.
406 ****************************************************************************/
408 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
410 bool use_version
= true;
414 time_t new_create_time
;
418 time_t old_create_time
;
420 struct smb_filename
*smb_fname
= NULL
;
421 files_struct
*fsp
= NULL
;
427 SET_STAT_INVALID(st
);
428 new_create_time
= (time_t)0;
429 old_create_time
= (time_t)0;
431 /* Get file version info (if available) for previous file (if it exists) */
432 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
433 if (!NT_STATUS_IS_OK(status
)) {
437 status
= SMB_VFS_CREATE_FILE(
440 0, /* root_dir_fid */
441 smb_fname
, /* fname */
442 FILE_GENERIC_READ
, /* access_mask */
443 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
444 FILE_OPEN
, /* create_disposition*/
445 0, /* create_options */
446 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
447 INTERNAL_OPEN_ONLY
, /* oplock_request */
448 0, /* allocation_size */
449 0, /* private_flags */
455 if (!NT_STATUS_IS_OK(status
)) {
456 /* Old file not found, so by definition new file is in fact newer */
457 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
458 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
464 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
470 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
473 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
476 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
477 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
478 (long)old_create_time
));
481 close_file(NULL
, fsp
, NORMAL_CLOSE
);
484 /* Get file version info (if available) for new file */
485 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
486 if (!NT_STATUS_IS_OK(status
)) {
490 status
= SMB_VFS_CREATE_FILE(
493 0, /* root_dir_fid */
494 smb_fname
, /* fname */
495 FILE_GENERIC_READ
, /* access_mask */
496 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
497 FILE_OPEN
, /* create_disposition*/
498 0, /* create_options */
499 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
500 INTERNAL_OPEN_ONLY
, /* oplock_request */
501 0, /* allocation_size */
502 0, /* private_flags */
508 if (!NT_STATUS_IS_OK(status
)) {
509 /* New file not found, this shouldn't occur if the caller did its job */
510 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
511 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
515 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
521 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
524 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
527 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
528 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
529 (long)new_create_time
));
532 close_file(NULL
, fsp
, NORMAL_CLOSE
);
535 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
536 /* Compare versions and choose the larger version number */
537 if (new_major
> old_major
||
538 (new_major
== old_major
&& new_minor
> old_minor
)) {
540 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
545 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
551 /* Compare modification time/dates and choose the newest time/date */
552 if (new_create_time
> old_create_time
) {
553 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
558 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
566 close_file(NULL
, fsp
, NORMAL_CLOSE
);
569 TALLOC_FREE(smb_fname
);
573 /****************************************************************************
574 Determine the correct cVersion associated with an architecture and driver
575 ****************************************************************************/
576 static uint32
get_correct_cversion(struct pipes_struct
*p
,
577 const char *architecture
,
578 const char *driverpath_in
,
583 struct smb_filename
*smb_fname
= NULL
;
584 char *driverpath
= NULL
;
585 files_struct
*fsp
= NULL
;
586 connection_struct
*conn
= NULL
;
590 int printdollar_snum
;
592 *perr
= WERR_INVALID_PARAM
;
594 /* If architecture is Windows 95/98/ME, the version is always 0. */
595 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
596 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
601 /* If architecture is Windows x64, the version is always 3. */
602 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
603 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
608 fstrcpy(printdollar
, "print$");
610 printdollar_snum
= find_service(printdollar
);
611 if (printdollar_snum
== -1) {
612 *perr
= WERR_NO_SUCH_SHARE
;
616 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
617 lp_pathname(printdollar_snum
),
618 p
->server_info
, &oldcwd
);
619 if (!NT_STATUS_IS_OK(nt_status
)) {
620 DEBUG(0,("get_correct_cversion: create_conn_struct "
621 "returned %s\n", nt_errstr(nt_status
)));
622 *perr
= ntstatus_to_werror(nt_status
);
626 /* Open the driver file (Portable Executable format) and determine the
627 * deriver the cversion. */
628 driverpath
= talloc_asprintf(talloc_tos(),
637 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
638 if (!NT_STATUS_IS_OK(nt_status
)) {
639 *perr
= ntstatus_to_werror(nt_status
);
643 nt_status
= vfs_file_exist(conn
, smb_fname
);
644 if (!NT_STATUS_IS_OK(nt_status
)) {
645 *perr
= WERR_BADFILE
;
649 status
= SMB_VFS_CREATE_FILE(
652 0, /* root_dir_fid */
653 smb_fname
, /* fname */
654 FILE_GENERIC_READ
, /* access_mask */
655 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
656 FILE_OPEN
, /* create_disposition*/
657 0, /* create_options */
658 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
659 INTERNAL_OPEN_ONLY
, /* oplock_request */
660 0, /* private_flags */
661 0, /* allocation_size */
667 if (!NT_STATUS_IS_OK(status
)) {
668 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
669 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
670 *perr
= WERR_ACCESS_DENIED
;
677 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
678 if (ret
== -1) goto error_exit
;
681 DEBUG(6,("get_correct_cversion: Version info not "
683 smb_fname_str_dbg(smb_fname
)));
688 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
689 * for more details. Version in this case is not just the version of the
690 * file, but the version in the sense of kernal mode (2) vs. user mode
691 * (3) drivers. Other bits of the version fields are the version info.
694 cversion
= major
& 0x0000ffff;
696 case 2: /* WinNT drivers */
697 case 3: /* Win2K drivers */
701 DEBUG(6,("get_correct_cversion: cversion "
702 "invalid [%s] cversion = %d\n",
703 smb_fname_str_dbg(smb_fname
),
708 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
709 " = 0x%x minor = 0x%x\n",
710 smb_fname_str_dbg(smb_fname
), major
, minor
));
713 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
714 smb_fname_str_dbg(smb_fname
), cversion
));
721 TALLOC_FREE(smb_fname
);
723 close_file(NULL
, fsp
, NORMAL_CLOSE
);
726 vfs_ChDir(conn
, oldcwd
);
729 if (cversion
!= -1) {
735 /****************************************************************************
736 ****************************************************************************/
738 #define strip_driver_path(_mem_ctx, _element) do { \
739 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
740 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
741 W_ERROR_HAVE_NO_MEMORY((_element)); \
745 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
746 struct pipes_struct
*rpc_pipe
,
747 const char *architecture
,
748 const char **driver_path
,
749 const char **data_file
,
750 const char **config_file
,
751 const char **help_file
,
752 struct spoolss_StringArray
*dependent_files
,
755 const char *short_architecture
;
760 if (!*driver_path
|| !*data_file
|| !*config_file
) {
761 return WERR_INVALID_PARAM
;
764 /* clean up the driver name.
765 * we can get .\driver.dll
766 * or worse c:\windows\system\driver.dll !
768 /* using an intermediate string to not have overlaping memcpy()'s */
770 strip_driver_path(mem_ctx
, *driver_path
);
771 strip_driver_path(mem_ctx
, *data_file
);
772 strip_driver_path(mem_ctx
, *config_file
);
774 strip_driver_path(mem_ctx
, *help_file
);
777 if (dependent_files
&& dependent_files
->string
) {
778 for (i
=0; dependent_files
->string
[i
]; i
++) {
779 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
783 short_architecture
= get_short_archi(architecture
);
784 if (!short_architecture
) {
785 return WERR_UNKNOWN_PRINTER_DRIVER
;
788 /* jfm:7/16/2000 the client always sends the cversion=0.
789 * The server should check which version the driver is by reading
790 * the PE header of driver->driverpath.
792 * For Windows 95/98 the version is 0 (so the value sent is correct)
793 * For Windows NT (the architecture doesn't matter)
795 * NT 3.5/3.51: cversion=1
800 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
802 if (*version
== -1) {
809 /****************************************************************************
810 ****************************************************************************/
812 WERROR
clean_up_driver_struct(TALLOC_CTX
*mem_ctx
,
813 struct pipes_struct
*rpc_pipe
,
814 struct spoolss_AddDriverInfoCtr
*r
)
818 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
819 r
->info
.info3
->architecture
,
820 &r
->info
.info3
->driver_path
,
821 &r
->info
.info3
->data_file
,
822 &r
->info
.info3
->config_file
,
823 &r
->info
.info3
->help_file
,
824 r
->info
.info3
->dependent_files
,
825 &r
->info
.info3
->version
);
827 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
828 r
->info
.info6
->architecture
,
829 &r
->info
.info6
->driver_path
,
830 &r
->info
.info6
->data_file
,
831 &r
->info
.info6
->config_file
,
832 &r
->info
.info6
->help_file
,
833 r
->info
.info6
->dependent_files
,
834 &r
->info
.info6
->version
);
836 return WERR_NOT_SUPPORTED
;
840 /****************************************************************************
841 This function sucks and should be replaced. JRA.
842 ****************************************************************************/
844 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
845 const struct spoolss_AddDriverInfo6
*src
)
847 dst
->version
= src
->version
;
849 dst
->driver_name
= src
->driver_name
;
850 dst
->architecture
= src
->architecture
;
851 dst
->driver_path
= src
->driver_path
;
852 dst
->data_file
= src
->data_file
;
853 dst
->config_file
= src
->config_file
;
854 dst
->help_file
= src
->help_file
;
855 dst
->monitor_name
= src
->monitor_name
;
856 dst
->default_datatype
= src
->default_datatype
;
857 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
858 dst
->dependent_files
= src
->dependent_files
;
861 /****************************************************************************
862 ****************************************************************************/
864 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
865 connection_struct
*conn
,
866 const char *driver_file
,
867 const char *short_architecture
,
868 uint32_t driver_version
,
871 struct smb_filename
*smb_fname_old
= NULL
;
872 struct smb_filename
*smb_fname_new
= NULL
;
873 char *old_name
= NULL
;
874 char *new_name
= NULL
;
878 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
879 short_architecture
, driver_file
);
880 W_ERROR_HAVE_NO_MEMORY(old_name
);
882 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
883 short_architecture
, driver_version
, driver_file
);
884 if (new_name
== NULL
) {
885 TALLOC_FREE(old_name
);
889 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
891 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
892 if (!NT_STATUS_IS_OK(status
)) {
897 /* Setup a synthetic smb_filename struct */
898 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
899 if (!smb_fname_new
) {
904 smb_fname_new
->base_name
= new_name
;
906 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
907 "'%s'\n", smb_fname_old
->base_name
,
908 smb_fname_new
->base_name
));
910 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
911 OPENX_FILE_EXISTS_TRUNCATE
|
912 OPENX_FILE_CREATE_IF_NOT_EXIST
,
915 if (!NT_STATUS_IS_OK(status
)) {
916 DEBUG(0,("move_driver_file_to_download_area: Unable "
917 "to rename [%s] to [%s]: %s\n",
918 smb_fname_old
->base_name
, new_name
,
920 ret
= WERR_ACCESS_DENIED
;
927 TALLOC_FREE(smb_fname_old
);
928 TALLOC_FREE(smb_fname_new
);
932 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
933 struct spoolss_AddDriverInfoCtr
*r
,
936 struct spoolss_AddDriverInfo3
*driver
;
937 struct spoolss_AddDriverInfo3 converted_driver
;
938 const char *short_architecture
;
939 struct smb_filename
*smb_dname
= NULL
;
940 char *new_dir
= NULL
;
941 connection_struct
*conn
= NULL
;
944 TALLOC_CTX
*ctx
= talloc_tos();
948 int printdollar_snum
;
954 driver
= r
->info
.info3
;
957 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
958 driver
= &converted_driver
;
961 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
962 return WERR_UNKNOWN_LEVEL
;
965 short_architecture
= get_short_archi(driver
->architecture
);
966 if (!short_architecture
) {
967 return WERR_UNKNOWN_PRINTER_DRIVER
;
970 fstrcpy(printdollar
, "print$");
972 printdollar_snum
= find_service(printdollar
);
973 if (printdollar_snum
== -1) {
974 *perr
= WERR_NO_SUCH_SHARE
;
975 return WERR_NO_SUCH_SHARE
;
978 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
979 lp_pathname(printdollar_snum
),
980 p
->server_info
, &oldcwd
);
981 if (!NT_STATUS_IS_OK(nt_status
)) {
982 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
983 "returned %s\n", nt_errstr(nt_status
)));
984 *perr
= ntstatus_to_werror(nt_status
);
988 new_dir
= talloc_asprintf(ctx
,
996 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
997 if (!NT_STATUS_IS_OK(nt_status
)) {
1002 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1004 create_directory(conn
, NULL
, smb_dname
);
1006 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1007 * listed for this driver which has already been moved, skip it (note:
1008 * drivers may list the same file name several times. Then check if the
1009 * file already exists in archi\version\, if so, check that the version
1010 * info (or time stamps if version info is unavailable) is newer (or the
1011 * date is later). If it is, move it to archi\version\filexxx.yyy.
1012 * Otherwise, delete the file.
1014 * If a file is not moved to archi\version\ because of an error, all the
1015 * rest of the 'unmoved' driver files are removed from archi\. If one or
1016 * more of the driver's files was already moved to archi\version\, it
1017 * potentially leaves the driver in a partially updated state. Version
1018 * trauma will most likely occur if an client attempts to use any printer
1019 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1020 * done is appropriate... later JRR
1023 DEBUG(5,("Moving files now !\n"));
1025 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1027 *perr
= move_driver_file_to_download_area(ctx
,
1029 driver
->driver_path
,
1033 if (!W_ERROR_IS_OK(*perr
)) {
1034 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1041 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1042 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1044 *perr
= move_driver_file_to_download_area(ctx
,
1050 if (!W_ERROR_IS_OK(*perr
)) {
1051 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1059 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1060 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1061 !strequal(driver
->config_file
, driver
->data_file
)) {
1063 *perr
= move_driver_file_to_download_area(ctx
,
1065 driver
->config_file
,
1069 if (!W_ERROR_IS_OK(*perr
)) {
1070 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1078 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1079 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1080 !strequal(driver
->help_file
, driver
->data_file
) &&
1081 !strequal(driver
->help_file
, driver
->config_file
)) {
1083 *perr
= move_driver_file_to_download_area(ctx
,
1089 if (!W_ERROR_IS_OK(*perr
)) {
1090 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1098 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1099 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1100 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1101 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1102 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1103 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1105 for (j
=0; j
< i
; j
++) {
1106 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
1111 *perr
= move_driver_file_to_download_area(ctx
,
1113 driver
->dependent_files
->string
[i
],
1117 if (!W_ERROR_IS_OK(*perr
)) {
1118 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1129 TALLOC_FREE(smb_dname
);
1132 vfs_ChDir(conn
, oldcwd
);
1136 if (W_ERROR_EQUAL(*perr
, WERR_OK
)) {
1140 return WERR_UNKNOWN_PRINTER_DRIVER
;
1145 /****************************************************************************
1146 Create and allocate a default devicemode.
1147 ****************************************************************************/
1149 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
1150 const char *devicename
,
1151 struct spoolss_DeviceMode
**devmode
)
1153 struct spoolss_DeviceMode
*dm
;
1156 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
1161 dname
= talloc_asprintf(dm
, "%s", devicename
);
1162 if (dname
== NULL
) {
1165 if (strlen(dname
) > MAXDEVICENAME
) {
1166 dname
[MAXDEVICENAME
] = '\0';
1168 dm
->devicename
= dname
;
1170 dm
->formname
= talloc_strdup(dm
, "Letter");
1171 if (dm
->formname
== NULL
) {
1175 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
1176 dm
->driverversion
= 0x0400;
1178 dm
->__driverextra_length
= 0;
1179 dm
->fields
= DEVMODE_FORMNAME
|
1181 DEVMODE_PRINTQUALITY
|
1182 DEVMODE_DEFAULTSOURCE
|
1186 DEVMODE_ORIENTATION
;
1187 dm
->orientation
= DMORIENT_PORTRAIT
;
1188 dm
->papersize
= DMPAPER_LETTER
;
1189 dm
->paperlength
= 0;
1193 dm
->defaultsource
= DMBIN_FORMSOURCE
;
1194 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
1195 dm
->color
= DMRES_MONOCHROME
;
1196 dm
->duplex
= DMDUP_SIMPLEX
;
1197 dm
->yresolution
= 0;
1198 dm
->ttoption
= DMTT_SUBDEV
;
1199 dm
->collate
= DMCOLLATE_FALSE
;
1209 dm
->displayflags
= 0;
1210 dm
->displayfrequency
= 0;
1213 dm
->panningwidth
= 0;
1214 dm
->panningheight
= 0;
1216 dm
->driverextra_data
.data
= NULL
;
1217 dm
->driverextra_data
.length
= 0;
1223 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
1224 struct spoolss_security_descriptor
**secdesc
)
1226 struct security_ace ace
[7]; /* max number of ace entries */
1229 struct security_acl
*psa
= NULL
;
1230 struct security_descriptor
*psd
= NULL
;
1231 struct dom_sid adm_sid
;
1234 /* Create an ACE where Everyone is allowed to print */
1236 sa
= PRINTER_ACE_PRINT
;
1237 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1238 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1240 /* Add the domain admins group if we are a DC */
1243 struct dom_sid domadmins_sid
;
1245 sid_compose(&domadmins_sid
, get_global_sam_sid(),
1248 sa
= PRINTER_ACE_FULL_CONTROL
;
1249 init_sec_ace(&ace
[i
++], &domadmins_sid
,
1250 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1251 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1252 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1253 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1255 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
1256 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
1258 sa
= PRINTER_ACE_FULL_CONTROL
;
1259 init_sec_ace(&ace
[i
++], &adm_sid
,
1260 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1261 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1262 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1263 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1266 /* add BUILTIN\Administrators as FULL CONTROL */
1268 sa
= PRINTER_ACE_FULL_CONTROL
;
1269 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1270 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1271 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1272 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1273 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1274 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1276 /* add BUILTIN\Print Operators as FULL CONTROL */
1278 sa
= PRINTER_ACE_FULL_CONTROL
;
1279 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1280 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1281 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1282 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1283 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1284 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1286 /* Make the security descriptor owned by the BUILTIN\Administrators */
1288 /* The ACL revision number in rpc_secdesc.h differs from the one
1289 created by NT when setting ACE entries in printer
1290 descriptors. NT4 complains about the property being edited by a
1293 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
1294 psd
= make_sec_desc(mem_ctx
,
1296 SEC_DESC_SELF_RELATIVE
,
1297 &global_sid_Builtin_Administrators
,
1298 &global_sid_Builtin_Administrators
,
1305 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1309 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1310 (unsigned int)sd_size
));
1317 /****************************************************************************
1318 ***************************************************************************/
1320 static char *win_driver
;
1321 static char *os2_driver
;
1323 static const char *get_win_driver(void)
1325 if (win_driver
== NULL
) {
1331 static const char *get_os2_driver(void)
1333 if (os2_driver
== NULL
) {
1339 static bool set_driver_mapping(const char *from
, const char *to
)
1341 SAFE_FREE(win_driver
);
1342 SAFE_FREE(os2_driver
);
1344 win_driver
= SMB_STRDUP(from
);
1345 os2_driver
= SMB_STRDUP(to
);
1347 if (win_driver
== NULL
|| os2_driver
== NULL
) {
1348 SAFE_FREE(win_driver
);
1349 SAFE_FREE(os2_driver
);
1358 * @brief Map a Windows driver to a OS/2 driver.
1360 * @param[in] mem_ctx The memory context to use.
1362 * @param[in,out] pdrivername The drivername of Windows to remap.
1364 * @return WERR_OK on success, a corresponding WERROR on failure.
1366 WERROR
spoolss_map_to_os2_driver(TALLOC_CTX
*mem_ctx
, const char **pdrivername
)
1368 const char *mapfile
= lp_os2_driver_map();
1369 char **lines
= NULL
;
1370 const char *drivername
;
1374 if (pdrivername
== NULL
|| *pdrivername
== NULL
|| *pdrivername
[0] == '\0') {
1375 return WERR_INVALID_PARAMETER
;
1378 drivername
= *pdrivername
;
1380 if (mapfile
[0] == '\0') {
1381 return WERR_BADFILE
;
1384 if (strequal(drivername
, get_win_driver())) {
1385 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1386 drivername
, get_os2_driver()));
1387 drivername
= talloc_strdup(mem_ctx
, get_os2_driver());
1388 if (drivername
== NULL
) {
1391 *pdrivername
= drivername
;
1395 lines
= file_lines_load(mapfile
, &numlines
, 0, NULL
);
1396 if (numlines
== 0 || lines
== NULL
) {
1397 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile
));
1402 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
1404 for( i
= 0; i
< numlines
; i
++) {
1405 char *nt_name
= lines
[i
];
1406 char *os2_name
= strchr(nt_name
, '=');
1408 if (os2_name
== NULL
) {
1414 while (isspace(*nt_name
)) {
1418 if (*nt_name
== '\0' || strchr("#;", *nt_name
)) {
1423 int l
= strlen(nt_name
);
1424 while (l
&& isspace(nt_name
[l
- 1])) {
1430 while (isspace(*os2_name
)) {
1435 int l
= strlen(os2_name
);
1436 while (l
&& isspace(os2_name
[l
-1])) {
1442 if (strequal(nt_name
, drivername
)) {
1443 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,os2_name
));
1444 set_driver_mapping(drivername
, os2_name
);
1445 drivername
= talloc_strdup(mem_ctx
, os2_name
);
1447 if (drivername
== NULL
) {
1450 *pdrivername
= drivername
;
1459 /****************************************************************************
1460 ****************************************************************************/
1462 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
1463 struct spoolss_DriverInfo8
*_info8
)
1465 struct spoolss_DriverInfo8 info8
;
1471 info8
.version
= r
->info
.info3
->version
;
1472 info8
.driver_name
= r
->info
.info3
->driver_name
;
1473 info8
.architecture
= r
->info
.info3
->architecture
;
1474 info8
.driver_path
= r
->info
.info3
->driver_path
;
1475 info8
.data_file
= r
->info
.info3
->data_file
;
1476 info8
.config_file
= r
->info
.info3
->config_file
;
1477 info8
.help_file
= r
->info
.info3
->help_file
;
1478 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
1479 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
1480 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
1481 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
1485 info8
.version
= r
->info
.info6
->version
;
1486 info8
.driver_name
= r
->info
.info6
->driver_name
;
1487 info8
.architecture
= r
->info
.info6
->architecture
;
1488 info8
.driver_path
= r
->info
.info6
->driver_path
;
1489 info8
.data_file
= r
->info
.info6
->data_file
;
1490 info8
.config_file
= r
->info
.info6
->config_file
;
1491 info8
.help_file
= r
->info
.info6
->help_file
;
1492 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
1493 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
1494 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
1495 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
1497 info8
.driver_date
= r
->info
.info6
->driver_date
;
1498 info8
.driver_version
= r
->info
.info6
->driver_version
;
1499 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
1500 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
1501 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
1502 info8
.provider
= r
->info
.info6
->provider
;
1505 info8
.version
= r
->info
.info8
->version
;
1506 info8
.driver_name
= r
->info
.info8
->driver_name
;
1507 info8
.architecture
= r
->info
.info8
->architecture
;
1508 info8
.driver_path
= r
->info
.info8
->driver_path
;
1509 info8
.data_file
= r
->info
.info8
->data_file
;
1510 info8
.config_file
= r
->info
.info8
->config_file
;
1511 info8
.help_file
= r
->info
.info8
->help_file
;
1512 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
1513 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
1514 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
1515 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
1517 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
1518 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
1520 info8
.driver_date
= r
->info
.info8
->driver_date
;
1521 info8
.driver_version
= r
->info
.info8
->driver_version
;
1522 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
1523 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
1524 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
1525 info8
.provider
= r
->info
.info8
->provider
;
1526 info8
.print_processor
= r
->info
.info8
->print_processor
;
1527 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
1528 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
1529 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
1531 info8
.inf_path
= r
->info
.info8
->inf_path
;
1532 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
1533 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
1534 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
1536 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
1537 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
1549 /****************************************************************************
1550 Determine whether or not a particular driver is currently assigned
1552 ****************************************************************************/
1554 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
1555 struct auth_serversupplied_info
*server_info
,
1556 struct messaging_context
*msg_ctx
,
1557 const struct spoolss_DriverInfo8
*r
)
1560 int n_services
= lp_numservices();
1561 bool in_use
= False
;
1562 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1569 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1571 /* loop through the printers.tdb and check for the drivername */
1573 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
1574 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1578 result
= winreg_get_printer(mem_ctx
, server_info
, msg_ctx
,
1579 NULL
, lp_servicename(snum
),
1581 if (!W_ERROR_IS_OK(result
)) {
1582 continue; /* skip */
1585 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
1589 TALLOC_FREE(pinfo2
);
1592 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1595 struct spoolss_DriverInfo8
*driver
;
1598 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
1600 /* we can still remove the driver if there is one of
1601 "Windows NT x86" version 2 or 3 left */
1603 if (!strequal("Windows NT x86", r
->architecture
)) {
1604 werr
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
1609 } else if (r
->version
== 2) {
1610 werr
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
1614 } else if (r
->version
== 3) {
1615 werr
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
1620 DEBUG(0, ("printer_driver_in_use: ERROR!"
1621 " unknown driver version (%d)\n",
1623 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
1626 /* now check the error code */
1628 if ( W_ERROR_IS_OK(werr
) ) {
1629 /* it's ok to remove the driver, we have other architctures left */
1631 talloc_free(driver
);
1635 /* report that the driver is not in use by default */
1641 /**********************************************************************
1642 Check to see if a ogiven file is in use by *info
1643 *********************************************************************/
1645 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
1652 /* mz: skip files that are in the list but already deleted */
1653 if (!file
|| !file
[0]) {
1657 if (strequal(file
, info
->driver_path
))
1660 if (strequal(file
, info
->data_file
))
1663 if (strequal(file
, info
->config_file
))
1666 if (strequal(file
, info
->help_file
))
1669 /* see of there are any dependent files to examine */
1671 if (!info
->dependent_files
)
1674 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
1675 if (strequal(file
, info
->dependent_files
[i
]))
1684 /**********************************************************************
1685 Utility function to remove the dependent file pointed to by the
1686 input parameter from the list
1687 *********************************************************************/
1689 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
1692 /* bump everything down a slot */
1694 while (files
&& files
[idx
+1]) {
1695 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
1704 /**********************************************************************
1705 Check if any of the files used by src are also used by drv
1706 *********************************************************************/
1708 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
1709 struct spoolss_DriverInfo8
*src
,
1710 const struct spoolss_DriverInfo8
*drv
)
1712 bool in_use
= False
;
1718 /* check each file. Remove it from the src structure if it overlaps */
1720 if (drv_file_in_use(src
->driver_path
, drv
)) {
1722 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
1723 src
->driver_path
= talloc_strdup(mem_ctx
, "");
1724 if (!src
->driver_path
) { return false; }
1727 if (drv_file_in_use(src
->data_file
, drv
)) {
1729 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
1730 src
->data_file
= talloc_strdup(mem_ctx
, "");
1731 if (!src
->data_file
) { return false; }
1734 if (drv_file_in_use(src
->config_file
, drv
)) {
1736 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
1737 src
->config_file
= talloc_strdup(mem_ctx
, "");
1738 if (!src
->config_file
) { return false; }
1741 if (drv_file_in_use(src
->help_file
, drv
)) {
1743 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
1744 src
->help_file
= talloc_strdup(mem_ctx
, "");
1745 if (!src
->help_file
) { return false; }
1748 /* are there any dependentfiles to examine? */
1750 if (!src
->dependent_files
)
1753 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
1754 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
1756 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
1757 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
1765 /****************************************************************************
1766 Determine whether or not a particular driver files are currently being
1767 used by any other driver.
1769 Return value is True if any files were in use by other drivers
1770 and False otherwise.
1772 Upon return, *info has been modified to only contain the driver files
1773 which are not in use
1777 This needs to check all drivers to ensure that all files in use
1778 have been removed from *info, not just the ones in the first
1780 ****************************************************************************/
1782 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
1783 struct auth_serversupplied_info
*server_info
,
1784 struct messaging_context
*msg_ctx
,
1785 struct spoolss_DriverInfo8
*info
)
1789 struct spoolss_DriverInfo8
*driver
;
1790 bool in_use
= false;
1791 uint32_t num_drivers
;
1792 const char **drivers
;
1798 version
= info
->version
;
1800 /* loop over all driver versions */
1802 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1804 /* get the list of drivers */
1806 result
= winreg_get_driver_list(mem_ctx
, server_info
, msg_ctx
,
1807 info
->architecture
, version
,
1808 &num_drivers
, &drivers
);
1809 if (!W_ERROR_IS_OK(result
)) {
1813 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1814 num_drivers
, info
->architecture
, version
));
1816 /* check each driver for overlap in files */
1818 for (i
= 0; i
< num_drivers
; i
++) {
1819 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
1823 result
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
1824 info
->architecture
, drivers
[i
],
1826 if (!W_ERROR_IS_OK(result
)) {
1827 talloc_free(drivers
);
1831 /* check if d2 uses any files from d1 */
1832 /* only if this is a different driver than the one being deleted */
1834 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
1835 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
1836 /* mz: Do not instantly return -
1837 * we need to ensure this file isn't
1838 * also in use by other drivers. */
1843 talloc_free(driver
);
1846 talloc_free(drivers
);
1848 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1853 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
1856 struct smb_filename
*smb_fname
= NULL
;
1859 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
1861 if (!NT_STATUS_IS_OK(status
)) {
1865 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
1867 TALLOC_FREE(smb_fname
);
1871 /****************************************************************************
1872 Actually delete the driver files. Make sure that
1873 printer_driver_files_in_use() return False before calling
1875 ****************************************************************************/
1877 bool delete_driver_files(struct auth_serversupplied_info
*server_info
,
1878 const struct spoolss_DriverInfo8
*r
)
1883 connection_struct
*conn
;
1886 fstring printdollar
;
1887 int printdollar_snum
;
1894 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1895 r
->driver_name
, r
->version
));
1897 fstrcpy(printdollar
, "print$");
1899 printdollar_snum
= find_service(printdollar
);
1900 if (printdollar_snum
== -1) {
1904 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1905 lp_pathname(printdollar_snum
),
1906 server_info
, &oldcwd
);
1907 if (!NT_STATUS_IS_OK(nt_status
)) {
1908 DEBUG(0,("delete_driver_files: create_conn_struct "
1909 "returned %s\n", nt_errstr(nt_status
)));
1913 if ( !CAN_WRITE(conn
) ) {
1914 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1918 /* now delete the files; must strip the '\print$' string from
1921 if (r
->driver_path
&& r
->driver_path
[0]) {
1922 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
1924 DEBUG(10,("deleting driverfile [%s]\n", s
));
1925 driver_unlink_internals(conn
, file
);
1929 if (r
->config_file
&& r
->config_file
[0]) {
1930 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
1932 DEBUG(10,("deleting configfile [%s]\n", s
));
1933 driver_unlink_internals(conn
, file
);
1937 if (r
->data_file
&& r
->data_file
[0]) {
1938 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
1940 DEBUG(10,("deleting datafile [%s]\n", s
));
1941 driver_unlink_internals(conn
, file
);
1945 if (r
->help_file
&& r
->help_file
[0]) {
1946 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
1948 DEBUG(10,("deleting helpfile [%s]\n", s
));
1949 driver_unlink_internals(conn
, file
);
1953 /* check if we are done removing files */
1955 if (r
->dependent_files
) {
1956 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
1959 /* bypass the "\print$" portion of the path */
1961 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
1963 DEBUG(10,("deleting dependent file [%s]\n", file
));
1964 driver_unlink_internals(conn
, file
);
1976 vfs_ChDir(conn
, oldcwd
);
1984 1: level not implemented
1985 2: file doesn't exist
1986 3: can't allocate memory
1987 4: can't free memory
1988 5: non existant struct
1992 A printer and a printer driver are 2 different things.
1993 NT manages them separatelly, Samba does the same.
1994 Why ? Simply because it's easier and it makes sense !
1996 Now explanation: You have 3 printers behind your samba server,
1997 2 of them are the same make and model (laser A and B). But laser B
1998 has an 3000 sheet feeder and laser A doesn't such an option.
1999 Your third printer is an old dot-matrix model for the accounting :-).
2001 If the /usr/local/samba/lib directory (default dir), you will have
2002 5 files to describe all of this.
2004 3 files for the printers (1 by printer):
2007 NTprinter_accounting
2008 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2009 NTdriver_printer model X
2010 NTdriver_printer model Y
2012 jfm: I should use this comment for the text file to explain
2013 same thing for the forms BTW.
2014 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2018 /* Convert generic access rights to printer object specific access rights.
2019 It turns out that NT4 security descriptors use generic access rights and
2020 NT5 the object specific ones. */
2022 void map_printer_permissions(struct security_descriptor
*sd
)
2026 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2027 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2028 &printer_generic_mapping
);
2032 void map_job_permissions(struct security_descriptor
*sd
)
2036 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2037 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2038 &job_generic_mapping
);
2043 /****************************************************************************
2044 Check a user has permissions to perform the given operation. We use the
2045 permission constants defined in include/rpc_spoolss.h to check the various
2046 actions we perform when checking printer access.
2048 PRINTER_ACCESS_ADMINISTER:
2049 print_queue_pause, print_queue_resume, update_printer_sec,
2050 update_printer, spoolss_addprinterex_level_2,
2051 _spoolss_setprinterdata
2056 JOB_ACCESS_ADMINISTER:
2057 print_job_delete, print_job_pause, print_job_resume,
2060 Try access control in the following order (for performance reasons):
2061 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2062 2) check security descriptor (bit comparisons in memory)
2063 3) "printer admins" (may result in numerous calls to winbind)
2065 ****************************************************************************/
2066 bool print_access_check(struct auth_serversupplied_info
*server_info
,
2067 struct messaging_context
*msg_ctx
, int snum
,
2070 struct spoolss_security_descriptor
*secdesc
= NULL
;
2071 uint32 access_granted
;
2076 TALLOC_CTX
*mem_ctx
= NULL
;
2077 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2079 /* If user is NULL then use the current_user structure */
2081 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2083 if (server_info
->utok
.uid
== sec_initial_uid()
2084 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
2088 /* Get printer name */
2090 pname
= lp_printername(snum
);
2092 if (!pname
|| !*pname
) {
2097 /* Get printer security descriptor */
2099 if(!(mem_ctx
= talloc_init("print_access_check"))) {
2104 result
= winreg_get_printer_secdesc(mem_ctx
,
2109 if (!W_ERROR_IS_OK(result
)) {
2110 talloc_destroy(mem_ctx
);
2115 if (access_type
== JOB_ACCESS_ADMINISTER
) {
2116 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
2118 /* Create a child security descriptor to check permissions
2119 against. This is because print jobs are child objects
2120 objects of a printer. */
2121 status
= se_create_child_secdesc(mem_ctx
,
2125 parent_secdesc
->owner_sid
,
2126 parent_secdesc
->group_sid
,
2128 if (!NT_STATUS_IS_OK(status
)) {
2129 talloc_destroy(mem_ctx
);
2130 errno
= map_errno_from_nt_status(status
);
2134 map_job_permissions(secdesc
);
2136 map_printer_permissions(secdesc
);
2140 status
= se_access_check(secdesc
, server_info
->ptok
, access_type
,
2143 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
2145 /* see if we need to try the printer admin list */
2147 if (!NT_STATUS_IS_OK(status
) &&
2148 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
2149 server_info
->info3
->base
.domain
.string
,
2150 NULL
, server_info
->ptok
,
2151 lp_printer_admin(snum
)))) {
2152 talloc_destroy(mem_ctx
);
2156 talloc_destroy(mem_ctx
);
2158 if (!NT_STATUS_IS_OK(status
)) {
2162 return NT_STATUS_IS_OK(status
);
2165 /****************************************************************************
2166 Check the time parameters allow a print operation.
2167 *****************************************************************************/
2169 bool print_time_access_check(struct auth_serversupplied_info
*server_info
,
2170 struct messaging_context
*msg_ctx
,
2171 const char *servicename
)
2173 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2176 time_t now
= time(NULL
);
2180 result
= winreg_get_printer(NULL
, server_info
, msg_ctx
,
2181 NULL
, servicename
, &pinfo2
);
2182 if (!W_ERROR_IS_OK(result
)) {
2186 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
2191 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
2193 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
2197 TALLOC_FREE(pinfo2
);
2206 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
2207 struct auth_serversupplied_info
*server_info
,
2208 struct messaging_context
*msg_ctx
,
2209 const char *printer
)
2213 result
= winreg_delete_printer_key(mem_ctx
, server_info
, msg_ctx
,
2215 if (!W_ERROR_IS_OK(result
)) {
2216 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",