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/pcap.h"
24 #include "printing/nt_printing_tdb.h"
25 #include "printing/nt_printing_migrate.h"
27 #include "registry/reg_objects.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "../librpc/gen_ndr/ndr_spoolss.h"
30 #include "rpc_server/spoolss/srv_spoolss_util.h"
31 #include "nt_printing.h"
33 #include "../librpc/gen_ndr/netlogon.h"
34 #include "../libcli/security/security.h"
35 #include "passdb/machine_sid.h"
36 #include "smbd/smbd.h"
40 #include "rpc_server/spoolss/srv_spoolss_nt.h"
42 /* Map generic permissions to printer object specific permissions */
44 const struct generic_mapping printer_generic_mapping
= {
51 /* Map generic permissions to print server object specific permissions */
53 const struct generic_mapping printserver_generic_mapping
= {
60 /* Map generic permissions to job object specific permissions */
62 const struct generic_mapping job_generic_mapping
= {
69 static const struct print_architecture_table_node archi_table
[]= {
71 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
72 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
73 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
74 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
75 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
76 {"Windows IA64", SPL_ARCH_IA64
, 3 },
77 {"Windows x64", SPL_ARCH_X64
, 3 },
81 /****************************************************************************
82 Open the NT printing tdbs. Done once before fork().
83 ****************************************************************************/
85 bool nt_printing_init(struct messaging_context
*msg_ctx
)
89 if (!nt_printing_tdb_upgrade()) {
94 * register callback to handle updating printers as new
95 * drivers are installed
97 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
98 do_drv_upgrade_printer
);
100 /* of course, none of the message callbacks matter if you don't
101 tell messages.c that you interested in receiving PRINT_GENERAL
102 msgs. This is done in serverid_register() */
104 if ( lp_security() == SEC_ADS
) {
105 win_rc
= check_published_printers(msg_ctx
);
106 if (!W_ERROR_IS_OK(win_rc
))
107 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
113 /*******************************************************************
114 Function to allow filename parsing "the old way".
115 ********************************************************************/
117 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
118 const char *old_name
,
119 struct smb_filename
**smb_fname
)
122 TALLOC_CTX
*ctx
= talloc_tos();
123 char *name
= talloc_strdup(ctx
, old_name
);
126 return NT_STATUS_NO_MEMORY
;
129 name
= unix_clean_name(ctx
, name
);
131 return NT_STATUS_NO_MEMORY
;
133 trim_string(name
,"/","/");
135 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
136 if (!NT_STATUS_IS_OK(status
)) {
137 return NT_STATUS_NO_MEMORY
;
143 /****************************************************************************
144 Function to do the mapping between the long architecture name and
146 ****************************************************************************/
148 const char *get_short_archi(const char *long_archi
)
152 DEBUG(107,("Getting architecture dependent directory\n"));
155 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
156 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
158 if (archi_table
[i
].long_archi
==NULL
) {
159 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
163 /* this might be client code - but shouldn't this be an fstrcpy etc? */
165 DEBUGADD(108,("index: [%d]\n", i
));
166 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
167 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
169 return archi_table
[i
].short_archi
;
172 /****************************************************************************
173 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
174 There are two case to be covered here: PE (Portable Executable) and NE (New
175 Executable) files. Both files support the same INFO structure, but PE files
176 store the signature in unicode, and NE files store it as !unicode.
177 returns -1 on error, 1 on version info found, and 0 on no version info found.
178 ****************************************************************************/
180 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
186 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
187 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
188 fname
, DOS_HEADER_SIZE
));
192 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
193 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
194 fname
, (unsigned long)byte_count
));
195 goto no_version_info
;
198 /* Is this really a DOS header? */
199 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
200 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
201 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
202 goto no_version_info
;
205 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
206 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
207 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
209 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
210 goto no_version_info
;
213 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
214 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
215 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
216 fname
, (unsigned long)byte_count
));
217 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
218 goto no_version_info
;
221 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
222 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
223 unsigned int num_sections
;
224 unsigned int section_table_bytes
;
226 /* Just skip over optional header to get to section table */
227 if (SMB_VFS_LSEEK(fsp
,
228 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
229 SEEK_CUR
) == (SMB_OFF_T
)-1) {
230 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
235 /* get the section table */
236 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
237 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
238 if (section_table_bytes
== 0)
242 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
243 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
244 fname
, section_table_bytes
));
248 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
249 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
250 fname
, (unsigned long)byte_count
));
254 /* Iterate the section table looking for the resource section ".rsrc" */
255 for (i
= 0; i
< num_sections
; i
++) {
256 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
258 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
259 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
260 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
262 if (section_bytes
== 0)
266 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
267 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
268 fname
, section_bytes
));
272 /* Seek to the start of the .rsrc section info */
273 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
274 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
279 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
280 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
281 fname
, (unsigned long)byte_count
));
285 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
288 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
289 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
290 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
291 /* Align to next long address */
292 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
294 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
295 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
296 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
298 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
299 fname
, *major
, *minor
,
300 (*major
>>16)&0xffff, *major
&0xffff,
301 (*minor
>>16)&0xffff, *minor
&0xffff));
310 /* Version info not found, fall back to origin date/time */
311 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
315 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
316 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
317 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
318 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
319 /* At this point, we assume the file is in error. It still could be somthing
320 * else besides a NE file, but it unlikely at this point. */
324 /* Allocate a bit more space to speed up things */
326 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
327 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
328 fname
, PE_HEADER_SIZE
));
332 /* This is a HACK! I got tired of trying to sort through the messy
333 * 'NE' file format. If anyone wants to clean this up please have at
334 * it, but this works. 'NE' files will eventually fade away. JRR */
335 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
336 /* Cover case that should not occur in a well formed 'NE' .dll file */
337 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
339 for(i
=0; i
<byte_count
; i
++) {
340 /* Fast skip past data that can't possibly match */
341 if (buf
[i
] != 'V') continue;
343 /* Potential match data crosses buf boundry, move it to beginning
344 * of buf, and fill the buf with as much as it will hold. */
345 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
348 memcpy(buf
, &buf
[i
], byte_count
-i
);
349 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
350 (byte_count
-i
))) < 0) {
352 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
357 byte_count
= bc
+ (byte_count
- i
);
358 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
363 /* Check that the full signature string and the magic number that
364 * follows exist (not a perfect solution, but the chances that this
365 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
366 * twice, as it is simpler to read the code. */
367 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
368 /* Compute skip alignment to next long address */
369 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
370 sizeof(VS_SIGNATURE
)) & 3;
371 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
373 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
374 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
375 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
376 fname
, *major
, *minor
,
377 (*major
>>16)&0xffff, *major
&0xffff,
378 (*minor
>>16)&0xffff, *minor
&0xffff));
385 /* Version info not found, fall back to origin date/time */
386 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
391 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
392 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
393 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
404 /****************************************************************************
405 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
406 share one or more files. During the MS installation process files are checked
407 to insure that only a newer version of a shared file is installed over an
408 older version. There are several possibilities for this comparison. If there
409 is no previous version, the new one is newer (obviously). If either file is
410 missing the version info structure, compare the creation date (on Unix use
411 the modification date). Otherwise chose the numerically larger version number.
412 ****************************************************************************/
414 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
416 bool use_version
= true;
420 time_t new_create_time
;
424 time_t old_create_time
;
426 struct smb_filename
*smb_fname
= NULL
;
427 files_struct
*fsp
= NULL
;
433 SET_STAT_INVALID(st
);
434 new_create_time
= (time_t)0;
435 old_create_time
= (time_t)0;
437 /* Get file version info (if available) for previous file (if it exists) */
438 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
439 if (!NT_STATUS_IS_OK(status
)) {
443 status
= SMB_VFS_CREATE_FILE(
446 0, /* root_dir_fid */
447 smb_fname
, /* fname */
448 FILE_GENERIC_READ
, /* access_mask */
449 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
450 FILE_OPEN
, /* create_disposition*/
451 0, /* create_options */
452 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
453 INTERNAL_OPEN_ONLY
, /* oplock_request */
454 0, /* allocation_size */
455 0, /* private_flags */
461 if (!NT_STATUS_IS_OK(status
)) {
462 /* Old file not found, so by definition new file is in fact newer */
463 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
464 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
470 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
476 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
479 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
482 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
483 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
484 (long)old_create_time
));
487 close_file(NULL
, fsp
, NORMAL_CLOSE
);
490 /* Get file version info (if available) for new file */
491 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
492 if (!NT_STATUS_IS_OK(status
)) {
496 status
= SMB_VFS_CREATE_FILE(
499 0, /* root_dir_fid */
500 smb_fname
, /* fname */
501 FILE_GENERIC_READ
, /* access_mask */
502 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
503 FILE_OPEN
, /* create_disposition*/
504 0, /* create_options */
505 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
506 INTERNAL_OPEN_ONLY
, /* oplock_request */
507 0, /* allocation_size */
508 0, /* private_flags */
514 if (!NT_STATUS_IS_OK(status
)) {
515 /* New file not found, this shouldn't occur if the caller did its job */
516 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
517 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
521 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
527 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
530 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
533 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
534 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
535 (long)new_create_time
));
538 close_file(NULL
, fsp
, NORMAL_CLOSE
);
541 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
542 /* Compare versions and choose the larger version number */
543 if (new_major
> old_major
||
544 (new_major
== old_major
&& new_minor
> old_minor
)) {
546 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
551 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
557 /* Compare modification time/dates and choose the newest time/date */
558 if (new_create_time
> old_create_time
) {
559 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
564 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
572 close_file(NULL
, fsp
, NORMAL_CLOSE
);
575 TALLOC_FREE(smb_fname
);
579 /****************************************************************************
580 Determine the correct cVersion associated with an architecture and driver
581 ****************************************************************************/
582 static uint32
get_correct_cversion(struct pipes_struct
*p
,
583 const char *architecture
,
584 const char *driverpath_in
,
589 struct smb_filename
*smb_fname
= NULL
;
590 char *driverpath
= NULL
;
591 files_struct
*fsp
= NULL
;
592 connection_struct
*conn
= NULL
;
594 char *printdollar
= NULL
;
595 int printdollar_snum
;
597 *perr
= WERR_INVALID_PARAM
;
599 /* If architecture is Windows 95/98/ME, the version is always 0. */
600 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
601 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
606 /* If architecture is Windows x64, the version is always 3. */
607 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
608 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
613 printdollar_snum
= find_service(talloc_tos(), "print$", &printdollar
);
618 if (printdollar_snum
== -1) {
619 *perr
= WERR_NO_SUCH_SHARE
;
623 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
624 lp_pathname(printdollar_snum
),
625 p
->session_info
, &oldcwd
);
626 if (!NT_STATUS_IS_OK(nt_status
)) {
627 DEBUG(0,("get_correct_cversion: create_conn_struct "
628 "returned %s\n", nt_errstr(nt_status
)));
629 *perr
= ntstatus_to_werror(nt_status
);
633 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
634 if (!NT_STATUS_IS_OK(nt_status
)) {
635 DEBUG(0, ("failed set force user / group\n"));
636 *perr
= ntstatus_to_werror(nt_status
);
637 goto error_free_conn
;
640 if (!become_user_by_session(conn
, p
->session_info
)) {
641 DEBUG(0, ("failed to become user\n"));
642 *perr
= WERR_ACCESS_DENIED
;
643 goto error_free_conn
;
646 /* Open the driver file (Portable Executable format) and determine the
647 * deriver the cversion. */
648 driverpath
= talloc_asprintf(talloc_tos(),
657 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
658 if (!NT_STATUS_IS_OK(nt_status
)) {
659 *perr
= ntstatus_to_werror(nt_status
);
663 nt_status
= vfs_file_exist(conn
, smb_fname
);
664 if (!NT_STATUS_IS_OK(nt_status
)) {
665 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
666 *perr
= WERR_BADFILE
;
670 nt_status
= SMB_VFS_CREATE_FILE(
673 0, /* root_dir_fid */
674 smb_fname
, /* fname */
675 FILE_GENERIC_READ
, /* access_mask */
676 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
677 FILE_OPEN
, /* create_disposition*/
678 0, /* create_options */
679 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
680 INTERNAL_OPEN_ONLY
, /* oplock_request */
681 0, /* private_flags */
682 0, /* allocation_size */
688 if (!NT_STATUS_IS_OK(nt_status
)) {
689 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
690 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
691 *perr
= WERR_ACCESS_DENIED
;
698 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
700 *perr
= WERR_INVALID_PARAM
;
703 DEBUG(6,("get_correct_cversion: Version info not "
705 smb_fname_str_dbg(smb_fname
)));
706 *perr
= WERR_INVALID_PARAM
;
711 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
712 * for more details. Version in this case is not just the version of the
713 * file, but the version in the sense of kernal mode (2) vs. user mode
714 * (3) drivers. Other bits of the version fields are the version info.
717 cversion
= major
& 0x0000ffff;
719 case 2: /* WinNT drivers */
720 case 3: /* Win2K drivers */
724 DEBUG(6,("get_correct_cversion: cversion "
725 "invalid [%s] cversion = %d\n",
726 smb_fname_str_dbg(smb_fname
),
731 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
732 " = 0x%x minor = 0x%x\n",
733 smb_fname_str_dbg(smb_fname
), major
, minor
));
736 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
737 smb_fname_str_dbg(smb_fname
), cversion
));
743 TALLOC_FREE(smb_fname
);
745 close_file(NULL
, fsp
, NORMAL_CLOSE
);
748 vfs_ChDir(conn
, oldcwd
);
749 SMB_VFS_DISCONNECT(conn
);
752 if (!NT_STATUS_IS_OK(*perr
)) {
759 /****************************************************************************
760 ****************************************************************************/
762 #define strip_driver_path(_mem_ctx, _element) do { \
763 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
764 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
765 W_ERROR_HAVE_NO_MEMORY((_element)); \
769 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
770 struct pipes_struct
*rpc_pipe
,
771 const char *architecture
,
772 const char **driver_path
,
773 const char **data_file
,
774 const char **config_file
,
775 const char **help_file
,
776 struct spoolss_StringArray
*dependent_files
,
777 enum spoolss_DriverOSVersion
*version
)
779 const char *short_architecture
;
784 if (!*driver_path
|| !*data_file
) {
785 return WERR_INVALID_PARAM
;
788 if (!strequal(architecture
, SPOOLSS_ARCHITECTURE_4_0
) && !*config_file
) {
789 return WERR_INVALID_PARAM
;
792 /* clean up the driver name.
793 * we can get .\driver.dll
794 * or worse c:\windows\system\driver.dll !
796 /* using an intermediate string to not have overlaping memcpy()'s */
798 strip_driver_path(mem_ctx
, *driver_path
);
799 strip_driver_path(mem_ctx
, *data_file
);
801 strip_driver_path(mem_ctx
, *config_file
);
804 strip_driver_path(mem_ctx
, *help_file
);
807 if (dependent_files
&& dependent_files
->string
) {
808 for (i
=0; dependent_files
->string
[i
]; i
++) {
809 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
813 short_architecture
= get_short_archi(architecture
);
814 if (!short_architecture
) {
815 return WERR_UNKNOWN_PRINTER_DRIVER
;
818 /* jfm:7/16/2000 the client always sends the cversion=0.
819 * The server should check which version the driver is by reading
820 * the PE header of driver->driverpath.
822 * For Windows 95/98 the version is 0 (so the value sent is correct)
823 * For Windows NT (the architecture doesn't matter)
825 * NT 3.5/3.51: cversion=1
830 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
832 if (*version
== -1) {
839 /****************************************************************************
840 ****************************************************************************/
842 WERROR
clean_up_driver_struct(TALLOC_CTX
*mem_ctx
,
843 struct pipes_struct
*rpc_pipe
,
844 struct spoolss_AddDriverInfoCtr
*r
)
848 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
849 r
->info
.info3
->architecture
,
850 &r
->info
.info3
->driver_path
,
851 &r
->info
.info3
->data_file
,
852 &r
->info
.info3
->config_file
,
853 &r
->info
.info3
->help_file
,
854 r
->info
.info3
->dependent_files
,
855 &r
->info
.info3
->version
);
857 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
858 r
->info
.info6
->architecture
,
859 &r
->info
.info6
->driver_path
,
860 &r
->info
.info6
->data_file
,
861 &r
->info
.info6
->config_file
,
862 &r
->info
.info6
->help_file
,
863 r
->info
.info6
->dependent_files
,
864 &r
->info
.info6
->version
);
866 return WERR_NOT_SUPPORTED
;
870 /****************************************************************************
871 This function sucks and should be replaced. JRA.
872 ****************************************************************************/
874 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
875 const struct spoolss_AddDriverInfo6
*src
)
877 dst
->version
= src
->version
;
879 dst
->driver_name
= src
->driver_name
;
880 dst
->architecture
= src
->architecture
;
881 dst
->driver_path
= src
->driver_path
;
882 dst
->data_file
= src
->data_file
;
883 dst
->config_file
= src
->config_file
;
884 dst
->help_file
= src
->help_file
;
885 dst
->monitor_name
= src
->monitor_name
;
886 dst
->default_datatype
= src
->default_datatype
;
887 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
888 dst
->dependent_files
= src
->dependent_files
;
891 /****************************************************************************
892 ****************************************************************************/
894 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
895 connection_struct
*conn
,
896 const char *driver_file
,
897 const char *short_architecture
,
898 uint32_t driver_version
,
901 struct smb_filename
*smb_fname_old
= NULL
;
902 struct smb_filename
*smb_fname_new
= NULL
;
903 char *old_name
= NULL
;
904 char *new_name
= NULL
;
908 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
909 short_architecture
, driver_file
);
910 W_ERROR_HAVE_NO_MEMORY(old_name
);
912 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
913 short_architecture
, driver_version
, driver_file
);
914 if (new_name
== NULL
) {
915 TALLOC_FREE(old_name
);
919 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
921 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
922 if (!NT_STATUS_IS_OK(status
)) {
927 /* Setup a synthetic smb_filename struct */
928 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
929 if (!smb_fname_new
) {
934 smb_fname_new
->base_name
= new_name
;
936 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
937 "'%s'\n", smb_fname_old
->base_name
,
938 smb_fname_new
->base_name
));
940 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
941 OPENX_FILE_EXISTS_TRUNCATE
|
942 OPENX_FILE_CREATE_IF_NOT_EXIST
,
945 if (!NT_STATUS_IS_OK(status
)) {
946 DEBUG(0,("move_driver_file_to_download_area: Unable "
947 "to rename [%s] to [%s]: %s\n",
948 smb_fname_old
->base_name
, new_name
,
950 ret
= WERR_ACCESS_DENIED
;
957 TALLOC_FREE(smb_fname_old
);
958 TALLOC_FREE(smb_fname_new
);
962 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
963 struct spoolss_AddDriverInfoCtr
*r
)
965 struct spoolss_AddDriverInfo3
*driver
;
966 struct spoolss_AddDriverInfo3 converted_driver
;
967 const char *short_architecture
;
968 struct smb_filename
*smb_dname
= NULL
;
969 char *new_dir
= NULL
;
970 connection_struct
*conn
= NULL
;
973 TALLOC_CTX
*ctx
= talloc_tos();
976 char *printdollar
= NULL
;
977 int printdollar_snum
;
978 WERROR err
= WERR_OK
;
982 driver
= r
->info
.info3
;
985 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
986 driver
= &converted_driver
;
989 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
990 return WERR_UNKNOWN_LEVEL
;
993 short_architecture
= get_short_archi(driver
->architecture
);
994 if (!short_architecture
) {
995 return WERR_UNKNOWN_PRINTER_DRIVER
;
998 printdollar_snum
= find_service(ctx
, "print$", &printdollar
);
1002 if (printdollar_snum
== -1) {
1003 return WERR_NO_SUCH_SHARE
;
1006 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1007 lp_pathname(printdollar_snum
),
1008 p
->session_info
, &oldcwd
);
1009 if (!NT_STATUS_IS_OK(nt_status
)) {
1010 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1011 "returned %s\n", nt_errstr(nt_status
)));
1012 err
= ntstatus_to_werror(nt_status
);
1016 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1017 if (!NT_STATUS_IS_OK(nt_status
)) {
1018 DEBUG(0, ("failed set force user / group\n"));
1019 err
= ntstatus_to_werror(nt_status
);
1023 if (!become_user_by_session(conn
, p
->session_info
)) {
1024 DEBUG(0, ("failed to become user\n"));
1025 err
= WERR_ACCESS_DENIED
;
1029 new_dir
= talloc_asprintf(ctx
,
1037 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1038 if (!NT_STATUS_IS_OK(nt_status
)) {
1043 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1045 nt_status
= create_directory(conn
, NULL
, smb_dname
);
1046 if (!NT_STATUS_IS_OK(nt_status
)
1047 && !NT_STATUS_EQUAL(nt_status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
1048 DEBUG(0, ("failed to create driver destination directory: %s\n",
1049 nt_errstr(nt_status
)));
1050 err
= ntstatus_to_werror(nt_status
);
1054 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1055 * listed for this driver which has already been moved, skip it (note:
1056 * drivers may list the same file name several times. Then check if the
1057 * file already exists in archi\version\, if so, check that the version
1058 * info (or time stamps if version info is unavailable) is newer (or the
1059 * date is later). If it is, move it to archi\version\filexxx.yyy.
1060 * Otherwise, delete the file.
1062 * If a file is not moved to archi\version\ because of an error, all the
1063 * rest of the 'unmoved' driver files are removed from archi\. If one or
1064 * more of the driver's files was already moved to archi\version\, it
1065 * potentially leaves the driver in a partially updated state. Version
1066 * trauma will most likely occur if an client attempts to use any printer
1067 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1068 * done is appropriate... later JRR
1071 DEBUG(5,("Moving files now !\n"));
1073 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1075 err
= move_driver_file_to_download_area(ctx
,
1077 driver
->driver_path
,
1081 if (!W_ERROR_IS_OK(err
)) {
1086 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1087 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1089 err
= move_driver_file_to_download_area(ctx
,
1095 if (!W_ERROR_IS_OK(err
)) {
1101 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1102 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1103 !strequal(driver
->config_file
, driver
->data_file
)) {
1105 err
= move_driver_file_to_download_area(ctx
,
1107 driver
->config_file
,
1111 if (!W_ERROR_IS_OK(err
)) {
1117 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1118 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1119 !strequal(driver
->help_file
, driver
->data_file
) &&
1120 !strequal(driver
->help_file
, driver
->config_file
)) {
1122 err
= move_driver_file_to_download_area(ctx
,
1128 if (!W_ERROR_IS_OK(err
)) {
1134 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1135 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1136 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1137 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1138 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1139 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1141 for (j
=0; j
< i
; j
++) {
1142 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
1147 err
= move_driver_file_to_download_area(ctx
,
1149 driver
->dependent_files
->string
[i
],
1153 if (!W_ERROR_IS_OK(err
)) {
1165 TALLOC_FREE(smb_dname
);
1168 vfs_ChDir(conn
, oldcwd
);
1169 SMB_VFS_DISCONNECT(conn
);
1176 /****************************************************************************
1177 Create and allocate a default devicemode.
1178 ****************************************************************************/
1180 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
1181 const char *devicename
,
1182 struct spoolss_DeviceMode
**devmode
)
1184 struct spoolss_DeviceMode
*dm
;
1187 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
1192 dname
= talloc_asprintf(dm
, "%s", devicename
);
1193 if (dname
== NULL
) {
1196 if (strlen(dname
) > MAXDEVICENAME
) {
1197 dname
[MAXDEVICENAME
] = '\0';
1199 dm
->devicename
= dname
;
1201 dm
->formname
= talloc_strdup(dm
, "Letter");
1202 if (dm
->formname
== NULL
) {
1206 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
1207 dm
->driverversion
= 0x0400;
1209 dm
->__driverextra_length
= 0;
1210 dm
->fields
= DEVMODE_FORMNAME
|
1212 DEVMODE_PRINTQUALITY
|
1213 DEVMODE_DEFAULTSOURCE
|
1217 DEVMODE_ORIENTATION
;
1218 dm
->orientation
= DMORIENT_PORTRAIT
;
1219 dm
->papersize
= DMPAPER_LETTER
;
1220 dm
->paperlength
= 0;
1224 dm
->defaultsource
= DMBIN_FORMSOURCE
;
1225 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
1226 dm
->color
= DMRES_MONOCHROME
;
1227 dm
->duplex
= DMDUP_SIMPLEX
;
1228 dm
->yresolution
= 0;
1229 dm
->ttoption
= DMTT_SUBDEV
;
1230 dm
->collate
= DMCOLLATE_FALSE
;
1240 dm
->displayflags
= 0;
1241 dm
->displayfrequency
= 0;
1244 dm
->panningwidth
= 0;
1245 dm
->panningheight
= 0;
1247 dm
->driverextra_data
.data
= NULL
;
1248 dm
->driverextra_data
.length
= 0;
1254 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
1255 struct spoolss_security_descriptor
**secdesc
)
1257 struct security_ace ace
[7]; /* max number of ace entries */
1260 struct security_acl
*psa
= NULL
;
1261 struct security_descriptor
*psd
= NULL
;
1262 struct dom_sid adm_sid
;
1265 /* Create an ACE where Everyone is allowed to print */
1267 sa
= PRINTER_ACE_PRINT
;
1268 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1269 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1271 /* Add the domain admins group if we are a DC */
1274 struct dom_sid domadmins_sid
;
1276 sid_compose(&domadmins_sid
, get_global_sam_sid(),
1279 sa
= PRINTER_ACE_FULL_CONTROL
;
1280 init_sec_ace(&ace
[i
++], &domadmins_sid
,
1281 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1282 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1283 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1284 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1286 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
1287 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
1289 sa
= PRINTER_ACE_FULL_CONTROL
;
1290 init_sec_ace(&ace
[i
++], &adm_sid
,
1291 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1292 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1293 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1294 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1297 /* add BUILTIN\Administrators as FULL CONTROL */
1299 sa
= PRINTER_ACE_FULL_CONTROL
;
1300 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1301 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1302 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1303 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1304 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1305 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1307 /* add BUILTIN\Print Operators as FULL CONTROL */
1309 sa
= PRINTER_ACE_FULL_CONTROL
;
1310 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1311 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1312 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1313 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1314 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1315 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1317 /* Make the security descriptor owned by the BUILTIN\Administrators */
1319 /* The ACL revision number in rpc_secdesc.h differs from the one
1320 created by NT when setting ACE entries in printer
1321 descriptors. NT4 complains about the property being edited by a
1324 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
1325 psd
= make_sec_desc(mem_ctx
,
1327 SEC_DESC_SELF_RELATIVE
,
1328 &global_sid_Builtin_Administrators
,
1329 &global_sid_Builtin_Administrators
,
1336 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1340 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1341 (unsigned int)sd_size
));
1348 /****************************************************************************
1349 ***************************************************************************/
1351 static char *win_driver
;
1352 static char *os2_driver
;
1354 static const char *get_win_driver(void)
1356 if (win_driver
== NULL
) {
1362 static const char *get_os2_driver(void)
1364 if (os2_driver
== NULL
) {
1370 static bool set_driver_mapping(const char *from
, const char *to
)
1372 SAFE_FREE(win_driver
);
1373 SAFE_FREE(os2_driver
);
1375 win_driver
= SMB_STRDUP(from
);
1376 os2_driver
= SMB_STRDUP(to
);
1378 if (win_driver
== NULL
|| os2_driver
== NULL
) {
1379 SAFE_FREE(win_driver
);
1380 SAFE_FREE(os2_driver
);
1389 * @brief Map a Windows driver to a OS/2 driver.
1391 * @param[in] mem_ctx The memory context to use.
1393 * @param[in,out] pdrivername The drivername of Windows to remap.
1395 * @return WERR_OK on success, a corresponding WERROR on failure.
1397 WERROR
spoolss_map_to_os2_driver(TALLOC_CTX
*mem_ctx
, const char **pdrivername
)
1399 const char *mapfile
= lp_os2_driver_map();
1400 char **lines
= NULL
;
1401 const char *drivername
;
1405 if (pdrivername
== NULL
|| *pdrivername
== NULL
|| *pdrivername
[0] == '\0') {
1406 return WERR_INVALID_PARAMETER
;
1409 drivername
= *pdrivername
;
1411 if (mapfile
[0] == '\0') {
1412 return WERR_BADFILE
;
1415 if (strequal(drivername
, get_win_driver())) {
1416 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1417 drivername
, get_os2_driver()));
1418 drivername
= talloc_strdup(mem_ctx
, get_os2_driver());
1419 if (drivername
== NULL
) {
1422 *pdrivername
= drivername
;
1426 lines
= file_lines_load(mapfile
, &numlines
, 0, NULL
);
1427 if (numlines
== 0 || lines
== NULL
) {
1428 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile
));
1433 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
1435 for( i
= 0; i
< numlines
; i
++) {
1436 char *nt_name
= lines
[i
];
1437 char *os2_name
= strchr(nt_name
, '=');
1439 if (os2_name
== NULL
) {
1445 while (isspace(*nt_name
)) {
1449 if (*nt_name
== '\0' || strchr("#;", *nt_name
)) {
1454 int l
= strlen(nt_name
);
1455 while (l
&& isspace(nt_name
[l
- 1])) {
1461 while (isspace(*os2_name
)) {
1466 int l
= strlen(os2_name
);
1467 while (l
&& isspace(os2_name
[l
-1])) {
1473 if (strequal(nt_name
, drivername
)) {
1474 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,os2_name
));
1475 set_driver_mapping(drivername
, os2_name
);
1476 drivername
= talloc_strdup(mem_ctx
, os2_name
);
1478 if (drivername
== NULL
) {
1481 *pdrivername
= drivername
;
1490 /****************************************************************************
1491 ****************************************************************************/
1493 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
1494 struct spoolss_DriverInfo8
*_info8
)
1496 struct spoolss_DriverInfo8 info8
;
1502 info8
.version
= r
->info
.info3
->version
;
1503 info8
.driver_name
= r
->info
.info3
->driver_name
;
1504 info8
.architecture
= r
->info
.info3
->architecture
;
1505 info8
.driver_path
= r
->info
.info3
->driver_path
;
1506 info8
.data_file
= r
->info
.info3
->data_file
;
1507 info8
.config_file
= r
->info
.info3
->config_file
;
1508 info8
.help_file
= r
->info
.info3
->help_file
;
1509 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
1510 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
1511 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
1512 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
1516 info8
.version
= r
->info
.info6
->version
;
1517 info8
.driver_name
= r
->info
.info6
->driver_name
;
1518 info8
.architecture
= r
->info
.info6
->architecture
;
1519 info8
.driver_path
= r
->info
.info6
->driver_path
;
1520 info8
.data_file
= r
->info
.info6
->data_file
;
1521 info8
.config_file
= r
->info
.info6
->config_file
;
1522 info8
.help_file
= r
->info
.info6
->help_file
;
1523 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
1524 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
1525 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
1526 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
1528 info8
.driver_date
= r
->info
.info6
->driver_date
;
1529 info8
.driver_version
= r
->info
.info6
->driver_version
;
1530 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
1531 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
1532 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
1533 info8
.provider
= r
->info
.info6
->provider
;
1536 info8
.version
= r
->info
.info8
->version
;
1537 info8
.driver_name
= r
->info
.info8
->driver_name
;
1538 info8
.architecture
= r
->info
.info8
->architecture
;
1539 info8
.driver_path
= r
->info
.info8
->driver_path
;
1540 info8
.data_file
= r
->info
.info8
->data_file
;
1541 info8
.config_file
= r
->info
.info8
->config_file
;
1542 info8
.help_file
= r
->info
.info8
->help_file
;
1543 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
1544 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
1545 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
1546 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
1548 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
1549 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
1551 info8
.driver_date
= r
->info
.info8
->driver_date
;
1552 info8
.driver_version
= r
->info
.info8
->driver_version
;
1553 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
1554 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
1555 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
1556 info8
.provider
= r
->info
.info8
->provider
;
1557 info8
.print_processor
= r
->info
.info8
->print_processor
;
1558 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
1559 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
1560 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
1562 info8
.inf_path
= r
->info
.info8
->inf_path
;
1563 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
1564 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
1565 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
1567 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
1568 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
1580 /****************************************************************************
1581 Determine whether or not a particular driver is currently assigned
1583 ****************************************************************************/
1585 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
1586 const struct auth_serversupplied_info
*session_info
,
1587 struct messaging_context
*msg_ctx
,
1588 const struct spoolss_DriverInfo8
*r
)
1591 int n_services
= lp_numservices();
1592 bool in_use
= False
;
1593 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1600 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1602 /* loop through the printers.tdb and check for the drivername */
1604 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
1605 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1609 result
= winreg_get_printer(mem_ctx
, session_info
, msg_ctx
,
1610 lp_servicename(snum
),
1612 if (!W_ERROR_IS_OK(result
)) {
1613 continue; /* skip */
1616 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
1620 TALLOC_FREE(pinfo2
);
1623 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1626 struct spoolss_DriverInfo8
*driver
;
1629 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
1631 /* we can still remove the driver if there is one of
1632 "Windows NT x86" version 2 or 3 left */
1634 if (!strequal("Windows NT x86", r
->architecture
)) {
1635 werr
= winreg_get_driver(mem_ctx
, session_info
, msg_ctx
,
1640 } else if (r
->version
== 2) {
1641 werr
= winreg_get_driver(mem_ctx
, session_info
, msg_ctx
,
1645 } else if (r
->version
== 3) {
1646 werr
= winreg_get_driver(mem_ctx
, session_info
, msg_ctx
,
1651 DEBUG(0, ("printer_driver_in_use: ERROR!"
1652 " unknown driver version (%d)\n",
1654 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
1657 /* now check the error code */
1659 if ( W_ERROR_IS_OK(werr
) ) {
1660 /* it's ok to remove the driver, we have other architctures left */
1662 talloc_free(driver
);
1666 /* report that the driver is not in use by default */
1672 /**********************************************************************
1673 Check to see if a ogiven file is in use by *info
1674 *********************************************************************/
1676 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
1683 /* mz: skip files that are in the list but already deleted */
1684 if (!file
|| !file
[0]) {
1688 if (strequal(file
, info
->driver_path
))
1691 if (strequal(file
, info
->data_file
))
1694 if (strequal(file
, info
->config_file
))
1697 if (strequal(file
, info
->help_file
))
1700 /* see of there are any dependent files to examine */
1702 if (!info
->dependent_files
)
1705 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
1706 if (strequal(file
, info
->dependent_files
[i
]))
1715 /**********************************************************************
1716 Utility function to remove the dependent file pointed to by the
1717 input parameter from the list
1718 *********************************************************************/
1720 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
1723 /* bump everything down a slot */
1725 while (files
&& files
[idx
+1]) {
1726 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
1735 /**********************************************************************
1736 Check if any of the files used by src are also used by drv
1737 *********************************************************************/
1739 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
1740 struct spoolss_DriverInfo8
*src
,
1741 const struct spoolss_DriverInfo8
*drv
)
1743 bool in_use
= False
;
1749 /* check each file. Remove it from the src structure if it overlaps */
1751 if (drv_file_in_use(src
->driver_path
, drv
)) {
1753 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
1754 src
->driver_path
= talloc_strdup(mem_ctx
, "");
1755 if (!src
->driver_path
) { return false; }
1758 if (drv_file_in_use(src
->data_file
, drv
)) {
1760 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
1761 src
->data_file
= talloc_strdup(mem_ctx
, "");
1762 if (!src
->data_file
) { return false; }
1765 if (drv_file_in_use(src
->config_file
, drv
)) {
1767 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
1768 src
->config_file
= talloc_strdup(mem_ctx
, "");
1769 if (!src
->config_file
) { return false; }
1772 if (drv_file_in_use(src
->help_file
, drv
)) {
1774 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
1775 src
->help_file
= talloc_strdup(mem_ctx
, "");
1776 if (!src
->help_file
) { return false; }
1779 /* are there any dependentfiles to examine? */
1781 if (!src
->dependent_files
)
1784 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
1785 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
1787 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
1788 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
1796 /****************************************************************************
1797 Determine whether or not a particular driver files are currently being
1798 used by any other driver.
1800 Return value is True if any files were in use by other drivers
1801 and False otherwise.
1803 Upon return, *info has been modified to only contain the driver files
1804 which are not in use
1808 This needs to check all drivers to ensure that all files in use
1809 have been removed from *info, not just the ones in the first
1811 ****************************************************************************/
1813 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
1814 const struct auth_serversupplied_info
*session_info
,
1815 struct messaging_context
*msg_ctx
,
1816 struct spoolss_DriverInfo8
*info
)
1820 struct spoolss_DriverInfo8
*driver
;
1821 bool in_use
= false;
1822 uint32_t num_drivers
;
1823 const char **drivers
;
1829 version
= info
->version
;
1831 /* loop over all driver versions */
1833 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1835 /* get the list of drivers */
1837 result
= winreg_get_driver_list(mem_ctx
, session_info
, msg_ctx
,
1838 info
->architecture
, version
,
1839 &num_drivers
, &drivers
);
1840 if (!W_ERROR_IS_OK(result
)) {
1844 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1845 num_drivers
, info
->architecture
, version
));
1847 /* check each driver for overlap in files */
1849 for (i
= 0; i
< num_drivers
; i
++) {
1850 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
1854 result
= winreg_get_driver(mem_ctx
, session_info
, msg_ctx
,
1855 info
->architecture
, drivers
[i
],
1857 if (!W_ERROR_IS_OK(result
)) {
1858 talloc_free(drivers
);
1862 /* check if d2 uses any files from d1 */
1863 /* only if this is a different driver than the one being deleted */
1865 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
1866 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
1867 /* mz: Do not instantly return -
1868 * we need to ensure this file isn't
1869 * also in use by other drivers. */
1874 talloc_free(driver
);
1877 talloc_free(drivers
);
1879 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1884 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
1887 struct smb_filename
*smb_fname
= NULL
;
1890 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
1892 if (!NT_STATUS_IS_OK(status
)) {
1896 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
1898 TALLOC_FREE(smb_fname
);
1902 /****************************************************************************
1903 Actually delete the driver files. Make sure that
1904 printer_driver_files_in_use() return False before calling
1906 ****************************************************************************/
1908 bool delete_driver_files(const struct auth_serversupplied_info
*session_info
,
1909 const struct spoolss_DriverInfo8
*r
)
1914 connection_struct
*conn
;
1917 char *printdollar
= NULL
;
1918 int printdollar_snum
;
1925 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1926 r
->driver_name
, r
->version
));
1928 printdollar_snum
= find_service(talloc_tos(), "print$", &printdollar
);
1932 if (printdollar_snum
== -1) {
1936 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1937 lp_pathname(printdollar_snum
),
1938 session_info
, &oldcwd
);
1939 if (!NT_STATUS_IS_OK(nt_status
)) {
1940 DEBUG(0,("delete_driver_files: create_conn_struct "
1941 "returned %s\n", nt_errstr(nt_status
)));
1945 nt_status
= set_conn_force_user_group(conn
, printdollar_snum
);
1946 if (!NT_STATUS_IS_OK(nt_status
)) {
1947 DEBUG(0, ("failed set force user / group\n"));
1952 if (!become_user_by_session(conn
, session_info
)) {
1953 DEBUG(0, ("failed to become user\n"));
1958 if ( !CAN_WRITE(conn
) ) {
1959 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1964 /* now delete the files; must strip the '\print$' string from
1967 if (r
->driver_path
&& r
->driver_path
[0]) {
1968 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
1970 DEBUG(10,("deleting driverfile [%s]\n", s
));
1971 driver_unlink_internals(conn
, file
);
1975 if (r
->config_file
&& r
->config_file
[0]) {
1976 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
1978 DEBUG(10,("deleting configfile [%s]\n", s
));
1979 driver_unlink_internals(conn
, file
);
1983 if (r
->data_file
&& r
->data_file
[0]) {
1984 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
1986 DEBUG(10,("deleting datafile [%s]\n", s
));
1987 driver_unlink_internals(conn
, file
);
1991 if (r
->help_file
&& r
->help_file
[0]) {
1992 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
1994 DEBUG(10,("deleting helpfile [%s]\n", s
));
1995 driver_unlink_internals(conn
, file
);
1999 /* check if we are done removing files */
2001 if (r
->dependent_files
) {
2002 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
2005 /* bypass the "\print$" portion of the path */
2007 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
2009 DEBUG(10,("deleting dependent file [%s]\n", file
));
2010 driver_unlink_internals(conn
, file
);
2022 vfs_ChDir(conn
, oldcwd
);
2023 SMB_VFS_DISCONNECT(conn
);
2031 1: level not implemented
2032 2: file doesn't exist
2033 3: can't allocate memory
2034 4: can't free memory
2035 5: non existant struct
2039 A printer and a printer driver are 2 different things.
2040 NT manages them separatelly, Samba does the same.
2041 Why ? Simply because it's easier and it makes sense !
2043 Now explanation: You have 3 printers behind your samba server,
2044 2 of them are the same make and model (laser A and B). But laser B
2045 has an 3000 sheet feeder and laser A doesn't such an option.
2046 Your third printer is an old dot-matrix model for the accounting :-).
2048 If the /usr/local/samba/lib directory (default dir), you will have
2049 5 files to describe all of this.
2051 3 files for the printers (1 by printer):
2054 NTprinter_accounting
2055 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2056 NTdriver_printer model X
2057 NTdriver_printer model Y
2059 jfm: I should use this comment for the text file to explain
2060 same thing for the forms BTW.
2061 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2065 /* Convert generic access rights to printer object specific access rights.
2066 It turns out that NT4 security descriptors use generic access rights and
2067 NT5 the object specific ones. */
2069 void map_printer_permissions(struct security_descriptor
*sd
)
2073 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2074 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2075 &printer_generic_mapping
);
2079 void map_job_permissions(struct security_descriptor
*sd
)
2083 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2084 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2085 &job_generic_mapping
);
2090 /****************************************************************************
2091 Check a user has permissions to perform the given operation. We use the
2092 permission constants defined in include/rpc_spoolss.h to check the various
2093 actions we perform when checking printer access.
2095 PRINTER_ACCESS_ADMINISTER:
2096 print_queue_pause, print_queue_resume, update_printer_sec,
2097 update_printer, spoolss_addprinterex_level_2,
2098 _spoolss_setprinterdata
2103 JOB_ACCESS_ADMINISTER:
2104 print_job_delete, print_job_pause, print_job_resume,
2107 Try access control in the following order (for performance reasons):
2108 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2109 2) check security descriptor (bit comparisons in memory)
2110 3) "printer admins" (may result in numerous calls to winbind)
2112 ****************************************************************************/
2113 bool print_access_check(const struct auth_serversupplied_info
*session_info
,
2114 struct messaging_context
*msg_ctx
, int snum
,
2117 struct spoolss_security_descriptor
*secdesc
= NULL
;
2118 uint32 access_granted
;
2123 TALLOC_CTX
*mem_ctx
= NULL
;
2125 /* If user is NULL then use the current_user structure */
2127 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2129 if (session_info
->utok
.uid
== sec_initial_uid()
2130 || security_token_has_privilege(session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)) {
2134 /* Get printer name */
2136 pname
= lp_printername(snum
);
2138 if (!pname
|| !*pname
) {
2143 /* Get printer security descriptor */
2145 if(!(mem_ctx
= talloc_init("print_access_check"))) {
2150 result
= winreg_get_printer_secdesc(mem_ctx
,
2151 get_session_info_system(),
2155 if (!W_ERROR_IS_OK(result
)) {
2156 talloc_destroy(mem_ctx
);
2161 if (access_type
== JOB_ACCESS_ADMINISTER
) {
2162 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
2164 /* Create a child security descriptor to check permissions
2165 against. This is because print jobs are child objects
2166 objects of a printer. */
2167 status
= se_create_child_secdesc(mem_ctx
,
2171 parent_secdesc
->owner_sid
,
2172 parent_secdesc
->group_sid
,
2174 if (!NT_STATUS_IS_OK(status
)) {
2175 talloc_destroy(mem_ctx
);
2176 errno
= map_errno_from_nt_status(status
);
2180 map_job_permissions(secdesc
);
2182 map_printer_permissions(secdesc
);
2186 status
= se_access_check(secdesc
, session_info
->security_token
, access_type
,
2189 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
2191 /* see if we need to try the printer admin list */
2193 if (!NT_STATUS_IS_OK(status
) &&
2194 (token_contains_name_in_list(uidtoname(session_info
->utok
.uid
),
2195 session_info
->info3
->base
.domain
.string
,
2196 NULL
, session_info
->security_token
,
2197 lp_printer_admin(snum
)))) {
2198 talloc_destroy(mem_ctx
);
2202 talloc_destroy(mem_ctx
);
2204 if (!NT_STATUS_IS_OK(status
)) {
2208 return NT_STATUS_IS_OK(status
);
2211 /****************************************************************************
2212 Check the time parameters allow a print operation.
2213 *****************************************************************************/
2215 bool print_time_access_check(const struct auth_serversupplied_info
*session_info
,
2216 struct messaging_context
*msg_ctx
,
2217 const char *servicename
)
2219 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2222 time_t now
= time(NULL
);
2226 result
= winreg_get_printer(NULL
, session_info
, msg_ctx
,
2227 servicename
, &pinfo2
);
2228 if (!W_ERROR_IS_OK(result
)) {
2232 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
2237 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
2239 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
2243 TALLOC_FREE(pinfo2
);
2252 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
2253 const struct auth_serversupplied_info
*session_info
,
2254 struct messaging_context
*msg_ctx
,
2255 const char *printer
)
2259 result
= winreg_delete_printer_key(mem_ctx
, session_info
, msg_ctx
,
2261 if (!W_ERROR_IS_OK(result
)) {
2262 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",