c9ce969b8893a182dafd1962d02a728daa6bf615
[vlendec/samba-autobuild/.git] / source3 / printing / nt_printing.c
1 /*
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.
7  *
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.
12  *
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.
17  *
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/>.
20  */
21
22 #include "includes.h"
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"
27 #include "registry.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"
34
35 /* Map generic permissions to printer object specific permissions */
36
37 const struct generic_mapping printer_generic_mapping = {
38         PRINTER_READ,
39         PRINTER_WRITE,
40         PRINTER_EXECUTE,
41         PRINTER_ALL_ACCESS
42 };
43
44 /* Map generic permissions to print server object specific permissions */
45
46 const struct generic_mapping printserver_generic_mapping = {
47         SERVER_READ,
48         SERVER_WRITE,
49         SERVER_EXECUTE,
50         SERVER_ALL_ACCESS
51 };
52
53 /* Map generic permissions to job object specific permissions */
54
55 const struct generic_mapping job_generic_mapping = {
56         JOB_READ,
57         JOB_WRITE,
58         JOB_EXECUTE,
59         JOB_ALL_ACCESS
60 };
61
62 static const struct print_architecture_table_node archi_table[]= {
63
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 },
71         {NULL,                   "",            -1 }
72 };
73
74 /****************************************************************************
75  Open the NT printing tdbs. Done once before fork().
76 ****************************************************************************/
77
78 bool nt_printing_init(struct messaging_context *msg_ctx)
79 {
80         WERROR win_rc;
81
82         if (!nt_printing_tdb_upgrade()) {
83                 return false;
84         }
85
86         /*
87          * register callback to handle updating printers as new
88          * drivers are installed
89          */
90         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
91                            do_drv_upgrade_printer);
92
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() */
96
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)));
101         }
102
103         return true;
104 }
105
106 /*******************************************************************
107  Function to allow filename parsing "the old way".
108 ********************************************************************/
109
110 static NTSTATUS driver_unix_convert(connection_struct *conn,
111                                     const char *old_name,
112                                     struct smb_filename **smb_fname)
113 {
114         NTSTATUS status;
115         TALLOC_CTX *ctx = talloc_tos();
116         char *name = talloc_strdup(ctx, old_name);
117
118         if (!name) {
119                 return NT_STATUS_NO_MEMORY;
120         }
121         unix_format(name);
122         name = unix_clean_name(ctx, name);
123         if (!name) {
124                 return NT_STATUS_NO_MEMORY;
125         }
126         trim_string(name,"/","/");
127
128         status = unix_convert(ctx, conn, name, smb_fname, 0);
129         if (!NT_STATUS_IS_OK(status)) {
130                 return NT_STATUS_NO_MEMORY;
131         }
132
133         return NT_STATUS_OK;
134 }
135
136 /****************************************************************************
137  Function to do the mapping between the long architecture name and
138  the short one.
139 ****************************************************************************/
140
141 const char *get_short_archi(const char *long_archi)
142 {
143         int i=-1;
144
145         DEBUG(107,("Getting architecture dependant directory\n"));
146         do {
147                 i++;
148         } while ( (archi_table[i].long_archi!=NULL ) &&
149                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
150
151         if (archi_table[i].long_archi==NULL) {
152                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
153                 return NULL;
154         }
155
156         /* this might be client code - but shouldn't this be an fstrcpy etc? */
157
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));
161
162         return archi_table[i].short_archi;
163 }
164
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 ****************************************************************************/
172
173 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
174 {
175         int     i;
176         char    *buf = NULL;
177         ssize_t byte_count;
178
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));
182                 goto error_exit;
183         }
184
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;
189         }
190
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;
196         }
197
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",
201                                 fname, errno));
202                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
203                 goto no_version_info;
204         }
205
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;
212         }
213
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;
218
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",
224                                 fname, errno));
225                         goto error_exit;
226                 }
227
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)
232                         goto error_exit;
233
234                 SAFE_FREE(buf);
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));
238                         goto error_exit;
239                 }
240
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));
244                         goto error_exit;
245                 }
246
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;
250
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);
254
255                                 if (section_bytes == 0)
256                                         goto error_exit;
257
258                                 SAFE_FREE(buf);
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));
262                                         goto error_exit;
263                                 }
264
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",
268                                                         fname, errno));
269                                         goto error_exit;
270                                 }
271
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));
275                                         goto error_exit;
276                                 }
277
278                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
279                                         goto error_exit;
280
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;
286
287                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
288                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
289                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
290
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));
295                                                         SAFE_FREE(buf);
296                                                         return 1;
297                                                 }
298                                         }
299                                 }
300                         }
301                 }
302
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));
305                 SAFE_FREE(buf);
306                 return 0;
307
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. */
314                         goto error_exit;
315                 }
316
317                 /* Allocate a bit more space to speed up things */
318                 SAFE_FREE(buf);
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));
322                         goto error_exit;
323                 }
324
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;
331
332                         for(i=0; i<byte_count; i++) {
333                                 /* Fast skip past data that can't possibly match */
334                                 if (buf[i] != 'V') continue;
335
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) {
339                                         int bc;
340
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) {
344
345                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
346                                                                  fname, errno));
347                                                 goto error_exit;
348                                         }
349
350                                         byte_count = bc + (byte_count - i);
351                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
352
353                                         i = 0;
354                                 }
355
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;
365
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));
372                                         SAFE_FREE(buf);
373                                         return 1;
374                                 }
375                         }
376                 }
377
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));
380                 SAFE_FREE(buf);
381                 return 0;
382
383         } else
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)));
387
388         no_version_info:
389                 SAFE_FREE(buf);
390                 return 0;
391
392         error_exit:
393                 SAFE_FREE(buf);
394                 return -1;
395 }
396
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 ****************************************************************************/
406
407 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
408 {
409         bool use_version = true;
410
411         uint32 new_major;
412         uint32 new_minor;
413         time_t new_create_time;
414
415         uint32 old_major;
416         uint32 old_minor;
417         time_t old_create_time;
418
419         struct smb_filename *smb_fname = NULL;
420         files_struct    *fsp = NULL;
421         SMB_STRUCT_STAT st;
422
423         NTSTATUS status;
424         int ret;
425
426         SET_STAT_INVALID(st);
427         new_create_time = (time_t)0;
428         old_create_time = (time_t)0;
429
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)) {
433                 goto error_exit;
434         }
435
436         status = SMB_VFS_CREATE_FILE(
437                 conn,                                   /* conn */
438                 NULL,                                   /* req */
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 */
449                 NULL,                                   /* sd */
450                 NULL,                                   /* ea_list */
451                 &fsp,                                   /* result */
452                 NULL);                                  /* pinfo */
453
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),
458                           errno));
459                 ret = 1;
460                 goto done;
461
462         } else {
463                 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
464                 if (ret == -1) {
465                         goto error_exit;
466                 }
467
468                 if (!ret) {
469                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
470                                          old_file));
471                         use_version = false;
472                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
473                                  goto error_exit;
474                         }
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));
478                 }
479         }
480         close_file(NULL, fsp, NORMAL_CLOSE);
481         fsp = NULL;
482
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)) {
486                 goto error_exit;
487         }
488
489         status = SMB_VFS_CREATE_FILE(
490                 conn,                                   /* conn */
491                 NULL,                                   /* req */
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 */
502                 NULL,                                   /* sd */
503                 NULL,                                   /* ea_list */
504                 &fsp,                                   /* result */
505                 NULL);                                  /* pinfo */
506
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));
511                 goto error_exit;
512
513         } else {
514                 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
515                 if (ret == -1) {
516                         goto error_exit;
517                 }
518
519                 if (!ret) {
520                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
521                                          new_file));
522                         use_version = false;
523                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
524                                 goto error_exit;
525                         }
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));
529                 }
530         }
531         close_file(NULL, fsp, NORMAL_CLOSE);
532         fsp = NULL;
533
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)) {
538
539                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
540                         ret = 1;
541                         goto done;
542                 }
543                 else {
544                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
545                         ret = 0;
546                         goto done;
547                 }
548
549         } else {
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));
553                         ret = 1;
554                         goto done;
555                 }
556                 else {
557                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
558                         ret = 0;
559                         goto done;
560                 }
561         }
562
563  error_exit:
564         if(fsp)
565                 close_file(NULL, fsp, NORMAL_CLOSE);
566         ret = -1;
567  done:
568         TALLOC_FREE(smb_fname);
569         return ret;
570 }
571
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,
578                                    WERROR *perr)
579 {
580         int               cversion;
581         NTSTATUS          nt_status;
582         struct smb_filename *smb_fname = NULL;
583         char *driverpath = NULL;
584         files_struct      *fsp = NULL;
585         connection_struct *conn = NULL;
586         NTSTATUS status;
587         char *oldcwd;
588         fstring printdollar;
589         int printdollar_snum;
590
591         *perr = WERR_INVALID_PARAM;
592
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"));
596                 *perr = WERR_OK;
597                 return 0;
598         }
599
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"));
603                 *perr = WERR_OK;
604                 return 3;
605         }
606
607         fstrcpy(printdollar, "print$");
608
609         printdollar_snum = find_service(printdollar);
610         if (printdollar_snum == -1) {
611                 *perr = WERR_NO_SUCH_SHARE;
612                 return -1;
613         }
614
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);
622                 return -1;
623         }
624
625         /* Open the driver file (Portable Executable format) and determine the
626          * deriver the cversion. */
627         driverpath = talloc_asprintf(talloc_tos(),
628                                         "%s/%s",
629                                         architecture,
630                                         driverpath_in);
631         if (!driverpath) {
632                 *perr = WERR_NOMEM;
633                 goto error_exit;
634         }
635
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);
639                 goto error_exit;
640         }
641
642         nt_status = vfs_file_exist(conn, smb_fname);
643         if (!NT_STATUS_IS_OK(nt_status)) {
644                 *perr = WERR_BADFILE;
645                 goto error_exit;
646         }
647
648         status = SMB_VFS_CREATE_FILE(
649                 conn,                                   /* conn */
650                 NULL,                                   /* req */
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 */
661                 NULL,                                   /* sd */
662                 NULL,                                   /* ea_list */
663                 &fsp,                                   /* result */
664                 NULL);                                  /* pinfo */
665
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;
670                 goto error_exit;
671         } else {
672                 uint32 major;
673                 uint32 minor;
674                 int    ret;
675
676                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
677                 if (ret == -1) goto error_exit;
678
679                 if (!ret) {
680                         DEBUG(6,("get_correct_cversion: Version info not "
681                                  "found [%s]\n",
682                                  smb_fname_str_dbg(smb_fname)));
683                         goto error_exit;
684                 }
685
686                 /*
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.
691                  * JRR 010716
692                 */
693                 cversion = major & 0x0000ffff;
694                 switch (cversion) {
695                         case 2: /* WinNT drivers */
696                         case 3: /* Win2K drivers */
697                                 break;
698
699                         default:
700                                 DEBUG(6,("get_correct_cversion: cversion "
701                                          "invalid [%s]  cversion = %d\n",
702                                          smb_fname_str_dbg(smb_fname),
703                                          cversion));
704                                 goto error_exit;
705                 }
706
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));
710         }
711
712         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
713                   smb_fname_str_dbg(smb_fname), cversion));
714
715         goto done;
716
717  error_exit:
718         cversion = -1;
719  done:
720         TALLOC_FREE(smb_fname);
721         if (fsp != NULL) {
722                 close_file(NULL, fsp, NORMAL_CLOSE);
723         }
724         if (conn != NULL) {
725                 vfs_ChDir(conn, oldcwd);
726                 conn_free(conn);
727         }
728         if (cversion != -1) {
729                 *perr = WERR_OK;
730         }
731         return cversion;
732 }
733
734 /****************************************************************************
735 ****************************************************************************/
736
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)); \
741         } \
742 } while (0);
743
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,
752                                            uint32_t *version)
753 {
754         const char *short_architecture;
755         int i;
756         WERROR err;
757         char *_p;
758
759         if (!*driver_path || !*data_file || !*config_file) {
760                 return WERR_INVALID_PARAM;
761         }
762
763         /* clean up the driver name.
764          * we can get .\driver.dll
765          * or worse c:\windows\system\driver.dll !
766          */
767         /* using an intermediate string to not have overlaping memcpy()'s */
768
769         strip_driver_path(mem_ctx, *driver_path);
770         strip_driver_path(mem_ctx, *data_file);
771         strip_driver_path(mem_ctx, *config_file);
772         if (help_file) {
773                 strip_driver_path(mem_ctx, *help_file);
774         }
775
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]);
779                 }
780         }
781
782         short_architecture = get_short_archi(architecture);
783         if (!short_architecture) {
784                 return WERR_UNKNOWN_PRINTER_DRIVER;
785         }
786
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.
790          *
791          * For Windows 95/98 the version is 0 (so the value sent is correct)
792          * For Windows NT (the architecture doesn't matter)
793          *      NT 3.1: cversion=0
794          *      NT 3.5/3.51: cversion=1
795          *      NT 4: cversion=2
796          *      NT2K: cversion=3
797          */
798
799         *version = get_correct_cversion(rpc_pipe, short_architecture,
800                                         *driver_path, &err);
801         if (*version == -1) {
802                 return err;
803         }
804
805         return WERR_OK;
806 }
807
808 /****************************************************************************
809 ****************************************************************************/
810
811 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
812                               struct pipes_struct *rpc_pipe,
813                               struct spoolss_AddDriverInfoCtr *r)
814 {
815         switch (r->level) {
816         case 3:
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);
825         case 6:
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);
834         default:
835                 return WERR_NOT_SUPPORTED;
836         }
837 }
838
839 /****************************************************************************
840  This function sucks and should be replaced. JRA.
841 ****************************************************************************/
842
843 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
844                                       const struct spoolss_AddDriverInfo6 *src)
845 {
846         dst->version            = src->version;
847
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;
858 }
859
860 /****************************************************************************
861 ****************************************************************************/
862
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,
868                                                 uint32_t version)
869 {
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;
874         NTSTATUS status;
875         WERROR ret;
876
877         old_name = talloc_asprintf(mem_ctx, "%s/%s",
878                                    short_architecture, driver_file);
879         W_ERROR_HAVE_NO_MEMORY(old_name);
880
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);
885                 return WERR_NOMEM;
886         }
887
888         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
889
890                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
891                 if (!NT_STATUS_IS_OK(status)) {
892                         ret = WERR_NOMEM;
893                         goto out;
894                 }
895
896                 /* Setup a synthetic smb_filename struct */
897                 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
898                 if (!smb_fname_new) {
899                         ret = WERR_NOMEM;
900                         goto out;
901                 }
902
903                 smb_fname_new->base_name = new_name;
904
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));
908
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,
912                                    0, false);
913
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,
918                                  nt_errstr(status)));
919                         ret = WERR_ACCESS_DENIED;
920                         goto out;
921                 }
922         }
923
924         ret = WERR_OK;
925  out:
926         TALLOC_FREE(smb_fname_old);
927         TALLOC_FREE(smb_fname_new);
928         return ret;
929 }
930
931 WERROR move_driver_to_download_area(struct pipes_struct *p,
932                                     struct spoolss_AddDriverInfoCtr *r,
933                                     WERROR *perr)
934 {
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;
941         NTSTATUS nt_status;
942         int i;
943         TALLOC_CTX *ctx = talloc_tos();
944         int ver = 0;
945         char *oldcwd;
946         fstring printdollar;
947         int printdollar_snum;
948
949         *perr = WERR_OK;
950
951         switch (r->level) {
952         case 3:
953                 driver = r->info.info3;
954                 break;
955         case 6:
956                 convert_level_6_to_level3(&converted_driver, r->info.info6);
957                 driver = &converted_driver;
958                 break;
959         default:
960                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
961                 return WERR_UNKNOWN_LEVEL;
962         }
963
964         short_architecture = get_short_archi(driver->architecture);
965         if (!short_architecture) {
966                 return WERR_UNKNOWN_PRINTER_DRIVER;
967         }
968
969         fstrcpy(printdollar, "print$");
970
971         printdollar_snum = find_service(printdollar);
972         if (printdollar_snum == -1) {
973                 *perr = WERR_NO_SUCH_SHARE;
974                 return WERR_NO_SUCH_SHARE;
975         }
976
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);
984                 return *perr;
985         }
986
987         new_dir = talloc_asprintf(ctx,
988                                 "%s/%d",
989                                 short_architecture,
990                                 driver->version);
991         if (!new_dir) {
992                 *perr = WERR_NOMEM;
993                 goto err_exit;
994         }
995         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
996         if (!NT_STATUS_IS_OK(nt_status)) {
997                 *perr = WERR_NOMEM;
998                 goto err_exit;
999         }
1000
1001         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1002
1003         create_directory(conn, NULL, smb_dname);
1004
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.
1012          *
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
1020          */
1021
1022         DEBUG(5,("Moving files now !\n"));
1023
1024         if (driver->driver_path && strlen(driver->driver_path)) {
1025
1026                 *perr = move_driver_file_to_download_area(ctx,
1027                                                           conn,
1028                                                           driver->driver_path,
1029                                                           short_architecture,
1030                                                           driver->version,
1031                                                           ver);
1032                 if (!W_ERROR_IS_OK(*perr)) {
1033                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1034                                 ver = -1;
1035                         }
1036                         goto err_exit;
1037                 }
1038         }
1039
1040         if (driver->data_file && strlen(driver->data_file)) {
1041                 if (!strequal(driver->data_file, driver->driver_path)) {
1042
1043                         *perr = move_driver_file_to_download_area(ctx,
1044                                                                   conn,
1045                                                                   driver->data_file,
1046                                                                   short_architecture,
1047                                                                   driver->version,
1048                                                                   ver);
1049                         if (!W_ERROR_IS_OK(*perr)) {
1050                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1051                                         ver = -1;
1052                                 }
1053                                 goto err_exit;
1054                         }
1055                 }
1056         }
1057
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)) {
1061
1062                         *perr = move_driver_file_to_download_area(ctx,
1063                                                                   conn,
1064                                                                   driver->config_file,
1065                                                                   short_architecture,
1066                                                                   driver->version,
1067                                                                   ver);
1068                         if (!W_ERROR_IS_OK(*perr)) {
1069                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1070                                         ver = -1;
1071                                 }
1072                                 goto err_exit;
1073                         }
1074                 }
1075         }
1076
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)) {
1081
1082                         *perr = move_driver_file_to_download_area(ctx,
1083                                                                   conn,
1084                                                                   driver->help_file,
1085                                                                   short_architecture,
1086                                                                   driver->version,
1087                                                                   ver);
1088                         if (!W_ERROR_IS_OK(*perr)) {
1089                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1090                                         ver = -1;
1091                                 }
1092                                 goto err_exit;
1093                         }
1094                 }
1095         }
1096
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)) {
1103                                 int j;
1104                                 for (j=0; j < i; j++) {
1105                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1106                                                 goto NextDriver;
1107                                         }
1108                                 }
1109
1110                                 *perr = move_driver_file_to_download_area(ctx,
1111                                                                           conn,
1112                                                                           driver->dependent_files->string[i],
1113                                                                           short_architecture,
1114                                                                           driver->version,
1115                                                                           ver);
1116                                 if (!W_ERROR_IS_OK(*perr)) {
1117                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1118                                                 ver = -1;
1119                                         }
1120                                         goto err_exit;
1121                                 }
1122                         }
1123                 NextDriver: ;
1124                 }
1125         }
1126
1127   err_exit:
1128         TALLOC_FREE(smb_dname);
1129
1130         if (conn != NULL) {
1131                 vfs_ChDir(conn, oldcwd);
1132                 conn_free(conn);
1133         }
1134
1135         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1136                 return WERR_OK;
1137         }
1138         if (ver == -1) {
1139                 return WERR_UNKNOWN_PRINTER_DRIVER;
1140         }
1141         return (*perr);
1142 }
1143
1144 /****************************************************************************
1145  Create and allocate a default devicemode.
1146 ****************************************************************************/
1147
1148 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1149                                       const char *devicename,
1150                                       struct spoolss_DeviceMode **devmode)
1151 {
1152         struct spoolss_DeviceMode *dm;
1153         char *dname;
1154
1155         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1156         if (dm == NULL) {
1157                 return WERR_NOMEM;
1158         }
1159
1160         dname = talloc_asprintf(dm, "%s", devicename);
1161         if (dname == NULL) {
1162                 return WERR_NOMEM;
1163         }
1164         if (strlen(dname) > MAXDEVICENAME) {
1165                 dname[MAXDEVICENAME] = '\0';
1166         }
1167         dm->devicename = dname;
1168
1169         dm->formname = talloc_strdup(dm, "Letter");
1170         if (dm->formname == NULL) {
1171                 return WERR_NOMEM;
1172         }
1173
1174         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
1175         dm->driverversion        = 0x0400;
1176         dm->size                 = 0x00DC;
1177         dm->__driverextra_length = 0;
1178         dm->fields               = DEVMODE_FORMNAME |
1179                                    DEVMODE_TTOPTION |
1180                                    DEVMODE_PRINTQUALITY |
1181                                    DEVMODE_DEFAULTSOURCE |
1182                                    DEVMODE_COPIES |
1183                                    DEVMODE_SCALE |
1184                                    DEVMODE_PAPERSIZE |
1185                                    DEVMODE_ORIENTATION;
1186         dm->orientation          = DMORIENT_PORTRAIT;
1187         dm->papersize            = DMPAPER_LETTER;
1188         dm->paperlength          = 0;
1189         dm->paperwidth           = 0;
1190         dm->scale                = 0x64;
1191         dm->copies               = 1;
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;
1199         dm->icmmethod            = 0;
1200         dm->icmintent            = 0;
1201         dm->mediatype            = 0;
1202         dm->dithertype           = 0;
1203
1204         dm->logpixels            = 0;
1205         dm->bitsperpel           = 0;
1206         dm->pelswidth            = 0;
1207         dm->pelsheight           = 0;
1208         dm->displayflags         = 0;
1209         dm->displayfrequency     = 0;
1210         dm->reserved1            = 0;
1211         dm->reserved2            = 0;
1212         dm->panningwidth         = 0;
1213         dm->panningheight        = 0;
1214
1215         dm->driverextra_data.data = NULL;
1216         dm->driverextra_data.length = 0;
1217
1218         *devmode = dm;
1219         return WERR_OK;
1220 }
1221
1222 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1223                                       struct spoolss_security_descriptor **secdesc)
1224 {
1225         struct security_ace ace[7];     /* max number of ace entries */
1226         int i = 0;
1227         uint32_t sa;
1228         struct security_acl *psa = NULL;
1229         struct security_descriptor *psd = NULL;
1230         struct dom_sid adm_sid;
1231         size_t sd_size;
1232
1233         /* Create an ACE where Everyone is allowed to print */
1234
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);
1238
1239         /* Add the domain admins group if we are a DC */
1240
1241         if ( IS_DC ) {
1242                 struct dom_sid domadmins_sid;
1243
1244                 sid_compose(&domadmins_sid, get_global_sam_sid(),
1245                             DOMAIN_RID_ADMINS);
1246
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);
1253         }
1254         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1255                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1256
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);
1263         }
1264
1265         /* add BUILTIN\Administrators as FULL CONTROL */
1266
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);
1274
1275         /* add BUILTIN\Print Operators as FULL CONTROL */
1276
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);
1284
1285         /* Make the security descriptor owned by the BUILTIN\Administrators */
1286
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
1290            NT5 machine. */
1291
1292         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1293                 psd = make_sec_desc(mem_ctx,
1294                                     SD_REVISION,
1295                                     SEC_DESC_SELF_RELATIVE,
1296                                     &global_sid_Builtin_Administrators,
1297                                     &global_sid_Builtin_Administrators,
1298                                     NULL,
1299                                     psa,
1300                                     &sd_size);
1301         }
1302
1303         if (psd == NULL) {
1304                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1305                 return WERR_NOMEM;
1306         }
1307
1308         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1309                  (unsigned int)sd_size));
1310
1311         *secdesc = psd;
1312
1313         return WERR_OK;
1314 }
1315
1316 #ifdef HAVE_ADS
1317 /*****************************************************************
1318  ****************************************************************/
1319
1320 static void store_printer_guid(const char *printer, struct GUID guid)
1321 {
1322         TALLOC_CTX *tmp_ctx;
1323         struct auth_serversupplied_info *server_info = NULL;
1324         const char *guid_str;
1325         DATA_BLOB blob;
1326         NTSTATUS status;
1327         WERROR result;
1328
1329         tmp_ctx = talloc_new(NULL);
1330         if (!tmp_ctx) {
1331                 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1332                 return;
1333         }
1334
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"));
1339                 goto done;
1340         }
1341
1342         guid_str = GUID_string(tmp_ctx, &guid);
1343         if (!guid_str) {
1344                 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
1345                 goto done;
1346         }
1347
1348         /* We used to store this as a REG_BINARY but that causes
1349            Vista to whine */
1350
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",
1354                           guid_str));
1355                 goto done;
1356         }
1357
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));
1364         }
1365
1366 done:
1367         talloc_free(tmp_ctx);
1368 }
1369
1370 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
1371                                      struct spoolss_PrinterInfo2 *pinfo2)
1372 {
1373         ADS_STATUS ads_rc;
1374         LDAPMessage *res;
1375         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
1376         char *srv_dn_utf8, **srv_cn_utf8;
1377         TALLOC_CTX *ctx;
1378         ADS_MODLIST mods;
1379         const char *attrs[] = {"objectGUID", NULL};
1380         struct GUID guid;
1381         WERROR win_rc = WERR_OK;
1382         size_t converted_size;
1383         const char *printer = pinfo2->sharename;
1384
1385         /* build the ads mods */
1386         ctx = talloc_init("nt_printer_publish_ads");
1387         if (ctx == NULL) {
1388                 return WERR_NOMEM;
1389         }
1390
1391         DEBUG(5, ("publishing printer %s\n", printer));
1392
1393         /* figure out where to publish */
1394         ads_find_machine_acct(ads, &res, global_myname());
1395
1396         /* We use ldap_get_dn here as we need the answer
1397          * in utf8 to call ldap_explode_dn(). JRA. */
1398
1399         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1400         if (!srv_dn_utf8) {
1401                 TALLOC_FREE(ctx);
1402                 return WERR_SERVER_UNAVAILABLE;
1403         }
1404         ads_msgfree(ads, res);
1405         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
1406         if (!srv_cn_utf8) {
1407                 TALLOC_FREE(ctx);
1408                 ldap_memfree(srv_dn_utf8);
1409                 return WERR_SERVER_UNAVAILABLE;
1410         }
1411         /* Now convert to CH_UNIX. */
1412         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
1413                 TALLOC_FREE(ctx);
1414                 ldap_memfree(srv_dn_utf8);
1415                 ldap_memfree(srv_cn_utf8);
1416                 return WERR_SERVER_UNAVAILABLE;
1417         }
1418         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
1419                 TALLOC_FREE(ctx);
1420                 ldap_memfree(srv_dn_utf8);
1421                 ldap_memfree(srv_cn_utf8);
1422                 TALLOC_FREE(srv_dn);
1423                 return WERR_SERVER_UNAVAILABLE;
1424         }
1425
1426         ldap_memfree(srv_dn_utf8);
1427         ldap_memfree(srv_cn_utf8);
1428
1429         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
1430         if (!srv_cn_escaped) {
1431                 TALLOC_FREE(ctx);
1432                 return WERR_SERVER_UNAVAILABLE;
1433         }
1434         sharename_escaped = escape_rdn_val_string_alloc(printer);
1435         if (!sharename_escaped) {
1436                 SAFE_FREE(srv_cn_escaped);
1437                 TALLOC_FREE(ctx);
1438                 return WERR_SERVER_UNAVAILABLE;
1439         }
1440
1441         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
1442
1443         SAFE_FREE(srv_cn_escaped);
1444         SAFE_FREE(sharename_escaped);
1445
1446         mods = ads_init_mods(ctx);
1447
1448         if (mods == NULL) {
1449                 SAFE_FREE(prt_dn);
1450                 TALLOC_FREE(ctx);
1451                 return WERR_NOMEM;
1452         }
1453
1454         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
1455
1456         /* publish it */
1457         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
1458         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
1459                 int i;
1460                 for (i=0; mods[i] != 0; i++)
1461                         ;
1462                 mods[i] = (LDAPMod *)-1;
1463                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
1464         }
1465
1466         if (!ADS_ERR_OK(ads_rc)) {
1467                 DEBUG(3, ("error publishing %s: %s\n",
1468                           printer, ads_errstr(ads_rc)));
1469         }
1470
1471         /* retreive the guid and store it locally */
1472         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
1473                 ZERO_STRUCT(guid);
1474                 ads_pull_guid(ads, res, &guid);
1475                 ads_msgfree(ads, res);
1476                 store_printer_guid(printer, guid);
1477         }
1478         TALLOC_FREE(ctx);
1479
1480         return win_rc;
1481 }
1482
1483 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
1484                                        const char *printer)
1485 {
1486         ADS_STATUS ads_rc;
1487         LDAPMessage *res = NULL;
1488         char *prt_dn = NULL;
1489
1490         DEBUG(5, ("unpublishing printer %s\n", printer));
1491
1492         /* remove the printer from the directory */
1493         ads_rc = ads_find_printer_on_server(ads, &res,
1494                                             printer, global_myname());
1495
1496         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
1497                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
1498                 if (!prt_dn) {
1499                         ads_msgfree(ads, res);
1500                         return WERR_NOMEM;
1501                 }
1502                 ads_rc = ads_del_dn(ads, prt_dn);
1503                 TALLOC_FREE(prt_dn);
1504         }
1505
1506         if (res) {
1507                 ads_msgfree(ads, res);
1508         }
1509         return WERR_OK;
1510 }
1511
1512 /****************************************************************************
1513  * Publish a printer in the directory
1514  *
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  ***************************************************************************/
1521
1522 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
1523                           struct auth_serversupplied_info *server_info,
1524                           struct spoolss_PrinterInfo2 *pinfo2,
1525                           int action)
1526 {
1527         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
1528         struct spoolss_SetPrinterInfo2 *sinfo2;
1529         ADS_STATUS ads_rc;
1530         ADS_STRUCT *ads = NULL;
1531         WERROR win_rc;
1532
1533         sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
1534         if (!sinfo2) {
1535                 return WERR_NOMEM;
1536         }
1537
1538         switch (action) {
1539         case DSPRINT_PUBLISH:
1540         case DSPRINT_UPDATE:
1541                 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
1542                 break;
1543         case DSPRINT_UNPUBLISH:
1544                 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
1545                 break;
1546         default:
1547                 win_rc = WERR_NOT_SUPPORTED;
1548                 goto done;
1549         }
1550
1551         sinfo2->attributes = pinfo2->attributes;
1552
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)));
1558                 goto done;
1559         }
1560
1561         TALLOC_FREE(sinfo2);
1562
1563         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
1564         if (!ads) {
1565                 DEBUG(3, ("ads_init() failed\n"));
1566                 win_rc = WERR_SERVER_UNAVAILABLE;
1567                 goto done;
1568         }
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(),
1572                 NULL, NULL);
1573
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;
1579                 goto done;
1580         }
1581
1582         switch (action) {
1583         case DSPRINT_PUBLISH:
1584         case DSPRINT_UPDATE:
1585                 win_rc = nt_printer_publish_ads(ads, pinfo2);
1586                 break;
1587         case DSPRINT_UNPUBLISH:
1588                 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
1589                 break;
1590         }
1591
1592 done:
1593         ads_destroy(&ads);
1594         return win_rc;
1595 }
1596
1597 WERROR check_published_printers(void)
1598 {
1599         ADS_STATUS ads_rc;
1600         ADS_STRUCT *ads = NULL;
1601         int snum;
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;
1606         NTSTATUS status;
1607         WERROR result;
1608
1609         tmp_ctx = talloc_new(NULL);
1610         if (!tmp_ctx) return WERR_NOMEM;
1611
1612         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
1613         if (!ads) {
1614                 DEBUG(3, ("ads_init() failed\n"));
1615                 return WERR_SERVER_UNAVAILABLE;
1616         }
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(),
1620                 NULL, NULL);
1621
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;
1627                 goto done;
1628         }
1629
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;
1635                 goto done;
1636         }
1637
1638         for (snum = 0; snum < n_services; snum++) {
1639                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1640                         continue;
1641                 }
1642
1643                 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1644                                             lp_servicename(snum), &pinfo2);
1645                 if (!W_ERROR_IS_OK(result)) {
1646                         continue;
1647                 }
1648
1649                 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
1650                         nt_printer_publish_ads(ads, pinfo2);
1651                 }
1652
1653                 TALLOC_FREE(pinfo2);
1654         }
1655
1656         result = WERR_OK;
1657 done:
1658         ads_destroy(&ads);
1659         ads_kdestroy("MEMORY:prtpub_cache");
1660         talloc_free(tmp_ctx);
1661         return result;
1662 }
1663
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)
1668 {
1669         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1670         enum winreg_Type type;
1671         uint8_t *data;
1672         uint32_t data_size;
1673         WERROR result;
1674         NTSTATUS status;
1675
1676         result = winreg_get_printer(mem_ctx, server_info,
1677                                     servername, printer, &pinfo2);
1678         if (!W_ERROR_IS_OK(result)) {
1679                 return false;
1680         }
1681
1682         if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
1683                 TALLOC_FREE(pinfo2);
1684                 return false;
1685         }
1686
1687         if (!guid) {
1688                 goto done;
1689         }
1690
1691         /* fetching printer guids really ought to be a separate function. */
1692
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);
1698                 return false;
1699         }
1700
1701         /* We used to store the guid as REG_BINARY, then swapped
1702            to REG_SZ for Vista compatibility so check for both */
1703
1704         switch (type) {
1705         case REG_SZ:
1706                 status = GUID_from_string((char *)data, guid);
1707                 if (!NT_STATUS_IS_OK(status)) {
1708                         TALLOC_FREE(pinfo2);
1709                         return false;
1710                 }
1711                 break;
1712
1713         case REG_BINARY:
1714                 if (data_size != sizeof(struct GUID)) {
1715                         TALLOC_FREE(pinfo2);
1716                         return false;
1717                 }
1718                 memcpy(guid, data, sizeof(struct GUID));
1719                 break;
1720         default:
1721                 DEBUG(0,("is_printer_published: GUID value stored as "
1722                          "invaluid type (%d)\n", type));
1723                 break;
1724         }
1725
1726 done:
1727         if (info2) {
1728                 *info2 = talloc_move(mem_ctx, &pinfo2);
1729         }
1730         talloc_free(pinfo2);
1731         return true;
1732 }
1733 #else
1734 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
1735                           struct auth_serversupplied_info *server_info,
1736                           struct spoolss_PrinterInfo2 *pinfo2,
1737                           int action)
1738 {
1739         return WERR_OK;
1740 }
1741
1742 WERROR check_published_printers(void)
1743 {
1744         return WERR_OK;
1745 }
1746
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)
1751 {
1752         return False;
1753 }
1754 #endif /* HAVE_ADS */
1755
1756 /****************************************************************************
1757  ***************************************************************************/
1758
1759 static char *win_driver;
1760 static char *os2_driver;
1761
1762 static const char *get_win_driver(void)
1763 {
1764         if (win_driver == NULL) {
1765                 return "";
1766         }
1767         return win_driver;
1768 }
1769
1770 static const char *get_os2_driver(void)
1771 {
1772         if (os2_driver == NULL) {
1773                 return "";
1774         }
1775         return os2_driver;
1776 }
1777
1778 static bool set_driver_mapping(const char *from, const char *to)
1779 {
1780         SAFE_FREE(win_driver);
1781         SAFE_FREE(os2_driver);
1782
1783         win_driver = SMB_STRDUP(from);
1784         os2_driver = SMB_STRDUP(to);
1785
1786         if (win_driver == NULL || os2_driver == NULL) {
1787                 SAFE_FREE(win_driver);
1788                 SAFE_FREE(os2_driver);
1789                 return false;
1790         }
1791         return true;
1792 }
1793
1794 /**
1795  * @internal
1796  *
1797  * @brief Map a Windows driver to a OS/2 driver.
1798  *
1799  * @param[in]  mem_ctx  The memory context to use.
1800  *
1801  * @param[in,out] pdrivername The drivername of Windows to remap.
1802  *
1803  * @return              WERR_OK on success, a corresponding WERROR on failure.
1804  */
1805 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1806 {
1807         const char *mapfile = lp_os2_driver_map();
1808         char **lines = NULL;
1809         const char *drivername;
1810         int numlines = 0;
1811         int i;
1812
1813         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1814                 return WERR_INVALID_PARAMETER;
1815         }
1816
1817         drivername = *pdrivername;
1818
1819         if (mapfile[0] == '\0') {
1820                 return WERR_BADFILE;
1821         }
1822
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) {
1828                         return WERR_NOMEM;
1829                 }
1830                 *pdrivername = drivername;
1831                 return WERR_OK;
1832         }
1833
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));
1837                 TALLOC_FREE(lines);
1838                 return WERR_EMPTY;
1839         }
1840
1841         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1842
1843         for( i = 0; i < numlines; i++) {
1844                 char *nt_name = lines[i];
1845                 char *os2_name = strchr(nt_name, '=');
1846
1847                 if (os2_name == NULL) {
1848                         continue;
1849                 }
1850
1851                 *os2_name++ = '\0';
1852
1853                 while (isspace(*nt_name)) {
1854                         nt_name++;
1855                 }
1856
1857                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1858                         continue;
1859                 }
1860
1861                 {
1862                         int l = strlen(nt_name);
1863                         while (l && isspace(nt_name[l - 1])) {
1864                                 nt_name[l - 1] = 0;
1865                                 l--;
1866                         }
1867                 }
1868
1869                 while (isspace(*os2_name)) {
1870                         os2_name++;
1871                 }
1872
1873                 {
1874                         int l = strlen(os2_name);
1875                         while (l && isspace(os2_name[l-1])) {
1876                                 os2_name[l-1] = 0;
1877                                 l--;
1878                         }
1879                 }
1880
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);
1885                         TALLOC_FREE(lines);
1886                         if (drivername == NULL) {
1887                                 return WERR_NOMEM;
1888                         }
1889                         *pdrivername = drivername;
1890                         return WERR_OK;
1891                 }
1892         }
1893
1894         TALLOC_FREE(lines);
1895         return WERR_OK;
1896 }
1897
1898 /****************************************************************************
1899 ****************************************************************************/
1900
1901 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1902                               struct spoolss_DriverInfo8 *_info8)
1903 {
1904         struct spoolss_DriverInfo8 info8;
1905
1906         ZERO_STRUCT(info8);
1907
1908         switch (r->level) {
1909         case 3:
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;
1921                 }
1922                 break;
1923         case 6:
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;
1935                 }
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;
1942                 break;
1943         case 8:
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;
1955                 }
1956                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1957                         info8.previous_names    = r->info.info8->previous_names->string;
1958                 }
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;
1969                 }
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;
1974                 }
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;
1977                 break;
1978         default:
1979                 return false;
1980         }
1981
1982         *_info8 = info8;
1983
1984         return true;
1985 }
1986
1987
1988 /****************************************************************************
1989   Determine whether or not a particular driver is currently assigned
1990   to a printer
1991 ****************************************************************************/
1992
1993 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1994                            struct auth_serversupplied_info *server_info,
1995                            const struct spoolss_DriverInfo8 *r)
1996 {
1997         int snum;
1998         int n_services = lp_numservices();
1999         bool in_use = False;
2000         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2001         WERROR result;
2002
2003         if (!r) {
2004                 return false;
2005         }
2006
2007         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
2008
2009         /* loop through the printers.tdb and check for the drivername */
2010
2011         for (snum=0; snum<n_services && !in_use; snum++) {
2012                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
2013                         continue;
2014                 }
2015
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 */
2020                 }
2021
2022                 if (strequal(r->driver_name, pinfo2->drivername)) {
2023                         in_use = True;
2024                 }
2025
2026                 TALLOC_FREE(pinfo2);
2027         }
2028
2029         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
2030
2031         if ( in_use ) {
2032                 struct spoolss_DriverInfo8 *driver;
2033                 WERROR werr;
2034
2035                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
2036
2037                 /* we can still remove the driver if there is one of
2038                    "Windows NT x86" version 2 or 3 left */
2039
2040                 if (!strequal("Windows NT x86", r->architecture)) {
2041                         werr = winreg_get_driver(mem_ctx, server_info,
2042                                                  "Windows NT x86",
2043                                                  r->driver_name,
2044                                                  DRIVER_ANY_VERSION,
2045                                                  &driver);
2046                 } else if (r->version == 2) {
2047                         werr = winreg_get_driver(mem_ctx, server_info,
2048                                                  "Windows NT x86",
2049                                                  r->driver_name,
2050                                                  3, &driver);
2051                 } else if (r->version == 3) {
2052                         werr = winreg_get_driver(mem_ctx, server_info,
2053                                                  "Windows NT x86",
2054                                                  r->driver_name,
2055                                                  2, &driver);
2056                 } else {
2057                         DEBUG(0, ("printer_driver_in_use: ERROR!"
2058                                   " unknown driver version (%d)\n",
2059                                   r->version));
2060                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
2061                 }
2062
2063                 /* now check the error code */
2064
2065                 if ( W_ERROR_IS_OK(werr) ) {
2066                         /* it's ok to remove the driver, we have other architctures left */
2067                         in_use = False;
2068                         talloc_free(driver);
2069                 }
2070         }
2071
2072         /* report that the driver is not in use by default */
2073
2074         return in_use;
2075 }
2076
2077
2078 /**********************************************************************
2079  Check to see if a ogiven file is in use by *info
2080  *********************************************************************/
2081
2082 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
2083 {
2084         int i = 0;
2085
2086         if ( !info )
2087                 return False;
2088
2089         /* mz: skip files that are in the list but already deleted */
2090         if (!file || !file[0]) {
2091                 return false;
2092         }
2093
2094         if (strequal(file, info->driver_path))
2095                 return True;
2096
2097         if (strequal(file, info->data_file))
2098                 return True;
2099
2100         if (strequal(file, info->config_file))
2101                 return True;
2102
2103         if (strequal(file, info->help_file))
2104                 return True;
2105
2106         /* see of there are any dependent files to examine */
2107
2108         if (!info->dependent_files)
2109                 return False;
2110
2111         while (info->dependent_files[i] && *info->dependent_files[i]) {
2112                 if (strequal(file, info->dependent_files[i]))
2113                         return True;
2114                 i++;
2115         }
2116
2117         return False;
2118
2119 }
2120
2121 /**********************************************************************
2122  Utility function to remove the dependent file pointed to by the
2123  input parameter from the list
2124  *********************************************************************/
2125
2126 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
2127 {
2128
2129         /* bump everything down a slot */
2130
2131         while (files && files[idx+1]) {
2132                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
2133                 idx++;
2134         }
2135
2136         files[idx] = NULL;
2137
2138         return;
2139 }
2140
2141 /**********************************************************************
2142  Check if any of the files used by src are also used by drv
2143  *********************************************************************/
2144
2145 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
2146                                    struct spoolss_DriverInfo8 *src,
2147                                    const struct spoolss_DriverInfo8 *drv)
2148 {
2149         bool    in_use = False;
2150         int     i = 0;
2151
2152         if ( !src || !drv )
2153                 return False;
2154
2155         /* check each file.  Remove it from the src structure if it overlaps */
2156
2157         if (drv_file_in_use(src->driver_path, drv)) {
2158                 in_use = True;
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; }
2162         }
2163
2164         if (drv_file_in_use(src->data_file, drv)) {
2165                 in_use = True;
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; }
2169         }
2170
2171         if (drv_file_in_use(src->config_file, drv)) {
2172                 in_use = True;
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; }
2176         }
2177
2178         if (drv_file_in_use(src->help_file, drv)) {
2179                 in_use = True;
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; }
2183         }
2184
2185         /* are there any dependentfiles to examine? */
2186
2187         if (!src->dependent_files)
2188                 return in_use;
2189
2190         while (src->dependent_files[i] && *src->dependent_files[i]) {
2191                 if (drv_file_in_use(src->dependent_files[i], drv)) {
2192                         in_use = True;
2193                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
2194                         trim_dependent_file(mem_ctx, src->dependent_files, i);
2195                 } else
2196                         i++;
2197         }
2198
2199         return in_use;
2200 }
2201
2202 /****************************************************************************
2203   Determine whether or not a particular driver files are currently being
2204   used by any other driver.
2205
2206   Return value is True if any files were in use by other drivers
2207   and False otherwise.
2208
2209   Upon return, *info has been modified to only contain the driver files
2210   which are not in use
2211
2212   Fix from mz:
2213
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
2216   match.
2217 ****************************************************************************/
2218
2219 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
2220                                  struct auth_serversupplied_info *server_info,
2221                                  struct spoolss_DriverInfo8 *info)
2222 {
2223         int                             i;
2224         uint32                          version;
2225         struct spoolss_DriverInfo8      *driver;
2226         bool in_use = false;
2227         uint32_t num_drivers;
2228         const char **drivers;
2229         WERROR result;
2230
2231         if ( !info )
2232                 return False;
2233
2234         version = info->version;
2235
2236         /* loop over all driver versions */
2237
2238         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
2239
2240         /* get the list of drivers */
2241
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)) {
2246                 return true;
2247         }
2248
2249         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
2250                      num_drivers, info->architecture, version));
2251
2252         /* check each driver for overlap in files */
2253
2254         for (i = 0; i < num_drivers; i++) {
2255                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
2256
2257                 driver = NULL;
2258
2259                 result = winreg_get_driver(mem_ctx, server_info,
2260                                            info->architecture, drivers[i],
2261                                            version, &driver);
2262                 if (!W_ERROR_IS_OK(result)) {
2263                         talloc_free(drivers);
2264                         return True;
2265                 }
2266
2267                 /* check if d2 uses any files from d1 */
2268                 /* only if this is a different driver than the one being deleted */
2269
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. */
2275                                 in_use = true;
2276                         }
2277                 }
2278
2279                 talloc_free(driver);
2280         }
2281
2282         talloc_free(drivers);
2283
2284         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2285
2286         return in_use;
2287 }
2288
2289 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2290                                         const char *name)
2291 {
2292         struct smb_filename *smb_fname = NULL;
2293         NTSTATUS status;
2294
2295         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
2296             &smb_fname);
2297         if (!NT_STATUS_IS_OK(status)) {
2298                 return status;
2299         }
2300
2301         status = unlink_internals(conn, NULL, 0, smb_fname, false);
2302
2303         TALLOC_FREE(smb_fname);
2304         return status;
2305 }
2306
2307 /****************************************************************************
2308   Actually delete the driver files.  Make sure that
2309   printer_driver_files_in_use() return False before calling
2310   this.
2311 ****************************************************************************/
2312
2313 bool delete_driver_files(struct auth_serversupplied_info *server_info,
2314                          const struct spoolss_DriverInfo8 *r)
2315 {
2316         int i = 0;
2317         char *s;
2318         const char *file;
2319         connection_struct *conn;
2320         NTSTATUS nt_status;
2321         char *oldcwd;
2322         fstring printdollar;
2323         int printdollar_snum;
2324         bool ret = false;
2325
2326         if (!r) {
2327                 return false;
2328         }
2329
2330         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2331                 r->driver_name, r->version));
2332
2333         fstrcpy(printdollar, "print$");
2334
2335         printdollar_snum = find_service(printdollar);
2336         if (printdollar_snum == -1) {
2337                 return false;
2338         }
2339
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)));
2346                 return false;
2347         }
2348
2349         if ( !CAN_WRITE(conn) ) {
2350                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2351                 goto fail;
2352         }
2353
2354         /* now delete the files; must strip the '\print$' string from
2355            fron of path                                                */
2356
2357         if (r->driver_path && r->driver_path[0]) {
2358                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
2359                         file = s;
2360                         DEBUG(10,("deleting driverfile [%s]\n", s));
2361                         driver_unlink_internals(conn, file);
2362                 }
2363         }
2364
2365         if (r->config_file && r->config_file[0]) {
2366                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
2367                         file = s;
2368                         DEBUG(10,("deleting configfile [%s]\n", s));
2369                         driver_unlink_internals(conn, file);
2370                 }
2371         }
2372
2373         if (r->data_file && r->data_file[0]) {
2374                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
2375                         file = s;
2376                         DEBUG(10,("deleting datafile [%s]\n", s));
2377                         driver_unlink_internals(conn, file);
2378                 }
2379         }
2380
2381         if (r->help_file && r->help_file[0]) {
2382                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
2383                         file = s;
2384                         DEBUG(10,("deleting helpfile [%s]\n", s));
2385                         driver_unlink_internals(conn, file);
2386                 }
2387         }
2388
2389         /* check if we are done removing files */
2390
2391         if (r->dependent_files) {
2392                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2393                         char *p;
2394
2395                         /* bypass the "\print$" portion of the path */
2396
2397                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2398                                 file = p;
2399                                 DEBUG(10,("deleting dependent file [%s]\n", file));
2400                                 driver_unlink_internals(conn, file);
2401                         }
2402
2403                         i++;
2404                 }
2405         }
2406
2407         goto done;
2408  fail:
2409         ret = false;
2410  done:
2411         if (conn != NULL) {
2412                 vfs_ChDir(conn, oldcwd);
2413                 conn_free(conn);
2414         }
2415         return ret;
2416 }
2417
2418 /* error code:
2419         0: everything OK
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
2425 */
2426
2427 /*
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 !
2431
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 :-).
2436
2437         If the /usr/local/samba/lib directory (default dir), you will have
2438         5 files to describe all of this.
2439
2440         3 files for the printers (1 by printer):
2441                 NTprinter_laser A
2442                 NTprinter_laser B
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
2447
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 :-)
2451
2452 */
2453
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. */
2457
2458 void map_printer_permissions(struct security_descriptor *sd)
2459 {
2460         int i;
2461
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);
2465         }
2466 }
2467
2468 void map_job_permissions(struct security_descriptor *sd)
2469 {
2470         int i;
2471
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);
2475         }
2476 }
2477
2478
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.
2483
2484    PRINTER_ACCESS_ADMINISTER:
2485        print_queue_pause, print_queue_resume, update_printer_sec,
2486        update_printer, spoolss_addprinterex_level_2,
2487        _spoolss_setprinterdata
2488
2489    PRINTER_ACCESS_USE:
2490        print_job_start
2491
2492    JOB_ACCESS_ADMINISTER:
2493        print_job_delete, print_job_pause, print_job_resume,
2494        print_queue_purge
2495
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)
2500
2501  ****************************************************************************/
2502 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
2503                         int access_type)
2504 {
2505         struct spoolss_security_descriptor *secdesc = NULL;
2506         uint32 access_granted;
2507         size_t sd_size;
2508         NTSTATUS status;
2509         WERROR result;
2510         const char *pname;
2511         TALLOC_CTX *mem_ctx = NULL;
2512         SE_PRIV se_printop = SE_PRINT_OPERATOR;
2513
2514         /* If user is NULL then use the current_user structure */
2515
2516         /* Always allow root or SE_PRINT_OPERATROR to do anything */
2517
2518         if (server_info->utok.uid == sec_initial_uid()
2519             || user_has_privileges(server_info->ptok, &se_printop ) ) {
2520                 return True;
2521         }
2522
2523         /* Get printer name */
2524
2525         pname = lp_printername(snum);
2526
2527         if (!pname || !*pname) {
2528                 errno = EACCES;
2529                 return False;
2530         }
2531
2532         /* Get printer security descriptor */
2533
2534         if(!(mem_ctx = talloc_init("print_access_check"))) {
2535                 errno = ENOMEM;
2536                 return False;
2537         }
2538
2539         result = winreg_get_printer_secdesc(mem_ctx,
2540                                             server_info,
2541                                             pname,
2542                                             &secdesc);
2543         if (!W_ERROR_IS_OK(result)) {
2544                 talloc_destroy(mem_ctx);
2545                 errno = ENOMEM;
2546                 return False;
2547         }
2548
2549         if (access_type == JOB_ACCESS_ADMINISTER) {
2550                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2551
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,
2556                                                  &secdesc,
2557                                                  &sd_size,
2558                                                  parent_secdesc,
2559                                                  parent_secdesc->owner_sid,
2560                                                  parent_secdesc->group_sid,
2561                                                  false);
2562                 if (!NT_STATUS_IS_OK(status)) {
2563                         talloc_destroy(mem_ctx);
2564                         errno = map_errno_from_nt_status(status);
2565                         return False;
2566                 }
2567
2568                 map_job_permissions(secdesc);
2569         } else {
2570                 map_printer_permissions(secdesc);
2571         }
2572
2573         /* Check access */
2574         status = se_access_check(secdesc, server_info->ptok, access_type,
2575                                  &access_granted);
2576
2577         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2578
2579         /* see if we need to try the printer admin list */
2580
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);
2587                 return True;
2588         }
2589
2590         talloc_destroy(mem_ctx);
2591
2592         if (!NT_STATUS_IS_OK(status)) {
2593                 errno = EACCES;
2594         }
2595
2596         return NT_STATUS_IS_OK(status);
2597 }
2598
2599 /****************************************************************************
2600  Check the time parameters allow a print operation.
2601 *****************************************************************************/
2602
2603 bool print_time_access_check(struct auth_serversupplied_info *server_info,
2604                              const char *servicename)
2605 {
2606         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2607         WERROR result;
2608         bool ok = False;
2609         time_t now = time(NULL);
2610         struct tm *t;
2611         uint32 mins;
2612
2613         result = winreg_get_printer(NULL, server_info,
2614                                     NULL, servicename, &pinfo2);
2615         if (!W_ERROR_IS_OK(result)) {
2616                 return False;
2617         }
2618
2619         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2620                 ok = True;
2621         }
2622
2623         t = gmtime(&now);
2624         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2625
2626         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2627                 ok = True;
2628         }
2629
2630         TALLOC_FREE(pinfo2);
2631
2632         if (!ok) {
2633                 errno = EACCES;
2634         }
2635
2636         return ok;
2637 }
2638
2639 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2640                         struct auth_serversupplied_info *server_info,
2641                         const char *printer)
2642 {
2643         WERROR result;
2644
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",
2648                           printer));
2649         }
2650 }