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 "rpc_server/srv_spoolss_util.h"
32 #include "../rpc_server/srv_spoolss_util.h"
34 /* Map generic permissions to printer object specific permissions */
36 const struct generic_mapping printer_generic_mapping = {
43 /* Map generic permissions to print server object specific permissions */
45 const struct generic_mapping printserver_generic_mapping = {
52 /* Map generic permissions to job object specific permissions */
54 const struct generic_mapping job_generic_mapping = {
61 static const struct print_architecture_table_node archi_table[]= {
63 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
64 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
65 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
66 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
67 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
68 {"Windows IA64", SPL_ARCH_IA64, 3 },
69 {"Windows x64", SPL_ARCH_X64, 3 },
73 /****************************************************************************
74 Open the NT printing tdbs. Done once before fork().
75 ****************************************************************************/
77 bool nt_printing_init(struct messaging_context *msg_ctx)
81 if (!nt_printing_tdb_upgrade()) {
86 * register callback to handle updating printers as new
87 * drivers are installed
89 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
90 do_drv_upgrade_printer);
92 /* of course, none of the message callbacks matter if you don't
93 tell messages.c that you interested in receiving PRINT_GENERAL
94 msgs. This is done in serverid_register() */
96 if ( lp_security() == SEC_ADS ) {
97 win_rc = check_published_printers();
98 if (!W_ERROR_IS_OK(win_rc))
99 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
105 /*******************************************************************
106 Function to allow filename parsing "the old way".
107 ********************************************************************/
109 static NTSTATUS driver_unix_convert(connection_struct *conn,
110 const char *old_name,
111 struct smb_filename **smb_fname)
114 TALLOC_CTX *ctx = talloc_tos();
115 char *name = talloc_strdup(ctx, old_name);
118 return NT_STATUS_NO_MEMORY;
121 name = unix_clean_name(ctx, name);
123 return NT_STATUS_NO_MEMORY;
125 trim_string(name,"/","/");
127 status = unix_convert(ctx, conn, name, smb_fname, 0);
128 if (!NT_STATUS_IS_OK(status)) {
129 return NT_STATUS_NO_MEMORY;
135 /****************************************************************************
136 Function to do the mapping between the long architecture name and
138 ****************************************************************************/
140 const char *get_short_archi(const char *long_archi)
144 DEBUG(107,("Getting architecture dependant directory\n"));
147 } while ( (archi_table[i].long_archi!=NULL ) &&
148 StrCaseCmp(long_archi, archi_table[i].long_archi) );
150 if (archi_table[i].long_archi==NULL) {
151 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
155 /* this might be client code - but shouldn't this be an fstrcpy etc? */
157 DEBUGADD(108,("index: [%d]\n", i));
158 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
159 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
161 return archi_table[i].short_archi;
164 /****************************************************************************
165 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
166 There are two case to be covered here: PE (Portable Executable) and NE (New
167 Executable) files. Both files support the same INFO structure, but PE files
168 store the signature in unicode, and NE files store it as !unicode.
169 returns -1 on error, 1 on version info found, and 0 on no version info found.
170 ****************************************************************************/
172 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
178 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
179 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
180 fname, DOS_HEADER_SIZE));
184 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
185 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
186 fname, (unsigned long)byte_count));
187 goto no_version_info;
190 /* Is this really a DOS header? */
191 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
192 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
193 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
194 goto no_version_info;
197 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
198 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
199 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
201 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
202 goto no_version_info;
205 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
206 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
207 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
208 fname, (unsigned long)byte_count));
209 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
210 goto no_version_info;
213 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
214 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
215 unsigned int num_sections;
216 unsigned int section_table_bytes;
218 /* Just skip over optional header to get to section table */
219 if (SMB_VFS_LSEEK(fsp,
220 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
221 SEEK_CUR) == (SMB_OFF_T)-1) {
222 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
227 /* get the section table */
228 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
229 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
230 if (section_table_bytes == 0)
234 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
235 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
236 fname, section_table_bytes));
240 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
241 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
242 fname, (unsigned long)byte_count));
246 /* Iterate the section table looking for the resource section ".rsrc" */
247 for (i = 0; i < num_sections; i++) {
248 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
250 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
251 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
252 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
254 if (section_bytes == 0)
258 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
259 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
260 fname, section_bytes));
264 /* Seek to the start of the .rsrc section info */
265 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
266 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
271 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
272 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
273 fname, (unsigned long)byte_count));
277 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
280 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
281 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
282 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
283 /* Align to next long address */
284 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
286 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
287 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
288 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
290 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
291 fname, *major, *minor,
292 (*major>>16)&0xffff, *major&0xffff,
293 (*minor>>16)&0xffff, *minor&0xffff));
302 /* Version info not found, fall back to origin date/time */
303 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
307 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
308 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
309 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
310 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
311 /* At this point, we assume the file is in error. It still could be somthing
312 * else besides a NE file, but it unlikely at this point. */
316 /* Allocate a bit more space to speed up things */
318 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
319 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
320 fname, PE_HEADER_SIZE));
324 /* This is a HACK! I got tired of trying to sort through the messy
325 * 'NE' file format. If anyone wants to clean this up please have at
326 * it, but this works. 'NE' files will eventually fade away. JRR */
327 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
328 /* Cover case that should not occur in a well formed 'NE' .dll file */
329 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
331 for(i=0; i<byte_count; i++) {
332 /* Fast skip past data that can't possibly match */
333 if (buf[i] != 'V') continue;
335 /* Potential match data crosses buf boundry, move it to beginning
336 * of buf, and fill the buf with as much as it will hold. */
337 if (i>byte_count-VS_VERSION_INFO_SIZE) {
340 memcpy(buf, &buf[i], byte_count-i);
341 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
342 (byte_count-i))) < 0) {
344 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
349 byte_count = bc + (byte_count - i);
350 if (byte_count<VS_VERSION_INFO_SIZE) break;
355 /* Check that the full signature string and the magic number that
356 * follows exist (not a perfect solution, but the chances that this
357 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
358 * twice, as it is simpler to read the code. */
359 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
360 /* Compute skip alignment to next long address */
361 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
362 sizeof(VS_SIGNATURE)) & 3;
363 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
365 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
366 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
367 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
368 fname, *major, *minor,
369 (*major>>16)&0xffff, *major&0xffff,
370 (*minor>>16)&0xffff, *minor&0xffff));
377 /* Version info not found, fall back to origin date/time */
378 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
383 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
384 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
385 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
396 /****************************************************************************
397 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
398 share one or more files. During the MS installation process files are checked
399 to insure that only a newer version of a shared file is installed over an
400 older version. There are several possibilities for this comparison. If there
401 is no previous version, the new one is newer (obviously). If either file is
402 missing the version info structure, compare the creation date (on Unix use
403 the modification date). Otherwise chose the numerically larger version number.
404 ****************************************************************************/
406 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
408 bool use_version = true;
412 time_t new_create_time;
416 time_t old_create_time;
418 struct smb_filename *smb_fname = NULL;
419 files_struct *fsp = NULL;
425 SET_STAT_INVALID(st);
426 new_create_time = (time_t)0;
427 old_create_time = (time_t)0;
429 /* Get file version info (if available) for previous file (if it exists) */
430 status = driver_unix_convert(conn, old_file, &smb_fname);
431 if (!NT_STATUS_IS_OK(status)) {
435 status = SMB_VFS_CREATE_FILE(
438 0, /* root_dir_fid */
439 smb_fname, /* fname */
440 FILE_GENERIC_READ, /* access_mask */
441 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
442 FILE_OPEN, /* create_disposition*/
443 0, /* create_options */
444 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
445 INTERNAL_OPEN_ONLY, /* oplock_request */
446 0, /* allocation_size */
447 0, /* private_flags */
453 if (!NT_STATUS_IS_OK(status)) {
454 /* Old file not found, so by definition new file is in fact newer */
455 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
456 "errno = %d\n", smb_fname_str_dbg(smb_fname),
462 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
468 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
471 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
474 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
475 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
476 (long)old_create_time));
479 close_file(NULL, fsp, NORMAL_CLOSE);
482 /* Get file version info (if available) for new file */
483 status = driver_unix_convert(conn, new_file, &smb_fname);
484 if (!NT_STATUS_IS_OK(status)) {
488 status = SMB_VFS_CREATE_FILE(
491 0, /* root_dir_fid */
492 smb_fname, /* fname */
493 FILE_GENERIC_READ, /* access_mask */
494 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
495 FILE_OPEN, /* create_disposition*/
496 0, /* create_options */
497 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
498 INTERNAL_OPEN_ONLY, /* oplock_request */
499 0, /* allocation_size */
500 0, /* private_flags */
506 if (!NT_STATUS_IS_OK(status)) {
507 /* New file not found, this shouldn't occur if the caller did its job */
508 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
509 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
513 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
519 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
522 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
525 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
526 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
527 (long)new_create_time));
530 close_file(NULL, fsp, NORMAL_CLOSE);
533 if (use_version && (new_major != old_major || new_minor != old_minor)) {
534 /* Compare versions and choose the larger version number */
535 if (new_major > old_major ||
536 (new_major == old_major && new_minor > old_minor)) {
538 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
543 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
549 /* Compare modification time/dates and choose the newest time/date */
550 if (new_create_time > old_create_time) {
551 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
556 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
564 close_file(NULL, fsp, NORMAL_CLOSE);
567 TALLOC_FREE(smb_fname);
571 /****************************************************************************
572 Determine the correct cVersion associated with an architecture and driver
573 ****************************************************************************/
574 static uint32 get_correct_cversion(struct pipes_struct *p,
575 const char *architecture,
576 const char *driverpath_in,
581 struct smb_filename *smb_fname = NULL;
582 char *driverpath = NULL;
583 files_struct *fsp = NULL;
584 connection_struct *conn = NULL;
588 int printdollar_snum;
590 *perr = WERR_INVALID_PARAM;
592 /* If architecture is Windows 95/98/ME, the version is always 0. */
593 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
594 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
599 /* If architecture is Windows x64, the version is always 3. */
600 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
601 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
606 fstrcpy(printdollar, "print$");
608 printdollar_snum = find_service(printdollar);
609 if (printdollar_snum == -1) {
610 *perr = WERR_NO_SUCH_SHARE;
614 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
615 lp_pathname(printdollar_snum),
616 p->server_info, &oldcwd);
617 if (!NT_STATUS_IS_OK(nt_status)) {
618 DEBUG(0,("get_correct_cversion: create_conn_struct "
619 "returned %s\n", nt_errstr(nt_status)));
620 *perr = ntstatus_to_werror(nt_status);
624 /* Open the driver file (Portable Executable format) and determine the
625 * deriver the cversion. */
626 driverpath = talloc_asprintf(talloc_tos(),
635 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
636 if (!NT_STATUS_IS_OK(nt_status)) {
637 *perr = ntstatus_to_werror(nt_status);
641 nt_status = vfs_file_exist(conn, smb_fname);
642 if (!NT_STATUS_IS_OK(nt_status)) {
643 *perr = WERR_BADFILE;
647 status = SMB_VFS_CREATE_FILE(
650 0, /* root_dir_fid */
651 smb_fname, /* fname */
652 FILE_GENERIC_READ, /* access_mask */
653 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
654 FILE_OPEN, /* create_disposition*/
655 0, /* create_options */
656 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
657 INTERNAL_OPEN_ONLY, /* oplock_request */
658 0, /* private_flags */
659 0, /* allocation_size */
665 if (!NT_STATUS_IS_OK(status)) {
666 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
667 "%d\n", smb_fname_str_dbg(smb_fname), errno));
668 *perr = WERR_ACCESS_DENIED;
675 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
676 if (ret == -1) goto error_exit;
679 DEBUG(6,("get_correct_cversion: Version info not "
681 smb_fname_str_dbg(smb_fname)));
686 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
687 * for more details. Version in this case is not just the version of the
688 * file, but the version in the sense of kernal mode (2) vs. user mode
689 * (3) drivers. Other bits of the version fields are the version info.
692 cversion = major & 0x0000ffff;
694 case 2: /* WinNT drivers */
695 case 3: /* Win2K drivers */
699 DEBUG(6,("get_correct_cversion: cversion "
700 "invalid [%s] cversion = %d\n",
701 smb_fname_str_dbg(smb_fname),
706 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
707 " = 0x%x minor = 0x%x\n",
708 smb_fname_str_dbg(smb_fname), major, minor));
711 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
712 smb_fname_str_dbg(smb_fname), cversion));
719 TALLOC_FREE(smb_fname);
721 close_file(NULL, fsp, NORMAL_CLOSE);
724 vfs_ChDir(conn, oldcwd);
727 if (cversion != -1) {
733 /****************************************************************************
734 ****************************************************************************/
736 #define strip_driver_path(_mem_ctx, _element) do { \
737 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
738 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
739 W_ERROR_HAVE_NO_MEMORY((_element)); \
743 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
744 struct pipes_struct *rpc_pipe,
745 const char *architecture,
746 const char **driver_path,
747 const char **data_file,
748 const char **config_file,
749 const char **help_file,
750 struct spoolss_StringArray *dependent_files,
753 const char *short_architecture;
758 if (!*driver_path || !*data_file || !*config_file) {
759 return WERR_INVALID_PARAM;
762 /* clean up the driver name.
763 * we can get .\driver.dll
764 * or worse c:\windows\system\driver.dll !
766 /* using an intermediate string to not have overlaping memcpy()'s */
768 strip_driver_path(mem_ctx, *driver_path);
769 strip_driver_path(mem_ctx, *data_file);
770 strip_driver_path(mem_ctx, *config_file);
772 strip_driver_path(mem_ctx, *help_file);
775 if (dependent_files && dependent_files->string) {
776 for (i=0; dependent_files->string[i]; i++) {
777 strip_driver_path(mem_ctx, dependent_files->string[i]);
781 short_architecture = get_short_archi(architecture);
782 if (!short_architecture) {
783 return WERR_UNKNOWN_PRINTER_DRIVER;
786 /* jfm:7/16/2000 the client always sends the cversion=0.
787 * The server should check which version the driver is by reading
788 * the PE header of driver->driverpath.
790 * For Windows 95/98 the version is 0 (so the value sent is correct)
791 * For Windows NT (the architecture doesn't matter)
793 * NT 3.5/3.51: cversion=1
798 *version = get_correct_cversion(rpc_pipe, short_architecture,
800 if (*version == -1) {
807 /****************************************************************************
808 ****************************************************************************/
810 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
811 struct pipes_struct *rpc_pipe,
812 struct spoolss_AddDriverInfoCtr *r)
816 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
817 r->info.info3->architecture,
818 &r->info.info3->driver_path,
819 &r->info.info3->data_file,
820 &r->info.info3->config_file,
821 &r->info.info3->help_file,
822 r->info.info3->dependent_files,
823 &r->info.info3->version);
825 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
826 r->info.info6->architecture,
827 &r->info.info6->driver_path,
828 &r->info.info6->data_file,
829 &r->info.info6->config_file,
830 &r->info.info6->help_file,
831 r->info.info6->dependent_files,
832 &r->info.info6->version);
834 return WERR_NOT_SUPPORTED;
838 /****************************************************************************
839 This function sucks and should be replaced. JRA.
840 ****************************************************************************/
842 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
843 const struct spoolss_AddDriverInfo6 *src)
845 dst->version = src->version;
847 dst->driver_name = src->driver_name;
848 dst->architecture = src->architecture;
849 dst->driver_path = src->driver_path;
850 dst->data_file = src->data_file;
851 dst->config_file = src->config_file;
852 dst->help_file = src->help_file;
853 dst->monitor_name = src->monitor_name;
854 dst->default_datatype = src->default_datatype;
855 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
856 dst->dependent_files = src->dependent_files;
859 /****************************************************************************
860 ****************************************************************************/
862 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
863 connection_struct *conn,
864 const char *driver_file,
865 const char *short_architecture,
866 uint32_t driver_version,
869 struct smb_filename *smb_fname_old = NULL;
870 struct smb_filename *smb_fname_new = NULL;
871 char *old_name = NULL;
872 char *new_name = NULL;
876 old_name = talloc_asprintf(mem_ctx, "%s/%s",
877 short_architecture, driver_file);
878 W_ERROR_HAVE_NO_MEMORY(old_name);
880 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
881 short_architecture, driver_version, driver_file);
882 if (new_name == NULL) {
883 TALLOC_FREE(old_name);
887 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
889 status = driver_unix_convert(conn, old_name, &smb_fname_old);
890 if (!NT_STATUS_IS_OK(status)) {
895 /* Setup a synthetic smb_filename struct */
896 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
897 if (!smb_fname_new) {
902 smb_fname_new->base_name = new_name;
904 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
905 "'%s'\n", smb_fname_old->base_name,
906 smb_fname_new->base_name));
908 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
909 OPENX_FILE_EXISTS_TRUNCATE |
910 OPENX_FILE_CREATE_IF_NOT_EXIST,
913 if (!NT_STATUS_IS_OK(status)) {
914 DEBUG(0,("move_driver_file_to_download_area: Unable "
915 "to rename [%s] to [%s]: %s\n",
916 smb_fname_old->base_name, new_name,
918 ret = WERR_ACCESS_DENIED;
925 TALLOC_FREE(smb_fname_old);
926 TALLOC_FREE(smb_fname_new);
930 WERROR move_driver_to_download_area(struct pipes_struct *p,
931 struct spoolss_AddDriverInfoCtr *r,
934 struct spoolss_AddDriverInfo3 *driver;
935 struct spoolss_AddDriverInfo3 converted_driver;
936 const char *short_architecture;
937 struct smb_filename *smb_dname = NULL;
938 char *new_dir = NULL;
939 connection_struct *conn = NULL;
942 TALLOC_CTX *ctx = talloc_tos();
946 int printdollar_snum;
952 driver = r->info.info3;
955 convert_level_6_to_level3(&converted_driver, r->info.info6);
956 driver = &converted_driver;
959 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
960 return WERR_UNKNOWN_LEVEL;
963 short_architecture = get_short_archi(driver->architecture);
964 if (!short_architecture) {
965 return WERR_UNKNOWN_PRINTER_DRIVER;
968 fstrcpy(printdollar, "print$");
970 printdollar_snum = find_service(printdollar);
971 if (printdollar_snum == -1) {
972 *perr = WERR_NO_SUCH_SHARE;
973 return WERR_NO_SUCH_SHARE;
976 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
977 lp_pathname(printdollar_snum),
978 p->server_info, &oldcwd);
979 if (!NT_STATUS_IS_OK(nt_status)) {
980 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
981 "returned %s\n", nt_errstr(nt_status)));
982 *perr = ntstatus_to_werror(nt_status);
986 new_dir = talloc_asprintf(ctx,
994 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
995 if (!NT_STATUS_IS_OK(nt_status)) {
1000 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1002 create_directory(conn, NULL, smb_dname);
1004 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1005 * listed for this driver which has already been moved, skip it (note:
1006 * drivers may list the same file name several times. Then check if the
1007 * file already exists in archi\version\, if so, check that the version
1008 * info (or time stamps if version info is unavailable) is newer (or the
1009 * date is later). If it is, move it to archi\version\filexxx.yyy.
1010 * Otherwise, delete the file.
1012 * If a file is not moved to archi\version\ because of an error, all the
1013 * rest of the 'unmoved' driver files are removed from archi\. If one or
1014 * more of the driver's files was already moved to archi\version\, it
1015 * potentially leaves the driver in a partially updated state. Version
1016 * trauma will most likely occur if an client attempts to use any printer
1017 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1018 * done is appropriate... later JRR
1021 DEBUG(5,("Moving files now !\n"));
1023 if (driver->driver_path && strlen(driver->driver_path)) {
1025 *perr = move_driver_file_to_download_area(ctx,
1027 driver->driver_path,
1031 if (!W_ERROR_IS_OK(*perr)) {
1032 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1039 if (driver->data_file && strlen(driver->data_file)) {
1040 if (!strequal(driver->data_file, driver->driver_path)) {
1042 *perr = move_driver_file_to_download_area(ctx,
1048 if (!W_ERROR_IS_OK(*perr)) {
1049 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1057 if (driver->config_file && strlen(driver->config_file)) {
1058 if (!strequal(driver->config_file, driver->driver_path) &&
1059 !strequal(driver->config_file, driver->data_file)) {
1061 *perr = move_driver_file_to_download_area(ctx,
1063 driver->config_file,
1067 if (!W_ERROR_IS_OK(*perr)) {
1068 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1076 if (driver->help_file && strlen(driver->help_file)) {
1077 if (!strequal(driver->help_file, driver->driver_path) &&
1078 !strequal(driver->help_file, driver->data_file) &&
1079 !strequal(driver->help_file, driver->config_file)) {
1081 *perr = move_driver_file_to_download_area(ctx,
1087 if (!W_ERROR_IS_OK(*perr)) {
1088 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1096 if (driver->dependent_files && driver->dependent_files->string) {
1097 for (i=0; driver->dependent_files->string[i]; i++) {
1098 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1099 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1100 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1101 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1103 for (j=0; j < i; j++) {
1104 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1109 *perr = move_driver_file_to_download_area(ctx,
1111 driver->dependent_files->string[i],
1115 if (!W_ERROR_IS_OK(*perr)) {
1116 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1127 TALLOC_FREE(smb_dname);
1130 vfs_ChDir(conn, oldcwd);
1134 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1138 return WERR_UNKNOWN_PRINTER_DRIVER;
1143 /****************************************************************************
1144 Create and allocate a default devicemode.
1145 ****************************************************************************/
1147 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1148 const char *devicename,
1149 struct spoolss_DeviceMode **devmode)
1151 struct spoolss_DeviceMode *dm;
1154 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1159 dname = talloc_asprintf(dm, "%s", devicename);
1160 if (dname == NULL) {
1163 if (strlen(dname) > MAXDEVICENAME) {
1164 dname[MAXDEVICENAME] = '\0';
1166 dm->devicename = dname;
1168 dm->formname = talloc_strdup(dm, "Letter");
1169 if (dm->formname == NULL) {
1173 dm->specversion = DMSPEC_NT4_AND_ABOVE;
1174 dm->driverversion = 0x0400;
1176 dm->__driverextra_length = 0;
1177 dm->fields = DEVMODE_FORMNAME |
1179 DEVMODE_PRINTQUALITY |
1180 DEVMODE_DEFAULTSOURCE |
1184 DEVMODE_ORIENTATION;
1185 dm->orientation = DMORIENT_PORTRAIT;
1186 dm->papersize = DMPAPER_LETTER;
1187 dm->paperlength = 0;
1191 dm->defaultsource = DMBIN_FORMSOURCE;
1192 dm->printquality = DMRES_HIGH; /* 0x0258 */
1193 dm->color = DMRES_MONOCHROME;
1194 dm->duplex = DMDUP_SIMPLEX;
1195 dm->yresolution = 0;
1196 dm->ttoption = DMTT_SUBDEV;
1197 dm->collate = DMCOLLATE_FALSE;
1207 dm->displayflags = 0;
1208 dm->displayfrequency = 0;
1211 dm->panningwidth = 0;
1212 dm->panningheight = 0;
1214 dm->driverextra_data.data = NULL;
1215 dm->driverextra_data.length = 0;
1221 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1222 struct spoolss_security_descriptor **secdesc)
1224 struct security_ace ace[7]; /* max number of ace entries */
1227 struct security_acl *psa = NULL;
1228 struct security_descriptor *psd = NULL;
1229 struct dom_sid adm_sid;
1232 /* Create an ACE where Everyone is allowed to print */
1234 sa = PRINTER_ACE_PRINT;
1235 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1236 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1238 /* Add the domain admins group if we are a DC */
1241 struct dom_sid domadmins_sid;
1243 sid_compose(&domadmins_sid, get_global_sam_sid(),
1246 sa = PRINTER_ACE_FULL_CONTROL;
1247 init_sec_ace(&ace[i++], &domadmins_sid,
1248 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1249 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1250 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1251 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1253 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1254 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1256 sa = PRINTER_ACE_FULL_CONTROL;
1257 init_sec_ace(&ace[i++], &adm_sid,
1258 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1259 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1260 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1261 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1264 /* add BUILTIN\Administrators as FULL CONTROL */
1266 sa = PRINTER_ACE_FULL_CONTROL;
1267 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1268 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1269 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1270 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1271 SEC_ACE_TYPE_ACCESS_ALLOWED,
1272 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1274 /* add BUILTIN\Print Operators as FULL CONTROL */
1276 sa = PRINTER_ACE_FULL_CONTROL;
1277 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1278 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1279 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1280 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1281 SEC_ACE_TYPE_ACCESS_ALLOWED,
1282 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1284 /* Make the security descriptor owned by the BUILTIN\Administrators */
1286 /* The ACL revision number in rpc_secdesc.h differs from the one
1287 created by NT when setting ACE entries in printer
1288 descriptors. NT4 complains about the property being edited by a
1291 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1292 psd = make_sec_desc(mem_ctx,
1294 SEC_DESC_SELF_RELATIVE,
1295 &global_sid_Builtin_Administrators,
1296 &global_sid_Builtin_Administrators,
1303 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1307 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1308 (unsigned int)sd_size));
1316 /*****************************************************************
1317 ****************************************************************/
1319 static void store_printer_guid(const char *printer, struct GUID guid)
1321 TALLOC_CTX *tmp_ctx;
1322 struct auth_serversupplied_info *server_info = NULL;
1323 const char *guid_str;
1328 tmp_ctx = talloc_new(NULL);
1330 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1334 status = make_server_info_system(tmp_ctx, &server_info);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 DEBUG(0, ("store_printer_guid: "
1337 "Could not create system server_info\n"));
1341 guid_str = GUID_string(tmp_ctx, &guid);
1343 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1347 /* We used to store this as a REG_BINARY but that causes
1350 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
1351 DEBUG(0, ("store_printer_guid: "
1352 "Could not marshall string %s for objectGUID\n",
1357 result = winreg_set_printer_dataex(tmp_ctx, server_info, printer,
1358 SPOOL_DSSPOOLER_KEY, "objectGUID",
1359 REG_SZ, blob.data, blob.length);
1360 if (!W_ERROR_IS_OK(result)) {
1361 DEBUG(0, ("store_printer_guid: "
1362 "Failed to store GUID for printer %s\n", printer));
1366 talloc_free(tmp_ctx);
1369 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
1370 struct spoolss_PrinterInfo2 *pinfo2)
1374 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
1375 char *srv_dn_utf8, **srv_cn_utf8;
1378 const char *attrs[] = {"objectGUID", NULL};
1380 WERROR win_rc = WERR_OK;
1381 size_t converted_size;
1382 const char *printer = pinfo2->sharename;
1384 /* build the ads mods */
1385 ctx = talloc_init("nt_printer_publish_ads");
1390 DEBUG(5, ("publishing printer %s\n", printer));
1392 /* figure out where to publish */
1393 ads_find_machine_acct(ads, &res, global_myname());
1395 /* We use ldap_get_dn here as we need the answer
1396 * in utf8 to call ldap_explode_dn(). JRA. */
1398 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1401 return WERR_SERVER_UNAVAILABLE;
1403 ads_msgfree(ads, res);
1404 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
1407 ldap_memfree(srv_dn_utf8);
1408 return WERR_SERVER_UNAVAILABLE;
1410 /* Now convert to CH_UNIX. */
1411 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
1413 ldap_memfree(srv_dn_utf8);
1414 ldap_memfree(srv_cn_utf8);
1415 return WERR_SERVER_UNAVAILABLE;
1417 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
1419 ldap_memfree(srv_dn_utf8);
1420 ldap_memfree(srv_cn_utf8);
1421 TALLOC_FREE(srv_dn);
1422 return WERR_SERVER_UNAVAILABLE;
1425 ldap_memfree(srv_dn_utf8);
1426 ldap_memfree(srv_cn_utf8);
1428 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
1429 if (!srv_cn_escaped) {
1431 return WERR_SERVER_UNAVAILABLE;
1433 sharename_escaped = escape_rdn_val_string_alloc(printer);
1434 if (!sharename_escaped) {
1435 SAFE_FREE(srv_cn_escaped);
1437 return WERR_SERVER_UNAVAILABLE;
1440 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
1442 SAFE_FREE(srv_cn_escaped);
1443 SAFE_FREE(sharename_escaped);
1445 mods = ads_init_mods(ctx);
1453 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
1456 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
1457 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
1459 for (i=0; mods[i] != 0; i++)
1461 mods[i] = (LDAPMod *)-1;
1462 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
1465 if (!ADS_ERR_OK(ads_rc)) {
1466 DEBUG(3, ("error publishing %s: %s\n",
1467 printer, ads_errstr(ads_rc)));
1470 /* retreive the guid and store it locally */
1471 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
1473 ads_pull_guid(ads, res, &guid);
1474 ads_msgfree(ads, res);
1475 store_printer_guid(printer, guid);
1482 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
1483 const char *printer)
1486 LDAPMessage *res = NULL;
1487 char *prt_dn = NULL;
1489 DEBUG(5, ("unpublishing printer %s\n", printer));
1491 /* remove the printer from the directory */
1492 ads_rc = ads_find_printer_on_server(ads, &res,
1493 printer, global_myname());
1495 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
1496 prt_dn = ads_get_dn(ads, talloc_tos(), res);
1498 ads_msgfree(ads, res);
1501 ads_rc = ads_del_dn(ads, prt_dn);
1502 TALLOC_FREE(prt_dn);
1506 ads_msgfree(ads, res);
1511 /****************************************************************************
1512 * Publish a printer in the directory
1514 * @param mem_ctx memory context
1515 * @param server_info server_info to access winreg pipe
1516 * @param pinfo2 printer information
1517 * @param action publish/unpublish action
1518 * @return WERROR indicating status of publishing
1519 ***************************************************************************/
1521 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
1522 struct auth_serversupplied_info *server_info,
1523 struct spoolss_PrinterInfo2 *pinfo2,
1526 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1527 struct spoolss_SetPrinterInfo2 *sinfo2;
1529 ADS_STRUCT *ads = NULL;
1532 sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
1538 case DSPRINT_PUBLISH:
1539 case DSPRINT_UPDATE:
1540 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
1542 case DSPRINT_UNPUBLISH:
1543 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
1546 win_rc = WERR_NOT_SUPPORTED;
1550 sinfo2->attributes = pinfo2->attributes;
1552 win_rc = winreg_update_printer(mem_ctx, server_info,
1553 pinfo2->sharename, info2_mask,
1554 sinfo2, NULL, NULL);
1555 if (!W_ERROR_IS_OK(win_rc)) {
1556 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
1560 TALLOC_FREE(sinfo2);
1562 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
1564 DEBUG(3, ("ads_init() failed\n"));
1565 win_rc = WERR_SERVER_UNAVAILABLE;
1568 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
1569 SAFE_FREE(ads->auth.password);
1570 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
1573 /* ads_connect() will find the DC for us */
1574 ads_rc = ads_connect(ads);
1575 if (!ADS_ERR_OK(ads_rc)) {
1576 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
1577 win_rc = WERR_ACCESS_DENIED;
1582 case DSPRINT_PUBLISH:
1583 case DSPRINT_UPDATE:
1584 win_rc = nt_printer_publish_ads(ads, pinfo2);
1586 case DSPRINT_UNPUBLISH:
1587 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
1596 WERROR check_published_printers(void)
1599 ADS_STRUCT *ads = NULL;
1601 int n_services = lp_numservices();
1602 TALLOC_CTX *tmp_ctx = NULL;
1603 struct auth_serversupplied_info *server_info = NULL;
1604 struct spoolss_PrinterInfo2 *pinfo2;
1608 tmp_ctx = talloc_new(NULL);
1609 if (!tmp_ctx) return WERR_NOMEM;
1611 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
1613 DEBUG(3, ("ads_init() failed\n"));
1614 return WERR_SERVER_UNAVAILABLE;
1616 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
1617 SAFE_FREE(ads->auth.password);
1618 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
1621 /* ads_connect() will find the DC for us */
1622 ads_rc = ads_connect(ads);
1623 if (!ADS_ERR_OK(ads_rc)) {
1624 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
1625 result = WERR_ACCESS_DENIED;
1629 status = make_server_info_system(tmp_ctx, &server_info);
1630 if (!NT_STATUS_IS_OK(status)) {
1631 DEBUG(0, ("check_published_printers: "
1632 "Could not create system server_info\n"));
1633 result = WERR_ACCESS_DENIED;
1637 for (snum = 0; snum < n_services; snum++) {
1638 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1642 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1643 lp_servicename(snum), &pinfo2);
1644 if (!W_ERROR_IS_OK(result)) {
1648 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
1649 nt_printer_publish_ads(ads, pinfo2);
1652 TALLOC_FREE(pinfo2);
1658 ads_kdestroy("MEMORY:prtpub_cache");
1659 talloc_free(tmp_ctx);
1663 bool is_printer_published(TALLOC_CTX *mem_ctx,
1664 struct auth_serversupplied_info *server_info,
1665 char *servername, char *printer, struct GUID *guid,
1666 struct spoolss_PrinterInfo2 **info2)
1668 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1669 enum winreg_Type type;
1675 result = winreg_get_printer(mem_ctx, server_info,
1676 servername, printer, &pinfo2);
1677 if (!W_ERROR_IS_OK(result)) {
1681 if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
1682 TALLOC_FREE(pinfo2);
1690 /* fetching printer guids really ought to be a separate function. */
1692 result = winreg_get_printer_dataex(mem_ctx, server_info, printer,
1693 SPOOL_DSSPOOLER_KEY, "objectGUID",
1694 &type, &data, &data_size);
1695 if (!W_ERROR_IS_OK(result)) {
1696 TALLOC_FREE(pinfo2);
1700 /* We used to store the guid as REG_BINARY, then swapped
1701 to REG_SZ for Vista compatibility so check for both */
1705 status = GUID_from_string((char *)data, guid);
1706 if (!NT_STATUS_IS_OK(status)) {
1707 TALLOC_FREE(pinfo2);
1713 if (data_size != sizeof(struct GUID)) {
1714 TALLOC_FREE(pinfo2);
1717 memcpy(guid, data, sizeof(struct GUID));
1720 DEBUG(0,("is_printer_published: GUID value stored as "
1721 "invaluid type (%d)\n", type));
1727 *info2 = talloc_move(mem_ctx, &pinfo2);
1729 talloc_free(pinfo2);
1733 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
1734 struct auth_serversupplied_info *server_info,
1735 struct spoolss_PrinterInfo2 *pinfo2,
1741 WERROR check_published_printers(void)
1746 bool is_printer_published(TALLOC_CTX *mem_ctx,
1747 struct auth_serversupplied_info *server_info,
1748 char *servername, char *printer, struct GUID *guid,
1749 struct spoolss_PrinterInfo2 **info2)
1753 #endif /* HAVE_ADS */
1755 /****************************************************************************
1756 ***************************************************************************/
1758 static char *win_driver;
1759 static char *os2_driver;
1761 static const char *get_win_driver(void)
1763 if (win_driver == NULL) {
1769 static const char *get_os2_driver(void)
1771 if (os2_driver == NULL) {
1777 static bool set_driver_mapping(const char *from, const char *to)
1779 SAFE_FREE(win_driver);
1780 SAFE_FREE(os2_driver);
1782 win_driver = SMB_STRDUP(from);
1783 os2_driver = SMB_STRDUP(to);
1785 if (win_driver == NULL || os2_driver == NULL) {
1786 SAFE_FREE(win_driver);
1787 SAFE_FREE(os2_driver);
1796 * @brief Map a Windows driver to a OS/2 driver.
1798 * @param[in] mem_ctx The memory context to use.
1800 * @param[in,out] pdrivername The drivername of Windows to remap.
1802 * @return WERR_OK on success, a corresponding WERROR on failure.
1804 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1806 const char *mapfile = lp_os2_driver_map();
1807 char **lines = NULL;
1808 const char *drivername;
1812 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1813 return WERR_INVALID_PARAMETER;
1816 drivername = *pdrivername;
1818 if (mapfile[0] == '\0') {
1819 return WERR_BADFILE;
1822 if (strequal(drivername, get_win_driver())) {
1823 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1824 drivername, get_os2_driver()));
1825 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1826 if (drivername == NULL) {
1829 *pdrivername = drivername;
1833 lines = file_lines_load(mapfile, &numlines, 0, NULL);
1834 if (numlines == 0 || lines == NULL) {
1835 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1840 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1842 for( i = 0; i < numlines; i++) {
1843 char *nt_name = lines[i];
1844 char *os2_name = strchr(nt_name, '=');
1846 if (os2_name == NULL) {
1852 while (isspace(*nt_name)) {
1856 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1861 int l = strlen(nt_name);
1862 while (l && isspace(nt_name[l - 1])) {
1868 while (isspace(*os2_name)) {
1873 int l = strlen(os2_name);
1874 while (l && isspace(os2_name[l-1])) {
1880 if (strequal(nt_name, drivername)) {
1881 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1882 set_driver_mapping(drivername, os2_name);
1883 drivername = talloc_strdup(mem_ctx, os2_name);
1885 if (drivername == NULL) {
1888 *pdrivername = drivername;
1897 /****************************************************************************
1898 ****************************************************************************/
1900 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1901 struct spoolss_DriverInfo8 *_info8)
1903 struct spoolss_DriverInfo8 info8;
1909 info8.version = r->info.info3->version;
1910 info8.driver_name = r->info.info3->driver_name;
1911 info8.architecture = r->info.info3->architecture;
1912 info8.driver_path = r->info.info3->driver_path;
1913 info8.data_file = r->info.info3->data_file;
1914 info8.config_file = r->info.info3->config_file;
1915 info8.help_file = r->info.info3->help_file;
1916 info8.monitor_name = r->info.info3->monitor_name;
1917 info8.default_datatype = r->info.info3->default_datatype;
1918 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1919 info8.dependent_files = r->info.info3->dependent_files->string;
1923 info8.version = r->info.info6->version;
1924 info8.driver_name = r->info.info6->driver_name;
1925 info8.architecture = r->info.info6->architecture;
1926 info8.driver_path = r->info.info6->driver_path;
1927 info8.data_file = r->info.info6->data_file;
1928 info8.config_file = r->info.info6->config_file;
1929 info8.help_file = r->info.info6->help_file;
1930 info8.monitor_name = r->info.info6->monitor_name;
1931 info8.default_datatype = r->info.info6->default_datatype;
1932 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1933 info8.dependent_files = r->info.info6->dependent_files->string;
1935 info8.driver_date = r->info.info6->driver_date;
1936 info8.driver_version = r->info.info6->driver_version;
1937 info8.manufacturer_name = r->info.info6->manufacturer_name;
1938 info8.manufacturer_url = r->info.info6->manufacturer_url;
1939 info8.hardware_id = r->info.info6->hardware_id;
1940 info8.provider = r->info.info6->provider;
1943 info8.version = r->info.info8->version;
1944 info8.driver_name = r->info.info8->driver_name;
1945 info8.architecture = r->info.info8->architecture;
1946 info8.driver_path = r->info.info8->driver_path;
1947 info8.data_file = r->info.info8->data_file;
1948 info8.config_file = r->info.info8->config_file;
1949 info8.help_file = r->info.info8->help_file;
1950 info8.monitor_name = r->info.info8->monitor_name;
1951 info8.default_datatype = r->info.info8->default_datatype;
1952 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1953 info8.dependent_files = r->info.info8->dependent_files->string;
1955 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1956 info8.previous_names = r->info.info8->previous_names->string;
1958 info8.driver_date = r->info.info8->driver_date;
1959 info8.driver_version = r->info.info8->driver_version;
1960 info8.manufacturer_name = r->info.info8->manufacturer_name;
1961 info8.manufacturer_url = r->info.info8->manufacturer_url;
1962 info8.hardware_id = r->info.info8->hardware_id;
1963 info8.provider = r->info.info8->provider;
1964 info8.print_processor = r->info.info8->print_processor;
1965 info8.vendor_setup = r->info.info8->vendor_setup;
1966 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1967 info8.color_profiles = r->info.info8->color_profiles->string;
1969 info8.inf_path = r->info.info8->inf_path;
1970 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1971 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1972 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1974 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1975 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1987 /****************************************************************************
1988 Determine whether or not a particular driver is currently assigned
1990 ****************************************************************************/
1992 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1993 struct auth_serversupplied_info *server_info,
1994 const struct spoolss_DriverInfo8 *r)
1997 int n_services = lp_numservices();
1998 bool in_use = False;
1999 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2006 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
2008 /* loop through the printers.tdb and check for the drivername */
2010 for (snum=0; snum<n_services && !in_use; snum++) {
2011 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
2015 result = winreg_get_printer(mem_ctx, server_info, NULL,
2016 lp_servicename(snum), &pinfo2);
2017 if (!W_ERROR_IS_OK(result)) {
2018 continue; /* skip */
2021 if (strequal(r->driver_name, pinfo2->drivername)) {
2025 TALLOC_FREE(pinfo2);
2028 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
2031 struct spoolss_DriverInfo8 *driver;
2034 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
2036 /* we can still remove the driver if there is one of
2037 "Windows NT x86" version 2 or 3 left */
2039 if (!strequal("Windows NT x86", r->architecture)) {
2040 werr = winreg_get_driver(mem_ctx, server_info,
2045 } else if (r->version == 2) {
2046 werr = winreg_get_driver(mem_ctx, server_info,
2050 } else if (r->version == 3) {
2051 werr = winreg_get_driver(mem_ctx, server_info,
2056 DEBUG(0, ("printer_driver_in_use: ERROR!"
2057 " unknown driver version (%d)\n",
2059 werr = WERR_UNKNOWN_PRINTER_DRIVER;
2062 /* now check the error code */
2064 if ( W_ERROR_IS_OK(werr) ) {
2065 /* it's ok to remove the driver, we have other architctures left */
2067 talloc_free(driver);
2071 /* report that the driver is not in use by default */
2077 /**********************************************************************
2078 Check to see if a ogiven file is in use by *info
2079 *********************************************************************/
2081 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
2088 /* mz: skip files that are in the list but already deleted */
2089 if (!file || !file[0]) {
2093 if (strequal(file, info->driver_path))
2096 if (strequal(file, info->data_file))
2099 if (strequal(file, info->config_file))
2102 if (strequal(file, info->help_file))
2105 /* see of there are any dependent files to examine */
2107 if (!info->dependent_files)
2110 while (info->dependent_files[i] && *info->dependent_files[i]) {
2111 if (strequal(file, info->dependent_files[i]))
2120 /**********************************************************************
2121 Utility function to remove the dependent file pointed to by the
2122 input parameter from the list
2123 *********************************************************************/
2125 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
2128 /* bump everything down a slot */
2130 while (files && files[idx+1]) {
2131 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
2140 /**********************************************************************
2141 Check if any of the files used by src are also used by drv
2142 *********************************************************************/
2144 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
2145 struct spoolss_DriverInfo8 *src,
2146 const struct spoolss_DriverInfo8 *drv)
2148 bool in_use = False;
2154 /* check each file. Remove it from the src structure if it overlaps */
2156 if (drv_file_in_use(src->driver_path, drv)) {
2158 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
2159 src->driver_path = talloc_strdup(mem_ctx, "");
2160 if (!src->driver_path) { return false; }
2163 if (drv_file_in_use(src->data_file, drv)) {
2165 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
2166 src->data_file = talloc_strdup(mem_ctx, "");
2167 if (!src->data_file) { return false; }
2170 if (drv_file_in_use(src->config_file, drv)) {
2172 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
2173 src->config_file = talloc_strdup(mem_ctx, "");
2174 if (!src->config_file) { return false; }
2177 if (drv_file_in_use(src->help_file, drv)) {
2179 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
2180 src->help_file = talloc_strdup(mem_ctx, "");
2181 if (!src->help_file) { return false; }
2184 /* are there any dependentfiles to examine? */
2186 if (!src->dependent_files)
2189 while (src->dependent_files[i] && *src->dependent_files[i]) {
2190 if (drv_file_in_use(src->dependent_files[i], drv)) {
2192 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
2193 trim_dependent_file(mem_ctx, src->dependent_files, i);
2201 /****************************************************************************
2202 Determine whether or not a particular driver files are currently being
2203 used by any other driver.
2205 Return value is True if any files were in use by other drivers
2206 and False otherwise.
2208 Upon return, *info has been modified to only contain the driver files
2209 which are not in use
2213 This needs to check all drivers to ensure that all files in use
2214 have been removed from *info, not just the ones in the first
2216 ****************************************************************************/
2218 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
2219 struct auth_serversupplied_info *server_info,
2220 struct spoolss_DriverInfo8 *info)
2224 struct spoolss_DriverInfo8 *driver;
2225 bool in_use = false;
2226 uint32_t num_drivers;
2227 const char **drivers;
2233 version = info->version;
2235 /* loop over all driver versions */
2237 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
2239 /* get the list of drivers */
2241 result = winreg_get_driver_list(mem_ctx, server_info,
2242 info->architecture, version,
2243 &num_drivers, &drivers);
2244 if (!W_ERROR_IS_OK(result)) {
2248 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
2249 num_drivers, info->architecture, version));
2251 /* check each driver for overlap in files */
2253 for (i = 0; i < num_drivers; i++) {
2254 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
2258 result = winreg_get_driver(mem_ctx, server_info,
2259 info->architecture, drivers[i],
2261 if (!W_ERROR_IS_OK(result)) {
2262 talloc_free(drivers);
2266 /* check if d2 uses any files from d1 */
2267 /* only if this is a different driver than the one being deleted */
2269 if (!strequal(info->driver_name, driver->driver_name)) {
2270 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
2271 /* mz: Do not instantly return -
2272 * we need to ensure this file isn't
2273 * also in use by other drivers. */
2278 talloc_free(driver);
2281 talloc_free(drivers);
2283 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2288 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2291 struct smb_filename *smb_fname = NULL;
2294 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
2296 if (!NT_STATUS_IS_OK(status)) {
2300 status = unlink_internals(conn, NULL, 0, smb_fname, false);
2302 TALLOC_FREE(smb_fname);
2306 /****************************************************************************
2307 Actually delete the driver files. Make sure that
2308 printer_driver_files_in_use() return False before calling
2310 ****************************************************************************/
2312 bool delete_driver_files(struct auth_serversupplied_info *server_info,
2313 const struct spoolss_DriverInfo8 *r)
2318 connection_struct *conn;
2321 fstring printdollar;
2322 int printdollar_snum;
2329 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2330 r->driver_name, r->version));
2332 fstrcpy(printdollar, "print$");
2334 printdollar_snum = find_service(printdollar);
2335 if (printdollar_snum == -1) {
2339 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
2340 lp_pathname(printdollar_snum),
2341 server_info, &oldcwd);
2342 if (!NT_STATUS_IS_OK(nt_status)) {
2343 DEBUG(0,("delete_driver_files: create_conn_struct "
2344 "returned %s\n", nt_errstr(nt_status)));
2348 if ( !CAN_WRITE(conn) ) {
2349 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2353 /* now delete the files; must strip the '\print$' string from
2356 if (r->driver_path && r->driver_path[0]) {
2357 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
2359 DEBUG(10,("deleting driverfile [%s]\n", s));
2360 driver_unlink_internals(conn, file);
2364 if (r->config_file && r->config_file[0]) {
2365 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
2367 DEBUG(10,("deleting configfile [%s]\n", s));
2368 driver_unlink_internals(conn, file);
2372 if (r->data_file && r->data_file[0]) {
2373 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
2375 DEBUG(10,("deleting datafile [%s]\n", s));
2376 driver_unlink_internals(conn, file);
2380 if (r->help_file && r->help_file[0]) {
2381 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
2383 DEBUG(10,("deleting helpfile [%s]\n", s));
2384 driver_unlink_internals(conn, file);
2388 /* check if we are done removing files */
2390 if (r->dependent_files) {
2391 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2394 /* bypass the "\print$" portion of the path */
2396 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2398 DEBUG(10,("deleting dependent file [%s]\n", file));
2399 driver_unlink_internals(conn, file);
2411 vfs_ChDir(conn, oldcwd);
2419 1: level not implemented
2420 2: file doesn't exist
2421 3: can't allocate memory
2422 4: can't free memory
2423 5: non existant struct
2427 A printer and a printer driver are 2 different things.
2428 NT manages them separatelly, Samba does the same.
2429 Why ? Simply because it's easier and it makes sense !
2431 Now explanation: You have 3 printers behind your samba server,
2432 2 of them are the same make and model (laser A and B). But laser B
2433 has an 3000 sheet feeder and laser A doesn't such an option.
2434 Your third printer is an old dot-matrix model for the accounting :-).
2436 If the /usr/local/samba/lib directory (default dir), you will have
2437 5 files to describe all of this.
2439 3 files for the printers (1 by printer):
2442 NTprinter_accounting
2443 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2444 NTdriver_printer model X
2445 NTdriver_printer model Y
2447 jfm: I should use this comment for the text file to explain
2448 same thing for the forms BTW.
2449 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2453 /* Convert generic access rights to printer object specific access rights.
2454 It turns out that NT4 security descriptors use generic access rights and
2455 NT5 the object specific ones. */
2457 void map_printer_permissions(struct security_descriptor *sd)
2461 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2462 se_map_generic(&sd->dacl->aces[i].access_mask,
2463 &printer_generic_mapping);
2467 void map_job_permissions(struct security_descriptor *sd)
2471 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2472 se_map_generic(&sd->dacl->aces[i].access_mask,
2473 &job_generic_mapping);
2478 /****************************************************************************
2479 Check a user has permissions to perform the given operation. We use the
2480 permission constants defined in include/rpc_spoolss.h to check the various
2481 actions we perform when checking printer access.
2483 PRINTER_ACCESS_ADMINISTER:
2484 print_queue_pause, print_queue_resume, update_printer_sec,
2485 update_printer, spoolss_addprinterex_level_2,
2486 _spoolss_setprinterdata
2491 JOB_ACCESS_ADMINISTER:
2492 print_job_delete, print_job_pause, print_job_resume,
2495 Try access control in the following order (for performance reasons):
2496 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2497 2) check security descriptor (bit comparisons in memory)
2498 3) "printer admins" (may result in numerous calls to winbind)
2500 ****************************************************************************/
2501 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
2504 struct spoolss_security_descriptor *secdesc = NULL;
2505 uint32 access_granted;
2510 TALLOC_CTX *mem_ctx = NULL;
2511 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2513 /* If user is NULL then use the current_user structure */
2515 /* Always allow root or SE_PRINT_OPERATROR to do anything */
2517 if (server_info->utok.uid == sec_initial_uid()
2518 || user_has_privileges(server_info->ptok, &se_printop ) ) {
2522 /* Get printer name */
2524 pname = lp_printername(snum);
2526 if (!pname || !*pname) {
2531 /* Get printer security descriptor */
2533 if(!(mem_ctx = talloc_init("print_access_check"))) {
2538 result = winreg_get_printer_secdesc(mem_ctx,
2542 if (!W_ERROR_IS_OK(result)) {
2543 talloc_destroy(mem_ctx);
2548 if (access_type == JOB_ACCESS_ADMINISTER) {
2549 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2551 /* Create a child security descriptor to check permissions
2552 against. This is because print jobs are child objects
2553 objects of a printer. */
2554 status = se_create_child_secdesc(mem_ctx,
2558 parent_secdesc->owner_sid,
2559 parent_secdesc->group_sid,
2561 if (!NT_STATUS_IS_OK(status)) {
2562 talloc_destroy(mem_ctx);
2563 errno = map_errno_from_nt_status(status);
2567 map_job_permissions(secdesc);
2569 map_printer_permissions(secdesc);
2573 status = se_access_check(secdesc, server_info->ptok, access_type,
2576 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2578 /* see if we need to try the printer admin list */
2580 if (!NT_STATUS_IS_OK(status) &&
2581 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2582 server_info->info3->base.domain.string,
2583 NULL, server_info->ptok,
2584 lp_printer_admin(snum)))) {
2585 talloc_destroy(mem_ctx);
2589 talloc_destroy(mem_ctx);
2591 if (!NT_STATUS_IS_OK(status)) {
2595 return NT_STATUS_IS_OK(status);
2598 /****************************************************************************
2599 Check the time parameters allow a print operation.
2600 *****************************************************************************/
2602 bool print_time_access_check(struct auth_serversupplied_info *server_info,
2603 const char *servicename)
2605 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2608 time_t now = time(NULL);
2612 result = winreg_get_printer(NULL, server_info,
2613 NULL, servicename, &pinfo2);
2614 if (!W_ERROR_IS_OK(result)) {
2618 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2623 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2625 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2629 TALLOC_FREE(pinfo2);
2638 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2639 struct auth_serversupplied_info *server_info,
2640 const char *printer)
2644 result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
2645 if (!W_ERROR_IS_OK(result)) {
2646 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",