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"
33 #include "../rpc_server/srv_spoolss_util.h"
35 /* Map generic permissions to printer object specific permissions */
37 const struct generic_mapping printer_generic_mapping
= {
44 /* Map generic permissions to print server object specific permissions */
46 const struct generic_mapping printserver_generic_mapping
= {
53 /* Map generic permissions to job object specific permissions */
55 const struct generic_mapping job_generic_mapping
= {
62 static const struct print_architecture_table_node archi_table
[]= {
64 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
65 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
66 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
67 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
68 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
69 {"Windows IA64", SPL_ARCH_IA64
, 3 },
70 {"Windows x64", SPL_ARCH_X64
, 3 },
74 /****************************************************************************
75 Open the NT printing tdbs. Done once before fork().
76 ****************************************************************************/
78 bool nt_printing_init(struct messaging_context
*msg_ctx
)
82 if (!nt_printing_tdb_upgrade()) {
87 * register callback to handle updating printers as new
88 * drivers are installed
90 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
91 do_drv_upgrade_printer
);
93 /* of course, none of the message callbacks matter if you don't
94 tell messages.c that you interested in receiving PRINT_GENERAL
95 msgs. This is done in serverid_register() */
97 if ( lp_security() == SEC_ADS
) {
98 win_rc
= check_published_printers();
99 if (!W_ERROR_IS_OK(win_rc
))
100 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
106 /*******************************************************************
107 Function to allow filename parsing "the old way".
108 ********************************************************************/
110 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
111 const char *old_name
,
112 struct smb_filename
**smb_fname
)
115 TALLOC_CTX
*ctx
= talloc_tos();
116 char *name
= talloc_strdup(ctx
, old_name
);
119 return NT_STATUS_NO_MEMORY
;
122 name
= unix_clean_name(ctx
, name
);
124 return NT_STATUS_NO_MEMORY
;
126 trim_string(name
,"/","/");
128 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
129 if (!NT_STATUS_IS_OK(status
)) {
130 return NT_STATUS_NO_MEMORY
;
136 /****************************************************************************
137 Function to do the mapping between the long architecture name and
139 ****************************************************************************/
141 const char *get_short_archi(const char *long_archi
)
145 DEBUG(107,("Getting architecture dependant directory\n"));
148 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
149 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
151 if (archi_table
[i
].long_archi
==NULL
) {
152 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
156 /* this might be client code - but shouldn't this be an fstrcpy etc? */
158 DEBUGADD(108,("index: [%d]\n", i
));
159 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
160 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
162 return archi_table
[i
].short_archi
;
165 /****************************************************************************
166 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
167 There are two case to be covered here: PE (Portable Executable) and NE (New
168 Executable) files. Both files support the same INFO structure, but PE files
169 store the signature in unicode, and NE files store it as !unicode.
170 returns -1 on error, 1 on version info found, and 0 on no version info found.
171 ****************************************************************************/
173 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
179 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
180 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
181 fname
, DOS_HEADER_SIZE
));
185 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
186 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
187 fname
, (unsigned long)byte_count
));
188 goto no_version_info
;
191 /* Is this really a DOS header? */
192 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
193 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
194 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
195 goto no_version_info
;
198 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
199 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
200 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
202 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
203 goto no_version_info
;
206 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
207 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
208 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
209 fname
, (unsigned long)byte_count
));
210 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
211 goto no_version_info
;
214 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
215 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
216 unsigned int num_sections
;
217 unsigned int section_table_bytes
;
219 /* Just skip over optional header to get to section table */
220 if (SMB_VFS_LSEEK(fsp
,
221 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
222 SEEK_CUR
) == (SMB_OFF_T
)-1) {
223 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
228 /* get the section table */
229 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
230 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
231 if (section_table_bytes
== 0)
235 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
236 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
237 fname
, section_table_bytes
));
241 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
242 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
243 fname
, (unsigned long)byte_count
));
247 /* Iterate the section table looking for the resource section ".rsrc" */
248 for (i
= 0; i
< num_sections
; i
++) {
249 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
251 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
252 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
253 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
255 if (section_bytes
== 0)
259 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
260 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
261 fname
, section_bytes
));
265 /* Seek to the start of the .rsrc section info */
266 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
267 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
272 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
273 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
274 fname
, (unsigned long)byte_count
));
278 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
281 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
282 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
283 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
284 /* Align to next long address */
285 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
287 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
288 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
289 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
291 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
292 fname
, *major
, *minor
,
293 (*major
>>16)&0xffff, *major
&0xffff,
294 (*minor
>>16)&0xffff, *minor
&0xffff));
303 /* Version info not found, fall back to origin date/time */
304 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
308 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
309 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
310 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
311 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
312 /* At this point, we assume the file is in error. It still could be somthing
313 * else besides a NE file, but it unlikely at this point. */
317 /* Allocate a bit more space to speed up things */
319 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
320 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
321 fname
, PE_HEADER_SIZE
));
325 /* This is a HACK! I got tired of trying to sort through the messy
326 * 'NE' file format. If anyone wants to clean this up please have at
327 * it, but this works. 'NE' files will eventually fade away. JRR */
328 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
329 /* Cover case that should not occur in a well formed 'NE' .dll file */
330 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
332 for(i
=0; i
<byte_count
; i
++) {
333 /* Fast skip past data that can't possibly match */
334 if (buf
[i
] != 'V') continue;
336 /* Potential match data crosses buf boundry, move it to beginning
337 * of buf, and fill the buf with as much as it will hold. */
338 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
341 memcpy(buf
, &buf
[i
], byte_count
-i
);
342 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
343 (byte_count
-i
))) < 0) {
345 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
350 byte_count
= bc
+ (byte_count
- i
);
351 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
356 /* Check that the full signature string and the magic number that
357 * follows exist (not a perfect solution, but the chances that this
358 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
359 * twice, as it is simpler to read the code. */
360 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
361 /* Compute skip alignment to next long address */
362 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
363 sizeof(VS_SIGNATURE
)) & 3;
364 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
366 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
367 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
368 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
369 fname
, *major
, *minor
,
370 (*major
>>16)&0xffff, *major
&0xffff,
371 (*minor
>>16)&0xffff, *minor
&0xffff));
378 /* Version info not found, fall back to origin date/time */
379 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
384 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
385 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
386 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
397 /****************************************************************************
398 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
399 share one or more files. During the MS installation process files are checked
400 to insure that only a newer version of a shared file is installed over an
401 older version. There are several possibilities for this comparison. If there
402 is no previous version, the new one is newer (obviously). If either file is
403 missing the version info structure, compare the creation date (on Unix use
404 the modification date). Otherwise chose the numerically larger version number.
405 ****************************************************************************/
407 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
409 bool use_version
= true;
413 time_t new_create_time
;
417 time_t old_create_time
;
419 struct smb_filename
*smb_fname
= NULL
;
420 files_struct
*fsp
= NULL
;
426 SET_STAT_INVALID(st
);
427 new_create_time
= (time_t)0;
428 old_create_time
= (time_t)0;
430 /* Get file version info (if available) for previous file (if it exists) */
431 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
432 if (!NT_STATUS_IS_OK(status
)) {
436 status
= SMB_VFS_CREATE_FILE(
439 0, /* root_dir_fid */
440 smb_fname
, /* fname */
441 FILE_GENERIC_READ
, /* access_mask */
442 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
443 FILE_OPEN
, /* create_disposition*/
444 0, /* create_options */
445 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
446 INTERNAL_OPEN_ONLY
, /* oplock_request */
447 0, /* allocation_size */
448 0, /* private_flags */
454 if (!NT_STATUS_IS_OK(status
)) {
455 /* Old file not found, so by definition new file is in fact newer */
456 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
457 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
463 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
469 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
472 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
475 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
476 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
477 (long)old_create_time
));
480 close_file(NULL
, fsp
, NORMAL_CLOSE
);
483 /* Get file version info (if available) for new file */
484 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
485 if (!NT_STATUS_IS_OK(status
)) {
489 status
= SMB_VFS_CREATE_FILE(
492 0, /* root_dir_fid */
493 smb_fname
, /* fname */
494 FILE_GENERIC_READ
, /* access_mask */
495 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
496 FILE_OPEN
, /* create_disposition*/
497 0, /* create_options */
498 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
499 INTERNAL_OPEN_ONLY
, /* oplock_request */
500 0, /* allocation_size */
501 0, /* private_flags */
507 if (!NT_STATUS_IS_OK(status
)) {
508 /* New file not found, this shouldn't occur if the caller did its job */
509 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
510 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
514 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
520 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
523 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
526 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
527 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
528 (long)new_create_time
));
531 close_file(NULL
, fsp
, NORMAL_CLOSE
);
534 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
535 /* Compare versions and choose the larger version number */
536 if (new_major
> old_major
||
537 (new_major
== old_major
&& new_minor
> old_minor
)) {
539 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
544 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
550 /* Compare modification time/dates and choose the newest time/date */
551 if (new_create_time
> old_create_time
) {
552 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
557 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
565 close_file(NULL
, fsp
, NORMAL_CLOSE
);
568 TALLOC_FREE(smb_fname
);
572 /****************************************************************************
573 Determine the correct cVersion associated with an architecture and driver
574 ****************************************************************************/
575 static uint32
get_correct_cversion(struct pipes_struct
*p
,
576 const char *architecture
,
577 const char *driverpath_in
,
582 struct smb_filename
*smb_fname
= NULL
;
583 char *driverpath
= NULL
;
584 files_struct
*fsp
= NULL
;
585 connection_struct
*conn
= NULL
;
589 int printdollar_snum
;
591 *perr
= WERR_INVALID_PARAM
;
593 /* If architecture is Windows 95/98/ME, the version is always 0. */
594 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
595 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
600 /* If architecture is Windows x64, the version is always 3. */
601 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
602 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
607 fstrcpy(printdollar
, "print$");
609 printdollar_snum
= find_service(printdollar
);
610 if (printdollar_snum
== -1) {
611 *perr
= WERR_NO_SUCH_SHARE
;
615 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
616 lp_pathname(printdollar_snum
),
617 p
->server_info
, &oldcwd
);
618 if (!NT_STATUS_IS_OK(nt_status
)) {
619 DEBUG(0,("get_correct_cversion: create_conn_struct "
620 "returned %s\n", nt_errstr(nt_status
)));
621 *perr
= ntstatus_to_werror(nt_status
);
625 /* Open the driver file (Portable Executable format) and determine the
626 * deriver the cversion. */
627 driverpath
= talloc_asprintf(talloc_tos(),
636 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
637 if (!NT_STATUS_IS_OK(nt_status
)) {
638 *perr
= ntstatus_to_werror(nt_status
);
642 nt_status
= vfs_file_exist(conn
, smb_fname
);
643 if (!NT_STATUS_IS_OK(nt_status
)) {
644 *perr
= WERR_BADFILE
;
648 status
= SMB_VFS_CREATE_FILE(
651 0, /* root_dir_fid */
652 smb_fname
, /* fname */
653 FILE_GENERIC_READ
, /* access_mask */
654 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
655 FILE_OPEN
, /* create_disposition*/
656 0, /* create_options */
657 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
658 INTERNAL_OPEN_ONLY
, /* oplock_request */
659 0, /* private_flags */
660 0, /* allocation_size */
666 if (!NT_STATUS_IS_OK(status
)) {
667 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
668 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
669 *perr
= WERR_ACCESS_DENIED
;
676 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
677 if (ret
== -1) goto error_exit
;
680 DEBUG(6,("get_correct_cversion: Version info not "
682 smb_fname_str_dbg(smb_fname
)));
687 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
688 * for more details. Version in this case is not just the version of the
689 * file, but the version in the sense of kernal mode (2) vs. user mode
690 * (3) drivers. Other bits of the version fields are the version info.
693 cversion
= major
& 0x0000ffff;
695 case 2: /* WinNT drivers */
696 case 3: /* Win2K drivers */
700 DEBUG(6,("get_correct_cversion: cversion "
701 "invalid [%s] cversion = %d\n",
702 smb_fname_str_dbg(smb_fname
),
707 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
708 " = 0x%x minor = 0x%x\n",
709 smb_fname_str_dbg(smb_fname
), major
, minor
));
712 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
713 smb_fname_str_dbg(smb_fname
), cversion
));
720 TALLOC_FREE(smb_fname
);
722 close_file(NULL
, fsp
, NORMAL_CLOSE
);
725 vfs_ChDir(conn
, oldcwd
);
728 if (cversion
!= -1) {
734 /****************************************************************************
735 ****************************************************************************/
737 #define strip_driver_path(_mem_ctx, _element) do { \
738 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
739 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
740 W_ERROR_HAVE_NO_MEMORY((_element)); \
744 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
745 struct pipes_struct
*rpc_pipe
,
746 const char *architecture
,
747 const char **driver_path
,
748 const char **data_file
,
749 const char **config_file
,
750 const char **help_file
,
751 struct spoolss_StringArray
*dependent_files
,
754 const char *short_architecture
;
759 if (!*driver_path
|| !*data_file
|| !*config_file
) {
760 return WERR_INVALID_PARAM
;
763 /* clean up the driver name.
764 * we can get .\driver.dll
765 * or worse c:\windows\system\driver.dll !
767 /* using an intermediate string to not have overlaping memcpy()'s */
769 strip_driver_path(mem_ctx
, *driver_path
);
770 strip_driver_path(mem_ctx
, *data_file
);
771 strip_driver_path(mem_ctx
, *config_file
);
773 strip_driver_path(mem_ctx
, *help_file
);
776 if (dependent_files
&& dependent_files
->string
) {
777 for (i
=0; dependent_files
->string
[i
]; i
++) {
778 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
782 short_architecture
= get_short_archi(architecture
);
783 if (!short_architecture
) {
784 return WERR_UNKNOWN_PRINTER_DRIVER
;
787 /* jfm:7/16/2000 the client always sends the cversion=0.
788 * The server should check which version the driver is by reading
789 * the PE header of driver->driverpath.
791 * For Windows 95/98 the version is 0 (so the value sent is correct)
792 * For Windows NT (the architecture doesn't matter)
794 * NT 3.5/3.51: cversion=1
799 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
801 if (*version
== -1) {
808 /****************************************************************************
809 ****************************************************************************/
811 WERROR
clean_up_driver_struct(TALLOC_CTX
*mem_ctx
,
812 struct pipes_struct
*rpc_pipe
,
813 struct spoolss_AddDriverInfoCtr
*r
)
817 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
818 r
->info
.info3
->architecture
,
819 &r
->info
.info3
->driver_path
,
820 &r
->info
.info3
->data_file
,
821 &r
->info
.info3
->config_file
,
822 &r
->info
.info3
->help_file
,
823 r
->info
.info3
->dependent_files
,
824 &r
->info
.info3
->version
);
826 return clean_up_driver_struct_level(mem_ctx
, rpc_pipe
,
827 r
->info
.info6
->architecture
,
828 &r
->info
.info6
->driver_path
,
829 &r
->info
.info6
->data_file
,
830 &r
->info
.info6
->config_file
,
831 &r
->info
.info6
->help_file
,
832 r
->info
.info6
->dependent_files
,
833 &r
->info
.info6
->version
);
835 return WERR_NOT_SUPPORTED
;
839 /****************************************************************************
840 This function sucks and should be replaced. JRA.
841 ****************************************************************************/
843 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
844 const struct spoolss_AddDriverInfo6
*src
)
846 dst
->version
= src
->version
;
848 dst
->driver_name
= src
->driver_name
;
849 dst
->architecture
= src
->architecture
;
850 dst
->driver_path
= src
->driver_path
;
851 dst
->data_file
= src
->data_file
;
852 dst
->config_file
= src
->config_file
;
853 dst
->help_file
= src
->help_file
;
854 dst
->monitor_name
= src
->monitor_name
;
855 dst
->default_datatype
= src
->default_datatype
;
856 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
857 dst
->dependent_files
= src
->dependent_files
;
860 /****************************************************************************
861 ****************************************************************************/
863 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
864 connection_struct
*conn
,
865 const char *driver_file
,
866 const char *short_architecture
,
867 uint32_t driver_version
,
870 struct smb_filename
*smb_fname_old
= NULL
;
871 struct smb_filename
*smb_fname_new
= NULL
;
872 char *old_name
= NULL
;
873 char *new_name
= NULL
;
877 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
878 short_architecture
, driver_file
);
879 W_ERROR_HAVE_NO_MEMORY(old_name
);
881 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
882 short_architecture
, driver_version
, driver_file
);
883 if (new_name
== NULL
) {
884 TALLOC_FREE(old_name
);
888 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
890 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
891 if (!NT_STATUS_IS_OK(status
)) {
896 /* Setup a synthetic smb_filename struct */
897 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
898 if (!smb_fname_new
) {
903 smb_fname_new
->base_name
= new_name
;
905 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
906 "'%s'\n", smb_fname_old
->base_name
,
907 smb_fname_new
->base_name
));
909 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
910 OPENX_FILE_EXISTS_TRUNCATE
|
911 OPENX_FILE_CREATE_IF_NOT_EXIST
,
914 if (!NT_STATUS_IS_OK(status
)) {
915 DEBUG(0,("move_driver_file_to_download_area: Unable "
916 "to rename [%s] to [%s]: %s\n",
917 smb_fname_old
->base_name
, new_name
,
919 ret
= WERR_ACCESS_DENIED
;
926 TALLOC_FREE(smb_fname_old
);
927 TALLOC_FREE(smb_fname_new
);
931 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
932 struct spoolss_AddDriverInfoCtr
*r
,
935 struct spoolss_AddDriverInfo3
*driver
;
936 struct spoolss_AddDriverInfo3 converted_driver
;
937 const char *short_architecture
;
938 struct smb_filename
*smb_dname
= NULL
;
939 char *new_dir
= NULL
;
940 connection_struct
*conn
= NULL
;
943 TALLOC_CTX
*ctx
= talloc_tos();
947 int printdollar_snum
;
953 driver
= r
->info
.info3
;
956 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
957 driver
= &converted_driver
;
960 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
961 return WERR_UNKNOWN_LEVEL
;
964 short_architecture
= get_short_archi(driver
->architecture
);
965 if (!short_architecture
) {
966 return WERR_UNKNOWN_PRINTER_DRIVER
;
969 fstrcpy(printdollar
, "print$");
971 printdollar_snum
= find_service(printdollar
);
972 if (printdollar_snum
== -1) {
973 *perr
= WERR_NO_SUCH_SHARE
;
974 return WERR_NO_SUCH_SHARE
;
977 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
978 lp_pathname(printdollar_snum
),
979 p
->server_info
, &oldcwd
);
980 if (!NT_STATUS_IS_OK(nt_status
)) {
981 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
982 "returned %s\n", nt_errstr(nt_status
)));
983 *perr
= ntstatus_to_werror(nt_status
);
987 new_dir
= talloc_asprintf(ctx
,
995 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
996 if (!NT_STATUS_IS_OK(nt_status
)) {
1001 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1003 create_directory(conn
, NULL
, smb_dname
);
1005 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1006 * listed for this driver which has already been moved, skip it (note:
1007 * drivers may list the same file name several times. Then check if the
1008 * file already exists in archi\version\, if so, check that the version
1009 * info (or time stamps if version info is unavailable) is newer (or the
1010 * date is later). If it is, move it to archi\version\filexxx.yyy.
1011 * Otherwise, delete the file.
1013 * If a file is not moved to archi\version\ because of an error, all the
1014 * rest of the 'unmoved' driver files are removed from archi\. If one or
1015 * more of the driver's files was already moved to archi\version\, it
1016 * potentially leaves the driver in a partially updated state. Version
1017 * trauma will most likely occur if an client attempts to use any printer
1018 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1019 * done is appropriate... later JRR
1022 DEBUG(5,("Moving files now !\n"));
1024 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1026 *perr
= move_driver_file_to_download_area(ctx
,
1028 driver
->driver_path
,
1032 if (!W_ERROR_IS_OK(*perr
)) {
1033 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1040 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1041 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1043 *perr
= move_driver_file_to_download_area(ctx
,
1049 if (!W_ERROR_IS_OK(*perr
)) {
1050 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1058 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1059 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1060 !strequal(driver
->config_file
, driver
->data_file
)) {
1062 *perr
= move_driver_file_to_download_area(ctx
,
1064 driver
->config_file
,
1068 if (!W_ERROR_IS_OK(*perr
)) {
1069 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1077 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1078 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1079 !strequal(driver
->help_file
, driver
->data_file
) &&
1080 !strequal(driver
->help_file
, driver
->config_file
)) {
1082 *perr
= move_driver_file_to_download_area(ctx
,
1088 if (!W_ERROR_IS_OK(*perr
)) {
1089 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1097 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1098 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1099 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1100 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1101 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1102 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1104 for (j
=0; j
< i
; j
++) {
1105 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
1110 *perr
= move_driver_file_to_download_area(ctx
,
1112 driver
->dependent_files
->string
[i
],
1116 if (!W_ERROR_IS_OK(*perr
)) {
1117 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1128 TALLOC_FREE(smb_dname
);
1131 vfs_ChDir(conn
, oldcwd
);
1135 if (W_ERROR_EQUAL(*perr
, WERR_OK
)) {
1139 return WERR_UNKNOWN_PRINTER_DRIVER
;
1144 /****************************************************************************
1145 Create and allocate a default devicemode.
1146 ****************************************************************************/
1148 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
1149 const char *devicename
,
1150 struct spoolss_DeviceMode
**devmode
)
1152 struct spoolss_DeviceMode
*dm
;
1155 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
1160 dname
= talloc_asprintf(dm
, "%s", devicename
);
1161 if (dname
== NULL
) {
1164 if (strlen(dname
) > MAXDEVICENAME
) {
1165 dname
[MAXDEVICENAME
] = '\0';
1167 dm
->devicename
= dname
;
1169 dm
->formname
= talloc_strdup(dm
, "Letter");
1170 if (dm
->formname
== NULL
) {
1174 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
1175 dm
->driverversion
= 0x0400;
1177 dm
->__driverextra_length
= 0;
1178 dm
->fields
= DEVMODE_FORMNAME
|
1180 DEVMODE_PRINTQUALITY
|
1181 DEVMODE_DEFAULTSOURCE
|
1185 DEVMODE_ORIENTATION
;
1186 dm
->orientation
= DMORIENT_PORTRAIT
;
1187 dm
->papersize
= DMPAPER_LETTER
;
1188 dm
->paperlength
= 0;
1192 dm
->defaultsource
= DMBIN_FORMSOURCE
;
1193 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
1194 dm
->color
= DMRES_MONOCHROME
;
1195 dm
->duplex
= DMDUP_SIMPLEX
;
1196 dm
->yresolution
= 0;
1197 dm
->ttoption
= DMTT_SUBDEV
;
1198 dm
->collate
= DMCOLLATE_FALSE
;
1208 dm
->displayflags
= 0;
1209 dm
->displayfrequency
= 0;
1212 dm
->panningwidth
= 0;
1213 dm
->panningheight
= 0;
1215 dm
->driverextra_data
.data
= NULL
;
1216 dm
->driverextra_data
.length
= 0;
1222 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
1223 struct spoolss_security_descriptor
**secdesc
)
1225 struct security_ace ace
[7]; /* max number of ace entries */
1228 struct security_acl
*psa
= NULL
;
1229 struct security_descriptor
*psd
= NULL
;
1230 struct dom_sid adm_sid
;
1233 /* Create an ACE where Everyone is allowed to print */
1235 sa
= PRINTER_ACE_PRINT
;
1236 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1237 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1239 /* Add the domain admins group if we are a DC */
1242 struct dom_sid domadmins_sid
;
1244 sid_compose(&domadmins_sid
, get_global_sam_sid(),
1247 sa
= PRINTER_ACE_FULL_CONTROL
;
1248 init_sec_ace(&ace
[i
++], &domadmins_sid
,
1249 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1250 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1251 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1252 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1254 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
1255 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
1257 sa
= PRINTER_ACE_FULL_CONTROL
;
1258 init_sec_ace(&ace
[i
++], &adm_sid
,
1259 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1260 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1261 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
1262 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1265 /* add BUILTIN\Administrators as FULL CONTROL */
1267 sa
= PRINTER_ACE_FULL_CONTROL
;
1268 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1269 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1270 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1271 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
1272 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1273 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1275 /* add BUILTIN\Print Operators as FULL CONTROL */
1277 sa
= PRINTER_ACE_FULL_CONTROL
;
1278 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1279 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
1280 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
1281 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
1282 SEC_ACE_TYPE_ACCESS_ALLOWED
,
1283 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
1285 /* Make the security descriptor owned by the BUILTIN\Administrators */
1287 /* The ACL revision number in rpc_secdesc.h differs from the one
1288 created by NT when setting ACE entries in printer
1289 descriptors. NT4 complains about the property being edited by a
1292 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
1293 psd
= make_sec_desc(mem_ctx
,
1295 SEC_DESC_SELF_RELATIVE
,
1296 &global_sid_Builtin_Administrators
,
1297 &global_sid_Builtin_Administrators
,
1304 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1308 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1309 (unsigned int)sd_size
));
1317 /*****************************************************************
1318 ****************************************************************/
1320 static void store_printer_guid(const char *printer
, struct GUID guid
)
1322 TALLOC_CTX
*tmp_ctx
;
1323 struct auth_serversupplied_info
*server_info
= NULL
;
1324 const char *guid_str
;
1329 tmp_ctx
= talloc_new(NULL
);
1331 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1335 status
= make_server_info_system(tmp_ctx
, &server_info
);
1336 if (!NT_STATUS_IS_OK(status
)) {
1337 DEBUG(0, ("store_printer_guid: "
1338 "Could not create system server_info\n"));
1342 guid_str
= GUID_string(tmp_ctx
, &guid
);
1344 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1348 /* We used to store this as a REG_BINARY but that causes
1351 if (!push_reg_sz(tmp_ctx
, &blob
, guid_str
)) {
1352 DEBUG(0, ("store_printer_guid: "
1353 "Could not marshall string %s for objectGUID\n",
1358 result
= winreg_set_printer_dataex(tmp_ctx
, server_info
, printer
,
1359 SPOOL_DSSPOOLER_KEY
, "objectGUID",
1360 REG_SZ
, blob
.data
, blob
.length
);
1361 if (!W_ERROR_IS_OK(result
)) {
1362 DEBUG(0, ("store_printer_guid: "
1363 "Failed to store GUID for printer %s\n", printer
));
1367 talloc_free(tmp_ctx
);
1370 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
1371 struct spoolss_PrinterInfo2
*pinfo2
)
1375 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
, *srv_cn_escaped
, *sharename_escaped
;
1376 char *srv_dn_utf8
, **srv_cn_utf8
;
1379 const char *attrs
[] = {"objectGUID", NULL
};
1381 WERROR win_rc
= WERR_OK
;
1382 size_t converted_size
;
1383 const char *printer
= pinfo2
->sharename
;
1385 /* build the ads mods */
1386 ctx
= talloc_init("nt_printer_publish_ads");
1391 DEBUG(5, ("publishing printer %s\n", printer
));
1393 /* figure out where to publish */
1394 ads_find_machine_acct(ads
, &res
, global_myname());
1396 /* We use ldap_get_dn here as we need the answer
1397 * in utf8 to call ldap_explode_dn(). JRA. */
1399 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
1402 return WERR_SERVER_UNAVAILABLE
;
1404 ads_msgfree(ads
, res
);
1405 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
1408 ldap_memfree(srv_dn_utf8
);
1409 return WERR_SERVER_UNAVAILABLE
;
1411 /* Now convert to CH_UNIX. */
1412 if (!pull_utf8_talloc(ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
)) {
1414 ldap_memfree(srv_dn_utf8
);
1415 ldap_memfree(srv_cn_utf8
);
1416 return WERR_SERVER_UNAVAILABLE
;
1418 if (!pull_utf8_talloc(ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
)) {
1420 ldap_memfree(srv_dn_utf8
);
1421 ldap_memfree(srv_cn_utf8
);
1422 TALLOC_FREE(srv_dn
);
1423 return WERR_SERVER_UNAVAILABLE
;
1426 ldap_memfree(srv_dn_utf8
);
1427 ldap_memfree(srv_cn_utf8
);
1429 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
1430 if (!srv_cn_escaped
) {
1432 return WERR_SERVER_UNAVAILABLE
;
1434 sharename_escaped
= escape_rdn_val_string_alloc(printer
);
1435 if (!sharename_escaped
) {
1436 SAFE_FREE(srv_cn_escaped
);
1438 return WERR_SERVER_UNAVAILABLE
;
1441 prt_dn
= talloc_asprintf(ctx
, "cn=%s-%s,%s", srv_cn_escaped
, sharename_escaped
, srv_dn
);
1443 SAFE_FREE(srv_cn_escaped
);
1444 SAFE_FREE(sharename_escaped
);
1446 mods
= ads_init_mods(ctx
);
1454 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
, printer
);
1457 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
1458 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
1460 for (i
=0; mods
[i
] != 0; i
++)
1462 mods
[i
] = (LDAPMod
*)-1;
1463 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
1466 if (!ADS_ERR_OK(ads_rc
)) {
1467 DEBUG(3, ("error publishing %s: %s\n",
1468 printer
, ads_errstr(ads_rc
)));
1471 /* retreive the guid and store it locally */
1472 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
1474 ads_pull_guid(ads
, res
, &guid
);
1475 ads_msgfree(ads
, res
);
1476 store_printer_guid(printer
, guid
);
1483 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
1484 const char *printer
)
1487 LDAPMessage
*res
= NULL
;
1488 char *prt_dn
= NULL
;
1490 DEBUG(5, ("unpublishing printer %s\n", printer
));
1492 /* remove the printer from the directory */
1493 ads_rc
= ads_find_printer_on_server(ads
, &res
,
1494 printer
, global_myname());
1496 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
1497 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
1499 ads_msgfree(ads
, res
);
1502 ads_rc
= ads_del_dn(ads
, prt_dn
);
1503 TALLOC_FREE(prt_dn
);
1507 ads_msgfree(ads
, res
);
1512 /****************************************************************************
1513 * Publish a printer in the directory
1515 * @param mem_ctx memory context
1516 * @param server_info server_info to access winreg pipe
1517 * @param pinfo2 printer information
1518 * @param action publish/unpublish action
1519 * @return WERROR indicating status of publishing
1520 ***************************************************************************/
1522 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
1523 struct auth_serversupplied_info
*server_info
,
1524 struct spoolss_PrinterInfo2
*pinfo2
,
1527 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ATTRIBUTES
;
1528 struct spoolss_SetPrinterInfo2
*sinfo2
;
1530 ADS_STRUCT
*ads
= NULL
;
1533 sinfo2
= talloc_zero(mem_ctx
, struct spoolss_SetPrinterInfo2
);
1539 case DSPRINT_PUBLISH
:
1540 case DSPRINT_UPDATE
:
1541 pinfo2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
1543 case DSPRINT_UNPUBLISH
:
1544 pinfo2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
1547 win_rc
= WERR_NOT_SUPPORTED
;
1551 sinfo2
->attributes
= pinfo2
->attributes
;
1553 win_rc
= winreg_update_printer(mem_ctx
, server_info
,
1554 pinfo2
->sharename
, info2_mask
,
1555 sinfo2
, NULL
, NULL
);
1556 if (!W_ERROR_IS_OK(win_rc
)) {
1557 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
1561 TALLOC_FREE(sinfo2
);
1563 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
1565 DEBUG(3, ("ads_init() failed\n"));
1566 win_rc
= WERR_SERVER_UNAVAILABLE
;
1569 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
1570 SAFE_FREE(ads
->auth
.password
);
1571 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
1574 /* ads_connect() will find the DC for us */
1575 ads_rc
= ads_connect(ads
);
1576 if (!ADS_ERR_OK(ads_rc
)) {
1577 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
1578 win_rc
= WERR_ACCESS_DENIED
;
1583 case DSPRINT_PUBLISH
:
1584 case DSPRINT_UPDATE
:
1585 win_rc
= nt_printer_publish_ads(ads
, pinfo2
);
1587 case DSPRINT_UNPUBLISH
:
1588 win_rc
= nt_printer_unpublish_ads(ads
, pinfo2
->sharename
);
1597 WERROR
check_published_printers(void)
1600 ADS_STRUCT
*ads
= NULL
;
1602 int n_services
= lp_numservices();
1603 TALLOC_CTX
*tmp_ctx
= NULL
;
1604 struct auth_serversupplied_info
*server_info
= NULL
;
1605 struct spoolss_PrinterInfo2
*pinfo2
;
1609 tmp_ctx
= talloc_new(NULL
);
1610 if (!tmp_ctx
) return WERR_NOMEM
;
1612 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
1614 DEBUG(3, ("ads_init() failed\n"));
1615 return WERR_SERVER_UNAVAILABLE
;
1617 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
1618 SAFE_FREE(ads
->auth
.password
);
1619 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
1622 /* ads_connect() will find the DC for us */
1623 ads_rc
= ads_connect(ads
);
1624 if (!ADS_ERR_OK(ads_rc
)) {
1625 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
1626 result
= WERR_ACCESS_DENIED
;
1630 status
= make_server_info_system(tmp_ctx
, &server_info
);
1631 if (!NT_STATUS_IS_OK(status
)) {
1632 DEBUG(0, ("check_published_printers: "
1633 "Could not create system server_info\n"));
1634 result
= WERR_ACCESS_DENIED
;
1638 for (snum
= 0; snum
< n_services
; snum
++) {
1639 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1643 result
= winreg_get_printer(tmp_ctx
, server_info
, NULL
,
1644 lp_servicename(snum
), &pinfo2
);
1645 if (!W_ERROR_IS_OK(result
)) {
1649 if (pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
1650 nt_printer_publish_ads(ads
, pinfo2
);
1653 TALLOC_FREE(pinfo2
);
1659 ads_kdestroy("MEMORY:prtpub_cache");
1660 talloc_free(tmp_ctx
);
1664 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
1665 struct auth_serversupplied_info
*server_info
,
1666 char *servername
, char *printer
, struct GUID
*guid
,
1667 struct spoolss_PrinterInfo2
**info2
)
1669 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
1670 enum winreg_Type type
;
1676 result
= winreg_get_printer(mem_ctx
, server_info
,
1677 servername
, printer
, &pinfo2
);
1678 if (!W_ERROR_IS_OK(result
)) {
1682 if (!(pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
)) {
1683 TALLOC_FREE(pinfo2
);
1691 /* fetching printer guids really ought to be a separate function. */
1693 result
= winreg_get_printer_dataex(mem_ctx
, server_info
, printer
,
1694 SPOOL_DSSPOOLER_KEY
, "objectGUID",
1695 &type
, &data
, &data_size
);
1696 if (!W_ERROR_IS_OK(result
)) {
1697 TALLOC_FREE(pinfo2
);
1701 /* We used to store the guid as REG_BINARY, then swapped
1702 to REG_SZ for Vista compatibility so check for both */
1706 status
= GUID_from_string((char *)data
, guid
);
1707 if (!NT_STATUS_IS_OK(status
)) {
1708 TALLOC_FREE(pinfo2
);
1714 if (data_size
!= sizeof(struct GUID
)) {
1715 TALLOC_FREE(pinfo2
);
1718 memcpy(guid
, data
, sizeof(struct GUID
));
1721 DEBUG(0,("is_printer_published: GUID value stored as "
1722 "invaluid type (%d)\n", type
));
1728 *info2
= talloc_move(mem_ctx
, &pinfo2
);
1730 talloc_free(pinfo2
);
1734 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
1735 struct auth_serversupplied_info
*server_info
,
1736 struct spoolss_PrinterInfo2
*pinfo2
,
1742 WERROR
check_published_printers(void)
1747 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
1748 struct auth_serversupplied_info
*server_info
,
1749 char *servername
, char *printer
, struct GUID
*guid
,
1750 struct spoolss_PrinterInfo2
**info2
)
1754 #endif /* HAVE_ADS */
1756 /****************************************************************************
1757 ***************************************************************************/
1759 static char *win_driver
;
1760 static char *os2_driver
;
1762 static const char *get_win_driver(void)
1764 if (win_driver
== NULL
) {
1770 static const char *get_os2_driver(void)
1772 if (os2_driver
== NULL
) {
1778 static bool set_driver_mapping(const char *from
, const char *to
)
1780 SAFE_FREE(win_driver
);
1781 SAFE_FREE(os2_driver
);
1783 win_driver
= SMB_STRDUP(from
);
1784 os2_driver
= SMB_STRDUP(to
);
1786 if (win_driver
== NULL
|| os2_driver
== NULL
) {
1787 SAFE_FREE(win_driver
);
1788 SAFE_FREE(os2_driver
);
1797 * @brief Map a Windows driver to a OS/2 driver.
1799 * @param[in] mem_ctx The memory context to use.
1801 * @param[in,out] pdrivername The drivername of Windows to remap.
1803 * @return WERR_OK on success, a corresponding WERROR on failure.
1805 WERROR
spoolss_map_to_os2_driver(TALLOC_CTX
*mem_ctx
, const char **pdrivername
)
1807 const char *mapfile
= lp_os2_driver_map();
1808 char **lines
= NULL
;
1809 const char *drivername
;
1813 if (pdrivername
== NULL
|| *pdrivername
== NULL
|| *pdrivername
[0] == '\0') {
1814 return WERR_INVALID_PARAMETER
;
1817 drivername
= *pdrivername
;
1819 if (mapfile
[0] == '\0') {
1820 return WERR_BADFILE
;
1823 if (strequal(drivername
, get_win_driver())) {
1824 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1825 drivername
, get_os2_driver()));
1826 drivername
= talloc_strdup(mem_ctx
, get_os2_driver());
1827 if (drivername
== NULL
) {
1830 *pdrivername
= drivername
;
1834 lines
= file_lines_load(mapfile
, &numlines
, 0, NULL
);
1835 if (numlines
== 0 || lines
== NULL
) {
1836 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile
));
1841 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
1843 for( i
= 0; i
< numlines
; i
++) {
1844 char *nt_name
= lines
[i
];
1845 char *os2_name
= strchr(nt_name
, '=');
1847 if (os2_name
== NULL
) {
1853 while (isspace(*nt_name
)) {
1857 if (*nt_name
== '\0' || strchr("#;", *nt_name
)) {
1862 int l
= strlen(nt_name
);
1863 while (l
&& isspace(nt_name
[l
- 1])) {
1869 while (isspace(*os2_name
)) {
1874 int l
= strlen(os2_name
);
1875 while (l
&& isspace(os2_name
[l
-1])) {
1881 if (strequal(nt_name
, drivername
)) {
1882 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,os2_name
));
1883 set_driver_mapping(drivername
, os2_name
);
1884 drivername
= talloc_strdup(mem_ctx
, os2_name
);
1886 if (drivername
== NULL
) {
1889 *pdrivername
= drivername
;
1898 /****************************************************************************
1899 ****************************************************************************/
1901 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
1902 struct spoolss_DriverInfo8
*_info8
)
1904 struct spoolss_DriverInfo8 info8
;
1910 info8
.version
= r
->info
.info3
->version
;
1911 info8
.driver_name
= r
->info
.info3
->driver_name
;
1912 info8
.architecture
= r
->info
.info3
->architecture
;
1913 info8
.driver_path
= r
->info
.info3
->driver_path
;
1914 info8
.data_file
= r
->info
.info3
->data_file
;
1915 info8
.config_file
= r
->info
.info3
->config_file
;
1916 info8
.help_file
= r
->info
.info3
->help_file
;
1917 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
1918 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
1919 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
1920 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
1924 info8
.version
= r
->info
.info6
->version
;
1925 info8
.driver_name
= r
->info
.info6
->driver_name
;
1926 info8
.architecture
= r
->info
.info6
->architecture
;
1927 info8
.driver_path
= r
->info
.info6
->driver_path
;
1928 info8
.data_file
= r
->info
.info6
->data_file
;
1929 info8
.config_file
= r
->info
.info6
->config_file
;
1930 info8
.help_file
= r
->info
.info6
->help_file
;
1931 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
1932 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
1933 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
1934 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
1936 info8
.driver_date
= r
->info
.info6
->driver_date
;
1937 info8
.driver_version
= r
->info
.info6
->driver_version
;
1938 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
1939 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
1940 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
1941 info8
.provider
= r
->info
.info6
->provider
;
1944 info8
.version
= r
->info
.info8
->version
;
1945 info8
.driver_name
= r
->info
.info8
->driver_name
;
1946 info8
.architecture
= r
->info
.info8
->architecture
;
1947 info8
.driver_path
= r
->info
.info8
->driver_path
;
1948 info8
.data_file
= r
->info
.info8
->data_file
;
1949 info8
.config_file
= r
->info
.info8
->config_file
;
1950 info8
.help_file
= r
->info
.info8
->help_file
;
1951 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
1952 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
1953 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
1954 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
1956 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
1957 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
1959 info8
.driver_date
= r
->info
.info8
->driver_date
;
1960 info8
.driver_version
= r
->info
.info8
->driver_version
;
1961 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
1962 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
1963 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
1964 info8
.provider
= r
->info
.info8
->provider
;
1965 info8
.print_processor
= r
->info
.info8
->print_processor
;
1966 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
1967 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
1968 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
1970 info8
.inf_path
= r
->info
.info8
->inf_path
;
1971 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
1972 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
1973 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
1975 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
1976 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
1988 /****************************************************************************
1989 Determine whether or not a particular driver is currently assigned
1991 ****************************************************************************/
1993 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
1994 struct auth_serversupplied_info
*server_info
,
1995 const struct spoolss_DriverInfo8
*r
)
1998 int n_services
= lp_numservices();
1999 bool in_use
= False
;
2000 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2007 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
2009 /* loop through the printers.tdb and check for the drivername */
2011 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
2012 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
2016 result
= winreg_get_printer(mem_ctx
, server_info
, NULL
,
2017 lp_servicename(snum
), &pinfo2
);
2018 if (!W_ERROR_IS_OK(result
)) {
2019 continue; /* skip */
2022 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
2026 TALLOC_FREE(pinfo2
);
2029 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
2032 struct spoolss_DriverInfo8
*driver
;
2035 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
2037 /* we can still remove the driver if there is one of
2038 "Windows NT x86" version 2 or 3 left */
2040 if (!strequal("Windows NT x86", r
->architecture
)) {
2041 werr
= winreg_get_driver(mem_ctx
, server_info
,
2046 } else if (r
->version
== 2) {
2047 werr
= winreg_get_driver(mem_ctx
, server_info
,
2051 } else if (r
->version
== 3) {
2052 werr
= winreg_get_driver(mem_ctx
, server_info
,
2057 DEBUG(0, ("printer_driver_in_use: ERROR!"
2058 " unknown driver version (%d)\n",
2060 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
2063 /* now check the error code */
2065 if ( W_ERROR_IS_OK(werr
) ) {
2066 /* it's ok to remove the driver, we have other architctures left */
2068 talloc_free(driver
);
2072 /* report that the driver is not in use by default */
2078 /**********************************************************************
2079 Check to see if a ogiven file is in use by *info
2080 *********************************************************************/
2082 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
2089 /* mz: skip files that are in the list but already deleted */
2090 if (!file
|| !file
[0]) {
2094 if (strequal(file
, info
->driver_path
))
2097 if (strequal(file
, info
->data_file
))
2100 if (strequal(file
, info
->config_file
))
2103 if (strequal(file
, info
->help_file
))
2106 /* see of there are any dependent files to examine */
2108 if (!info
->dependent_files
)
2111 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
2112 if (strequal(file
, info
->dependent_files
[i
]))
2121 /**********************************************************************
2122 Utility function to remove the dependent file pointed to by the
2123 input parameter from the list
2124 *********************************************************************/
2126 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
2129 /* bump everything down a slot */
2131 while (files
&& files
[idx
+1]) {
2132 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
2141 /**********************************************************************
2142 Check if any of the files used by src are also used by drv
2143 *********************************************************************/
2145 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
2146 struct spoolss_DriverInfo8
*src
,
2147 const struct spoolss_DriverInfo8
*drv
)
2149 bool in_use
= False
;
2155 /* check each file. Remove it from the src structure if it overlaps */
2157 if (drv_file_in_use(src
->driver_path
, drv
)) {
2159 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
2160 src
->driver_path
= talloc_strdup(mem_ctx
, "");
2161 if (!src
->driver_path
) { return false; }
2164 if (drv_file_in_use(src
->data_file
, drv
)) {
2166 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
2167 src
->data_file
= talloc_strdup(mem_ctx
, "");
2168 if (!src
->data_file
) { return false; }
2171 if (drv_file_in_use(src
->config_file
, drv
)) {
2173 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
2174 src
->config_file
= talloc_strdup(mem_ctx
, "");
2175 if (!src
->config_file
) { return false; }
2178 if (drv_file_in_use(src
->help_file
, drv
)) {
2180 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
2181 src
->help_file
= talloc_strdup(mem_ctx
, "");
2182 if (!src
->help_file
) { return false; }
2185 /* are there any dependentfiles to examine? */
2187 if (!src
->dependent_files
)
2190 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
2191 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
2193 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
2194 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
2202 /****************************************************************************
2203 Determine whether or not a particular driver files are currently being
2204 used by any other driver.
2206 Return value is True if any files were in use by other drivers
2207 and False otherwise.
2209 Upon return, *info has been modified to only contain the driver files
2210 which are not in use
2214 This needs to check all drivers to ensure that all files in use
2215 have been removed from *info, not just the ones in the first
2217 ****************************************************************************/
2219 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
2220 struct auth_serversupplied_info
*server_info
,
2221 struct spoolss_DriverInfo8
*info
)
2225 struct spoolss_DriverInfo8
*driver
;
2226 bool in_use
= false;
2227 uint32_t num_drivers
;
2228 const char **drivers
;
2234 version
= info
->version
;
2236 /* loop over all driver versions */
2238 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
2240 /* get the list of drivers */
2242 result
= winreg_get_driver_list(mem_ctx
, server_info
,
2243 info
->architecture
, version
,
2244 &num_drivers
, &drivers
);
2245 if (!W_ERROR_IS_OK(result
)) {
2249 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
2250 num_drivers
, info
->architecture
, version
));
2252 /* check each driver for overlap in files */
2254 for (i
= 0; i
< num_drivers
; i
++) {
2255 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
2259 result
= winreg_get_driver(mem_ctx
, server_info
,
2260 info
->architecture
, drivers
[i
],
2262 if (!W_ERROR_IS_OK(result
)) {
2263 talloc_free(drivers
);
2267 /* check if d2 uses any files from d1 */
2268 /* only if this is a different driver than the one being deleted */
2270 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
2271 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
2272 /* mz: Do not instantly return -
2273 * we need to ensure this file isn't
2274 * also in use by other drivers. */
2279 talloc_free(driver
);
2282 talloc_free(drivers
);
2284 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2289 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
2292 struct smb_filename
*smb_fname
= NULL
;
2295 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
2297 if (!NT_STATUS_IS_OK(status
)) {
2301 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
2303 TALLOC_FREE(smb_fname
);
2307 /****************************************************************************
2308 Actually delete the driver files. Make sure that
2309 printer_driver_files_in_use() return False before calling
2311 ****************************************************************************/
2313 bool delete_driver_files(struct auth_serversupplied_info
*server_info
,
2314 const struct spoolss_DriverInfo8
*r
)
2319 connection_struct
*conn
;
2322 fstring printdollar
;
2323 int printdollar_snum
;
2330 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2331 r
->driver_name
, r
->version
));
2333 fstrcpy(printdollar
, "print$");
2335 printdollar_snum
= find_service(printdollar
);
2336 if (printdollar_snum
== -1) {
2340 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
2341 lp_pathname(printdollar_snum
),
2342 server_info
, &oldcwd
);
2343 if (!NT_STATUS_IS_OK(nt_status
)) {
2344 DEBUG(0,("delete_driver_files: create_conn_struct "
2345 "returned %s\n", nt_errstr(nt_status
)));
2349 if ( !CAN_WRITE(conn
) ) {
2350 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2354 /* now delete the files; must strip the '\print$' string from
2357 if (r
->driver_path
&& r
->driver_path
[0]) {
2358 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
2360 DEBUG(10,("deleting driverfile [%s]\n", s
));
2361 driver_unlink_internals(conn
, file
);
2365 if (r
->config_file
&& r
->config_file
[0]) {
2366 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
2368 DEBUG(10,("deleting configfile [%s]\n", s
));
2369 driver_unlink_internals(conn
, file
);
2373 if (r
->data_file
&& r
->data_file
[0]) {
2374 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
2376 DEBUG(10,("deleting datafile [%s]\n", s
));
2377 driver_unlink_internals(conn
, file
);
2381 if (r
->help_file
&& r
->help_file
[0]) {
2382 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
2384 DEBUG(10,("deleting helpfile [%s]\n", s
));
2385 driver_unlink_internals(conn
, file
);
2389 /* check if we are done removing files */
2391 if (r
->dependent_files
) {
2392 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
2395 /* bypass the "\print$" portion of the path */
2397 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
2399 DEBUG(10,("deleting dependent file [%s]\n", file
));
2400 driver_unlink_internals(conn
, file
);
2412 vfs_ChDir(conn
, oldcwd
);
2420 1: level not implemented
2421 2: file doesn't exist
2422 3: can't allocate memory
2423 4: can't free memory
2424 5: non existant struct
2428 A printer and a printer driver are 2 different things.
2429 NT manages them separatelly, Samba does the same.
2430 Why ? Simply because it's easier and it makes sense !
2432 Now explanation: You have 3 printers behind your samba server,
2433 2 of them are the same make and model (laser A and B). But laser B
2434 has an 3000 sheet feeder and laser A doesn't such an option.
2435 Your third printer is an old dot-matrix model for the accounting :-).
2437 If the /usr/local/samba/lib directory (default dir), you will have
2438 5 files to describe all of this.
2440 3 files for the printers (1 by printer):
2443 NTprinter_accounting
2444 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2445 NTdriver_printer model X
2446 NTdriver_printer model Y
2448 jfm: I should use this comment for the text file to explain
2449 same thing for the forms BTW.
2450 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2454 /* Convert generic access rights to printer object specific access rights.
2455 It turns out that NT4 security descriptors use generic access rights and
2456 NT5 the object specific ones. */
2458 void map_printer_permissions(struct security_descriptor
*sd
)
2462 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2463 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2464 &printer_generic_mapping
);
2468 void map_job_permissions(struct security_descriptor
*sd
)
2472 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
2473 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
2474 &job_generic_mapping
);
2479 /****************************************************************************
2480 Check a user has permissions to perform the given operation. We use the
2481 permission constants defined in include/rpc_spoolss.h to check the various
2482 actions we perform when checking printer access.
2484 PRINTER_ACCESS_ADMINISTER:
2485 print_queue_pause, print_queue_resume, update_printer_sec,
2486 update_printer, spoolss_addprinterex_level_2,
2487 _spoolss_setprinterdata
2492 JOB_ACCESS_ADMINISTER:
2493 print_job_delete, print_job_pause, print_job_resume,
2496 Try access control in the following order (for performance reasons):
2497 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2498 2) check security descriptor (bit comparisons in memory)
2499 3) "printer admins" (may result in numerous calls to winbind)
2501 ****************************************************************************/
2502 bool print_access_check(struct auth_serversupplied_info
*server_info
, int snum
,
2505 struct spoolss_security_descriptor
*secdesc
= NULL
;
2506 uint32 access_granted
;
2511 TALLOC_CTX
*mem_ctx
= NULL
;
2512 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2514 /* If user is NULL then use the current_user structure */
2516 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2518 if (server_info
->utok
.uid
== sec_initial_uid()
2519 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
2523 /* Get printer name */
2525 pname
= lp_printername(snum
);
2527 if (!pname
|| !*pname
) {
2532 /* Get printer security descriptor */
2534 if(!(mem_ctx
= talloc_init("print_access_check"))) {
2539 result
= winreg_get_printer_secdesc(mem_ctx
,
2543 if (!W_ERROR_IS_OK(result
)) {
2544 talloc_destroy(mem_ctx
);
2549 if (access_type
== JOB_ACCESS_ADMINISTER
) {
2550 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
2552 /* Create a child security descriptor to check permissions
2553 against. This is because print jobs are child objects
2554 objects of a printer. */
2555 status
= se_create_child_secdesc(mem_ctx
,
2559 parent_secdesc
->owner_sid
,
2560 parent_secdesc
->group_sid
,
2562 if (!NT_STATUS_IS_OK(status
)) {
2563 talloc_destroy(mem_ctx
);
2564 errno
= map_errno_from_nt_status(status
);
2568 map_job_permissions(secdesc
);
2570 map_printer_permissions(secdesc
);
2574 status
= se_access_check(secdesc
, server_info
->ptok
, access_type
,
2577 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
2579 /* see if we need to try the printer admin list */
2581 if (!NT_STATUS_IS_OK(status
) &&
2582 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
2583 server_info
->info3
->base
.domain
.string
,
2584 NULL
, server_info
->ptok
,
2585 lp_printer_admin(snum
)))) {
2586 talloc_destroy(mem_ctx
);
2590 talloc_destroy(mem_ctx
);
2592 if (!NT_STATUS_IS_OK(status
)) {
2596 return NT_STATUS_IS_OK(status
);
2599 /****************************************************************************
2600 Check the time parameters allow a print operation.
2601 *****************************************************************************/
2603 bool print_time_access_check(struct auth_serversupplied_info
*server_info
,
2604 const char *servicename
)
2606 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2609 time_t now
= time(NULL
);
2613 result
= winreg_get_printer(NULL
, server_info
,
2614 NULL
, servicename
, &pinfo2
);
2615 if (!W_ERROR_IS_OK(result
)) {
2619 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
2624 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
2626 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
2630 TALLOC_FREE(pinfo2
);
2639 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
2640 struct auth_serversupplied_info
*server_info
,
2641 const char *printer
)
2645 result
= winreg_delete_printer_key(mem_ctx
, server_info
, printer
, "");
2646 if (!W_ERROR_IS_OK(result
)) {
2647 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",