af790203d2f8818b8e9d20a1600ea76678f545ae
[samba.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/spoolss/srv_spoolss_util.h"
32 #include "nt_printing.h"
33 #include "secrets.h"
34 #include "../librpc/gen_ndr/netlogon.h"
35 #include "../libcli/security/security.h"
36 #include "passdb/machine_sid.h"
37 #include "smbd/smbd.h"
38
39 /* Map generic permissions to printer object specific permissions */
40
41 const struct generic_mapping printer_generic_mapping = {
42         PRINTER_READ,
43         PRINTER_WRITE,
44         PRINTER_EXECUTE,
45         PRINTER_ALL_ACCESS
46 };
47
48 /* Map generic permissions to print server object specific permissions */
49
50 const struct generic_mapping printserver_generic_mapping = {
51         SERVER_READ,
52         SERVER_WRITE,
53         SERVER_EXECUTE,
54         SERVER_ALL_ACCESS
55 };
56
57 /* Map generic permissions to job object specific permissions */
58
59 const struct generic_mapping job_generic_mapping = {
60         JOB_READ,
61         JOB_WRITE,
62         JOB_EXECUTE,
63         JOB_ALL_ACCESS
64 };
65
66 static const struct print_architecture_table_node archi_table[]= {
67
68         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
69         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
70         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
71         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
72         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
73         {"Windows IA64",         SPL_ARCH_IA64,         3 },
74         {"Windows x64",          SPL_ARCH_X64,          3 },
75         {NULL,                   "",            -1 }
76 };
77
78 /****************************************************************************
79  Open the NT printing tdbs. Done once before fork().
80 ****************************************************************************/
81
82 bool nt_printing_init(struct messaging_context *msg_ctx)
83 {
84         WERROR win_rc;
85
86         if (!nt_printing_tdb_upgrade()) {
87                 return false;
88         }
89
90         /*
91          * register callback to handle updating printers as new
92          * drivers are installed
93          */
94         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
95                            do_drv_upgrade_printer);
96
97         /* of course, none of the message callbacks matter if you don't
98            tell messages.c that you interested in receiving PRINT_GENERAL
99            msgs.  This is done in serverid_register() */
100
101         if ( lp_security() == SEC_ADS ) {
102                 win_rc = check_published_printers(msg_ctx);
103                 if (!W_ERROR_IS_OK(win_rc))
104                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
105         }
106
107         return true;
108 }
109
110 /*******************************************************************
111  Function to allow filename parsing "the old way".
112 ********************************************************************/
113
114 static NTSTATUS driver_unix_convert(connection_struct *conn,
115                                     const char *old_name,
116                                     struct smb_filename **smb_fname)
117 {
118         NTSTATUS status;
119         TALLOC_CTX *ctx = talloc_tos();
120         char *name = talloc_strdup(ctx, old_name);
121
122         if (!name) {
123                 return NT_STATUS_NO_MEMORY;
124         }
125         unix_format(name);
126         name = unix_clean_name(ctx, name);
127         if (!name) {
128                 return NT_STATUS_NO_MEMORY;
129         }
130         trim_string(name,"/","/");
131
132         status = unix_convert(ctx, conn, name, smb_fname, 0);
133         if (!NT_STATUS_IS_OK(status)) {
134                 return NT_STATUS_NO_MEMORY;
135         }
136
137         return NT_STATUS_OK;
138 }
139
140 /****************************************************************************
141  Function to do the mapping between the long architecture name and
142  the short one.
143 ****************************************************************************/
144
145 const char *get_short_archi(const char *long_archi)
146 {
147         int i=-1;
148
149         DEBUG(107,("Getting architecture dependent directory\n"));
150         do {
151                 i++;
152         } while ( (archi_table[i].long_archi!=NULL ) &&
153                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
154
155         if (archi_table[i].long_archi==NULL) {
156                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
157                 return NULL;
158         }
159
160         /* this might be client code - but shouldn't this be an fstrcpy etc? */
161
162         DEBUGADD(108,("index: [%d]\n", i));
163         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
164         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
165
166         return archi_table[i].short_archi;
167 }
168
169 /****************************************************************************
170  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
171  There are two case to be covered here: PE (Portable Executable) and NE (New
172  Executable) files. Both files support the same INFO structure, but PE files
173  store the signature in unicode, and NE files store it as !unicode.
174  returns -1 on error, 1 on version info found, and 0 on no version info found.
175 ****************************************************************************/
176
177 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
178 {
179         int     i;
180         char    *buf = NULL;
181         ssize_t byte_count;
182
183         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
184                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
185                                 fname, DOS_HEADER_SIZE));
186                 goto error_exit;
187         }
188
189         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
190                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
191                          fname, (unsigned long)byte_count));
192                 goto no_version_info;
193         }
194
195         /* Is this really a DOS header? */
196         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
197                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
198                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
199                 goto no_version_info;
200         }
201
202         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
203         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
204                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
205                                 fname, errno));
206                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
207                 goto no_version_info;
208         }
209
210         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
211         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
212                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
213                          fname, (unsigned long)byte_count));
214                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
215                 goto no_version_info;
216         }
217
218         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
219         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
220                 unsigned int num_sections;
221                 unsigned int section_table_bytes;
222
223                 /* Just skip over optional header to get to section table */
224                 if (SMB_VFS_LSEEK(fsp,
225                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
226                                 SEEK_CUR) == (SMB_OFF_T)-1) {
227                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
228                                 fname, errno));
229                         goto error_exit;
230                 }
231
232                 /* get the section table */
233                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
234                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
235                 if (section_table_bytes == 0)
236                         goto error_exit;
237
238                 SAFE_FREE(buf);
239                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
240                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
241                                         fname, section_table_bytes));
242                         goto error_exit;
243                 }
244
245                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
246                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
247                                  fname, (unsigned long)byte_count));
248                         goto error_exit;
249                 }
250
251                 /* Iterate the section table looking for the resource section ".rsrc" */
252                 for (i = 0; i < num_sections; i++) {
253                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
254
255                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
256                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
257                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
258
259                                 if (section_bytes == 0)
260                                         goto error_exit;
261
262                                 SAFE_FREE(buf);
263                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
264                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
265                                                         fname, section_bytes));
266                                         goto error_exit;
267                                 }
268
269                                 /* Seek to the start of the .rsrc section info */
270                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
271                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
272                                                         fname, errno));
273                                         goto error_exit;
274                                 }
275
276                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
277                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
278                                                  fname, (unsigned long)byte_count));
279                                         goto error_exit;
280                                 }
281
282                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
283                                         goto error_exit;
284
285                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
286                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
287                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
288                                                 /* Align to next long address */
289                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
290
291                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
292                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
293                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
294
295                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
296                                                                           fname, *major, *minor,
297                                                                           (*major>>16)&0xffff, *major&0xffff,
298                                                                           (*minor>>16)&0xffff, *minor&0xffff));
299                                                         SAFE_FREE(buf);
300                                                         return 1;
301                                                 }
302                                         }
303                                 }
304                         }
305                 }
306
307                 /* Version info not found, fall back to origin date/time */
308                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
309                 SAFE_FREE(buf);
310                 return 0;
311
312         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
313                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
314                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
315                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
316                         /* At this point, we assume the file is in error. It still could be somthing
317                          * else besides a NE file, but it unlikely at this point. */
318                         goto error_exit;
319                 }
320
321                 /* Allocate a bit more space to speed up things */
322                 SAFE_FREE(buf);
323                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
324                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
325                                         fname, PE_HEADER_SIZE));
326                         goto error_exit;
327                 }
328
329                 /* This is a HACK! I got tired of trying to sort through the messy
330                  * 'NE' file format. If anyone wants to clean this up please have at
331                  * it, but this works. 'NE' files will eventually fade away. JRR */
332                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
333                         /* Cover case that should not occur in a well formed 'NE' .dll file */
334                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
335
336                         for(i=0; i<byte_count; i++) {
337                                 /* Fast skip past data that can't possibly match */
338                                 if (buf[i] != 'V') continue;
339
340                                 /* Potential match data crosses buf boundry, move it to beginning
341                                  * of buf, and fill the buf with as much as it will hold. */
342                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
343                                         int bc;
344
345                                         memcpy(buf, &buf[i], byte_count-i);
346                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
347                                                                    (byte_count-i))) < 0) {
348
349                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
350                                                                  fname, errno));
351                                                 goto error_exit;
352                                         }
353
354                                         byte_count = bc + (byte_count - i);
355                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
356
357                                         i = 0;
358                                 }
359
360                                 /* Check that the full signature string and the magic number that
361                                  * follows exist (not a perfect solution, but the chances that this
362                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
363                                  * twice, as it is simpler to read the code. */
364                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
365                                         /* Compute skip alignment to next long address */
366                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
367                                                                  sizeof(VS_SIGNATURE)) & 3;
368                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
369
370                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
371                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
372                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
373                                                           fname, *major, *minor,
374                                                           (*major>>16)&0xffff, *major&0xffff,
375                                                           (*minor>>16)&0xffff, *minor&0xffff));
376                                         SAFE_FREE(buf);
377                                         return 1;
378                                 }
379                         }
380                 }
381
382                 /* Version info not found, fall back to origin date/time */
383                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
384                 SAFE_FREE(buf);
385                 return 0;
386
387         } else
388                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
389                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
390                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
391
392         no_version_info:
393                 SAFE_FREE(buf);
394                 return 0;
395
396         error_exit:
397                 SAFE_FREE(buf);
398                 return -1;
399 }
400
401 /****************************************************************************
402 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
403 share one or more files. During the MS installation process files are checked
404 to insure that only a newer version of a shared file is installed over an
405 older version. There are several possibilities for this comparison. If there
406 is no previous version, the new one is newer (obviously). If either file is
407 missing the version info structure, compare the creation date (on Unix use
408 the modification date). Otherwise chose the numerically larger version number.
409 ****************************************************************************/
410
411 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
412 {
413         bool use_version = true;
414
415         uint32 new_major;
416         uint32 new_minor;
417         time_t new_create_time;
418
419         uint32 old_major;
420         uint32 old_minor;
421         time_t old_create_time;
422
423         struct smb_filename *smb_fname = NULL;
424         files_struct    *fsp = NULL;
425         SMB_STRUCT_STAT st;
426
427         NTSTATUS status;
428         int ret;
429
430         SET_STAT_INVALID(st);
431         new_create_time = (time_t)0;
432         old_create_time = (time_t)0;
433
434         /* Get file version info (if available) for previous file (if it exists) */
435         status = driver_unix_convert(conn, old_file, &smb_fname);
436         if (!NT_STATUS_IS_OK(status)) {
437                 goto error_exit;
438         }
439
440         status = SMB_VFS_CREATE_FILE(
441                 conn,                                   /* conn */
442                 NULL,                                   /* req */
443                 0,                                      /* root_dir_fid */
444                 smb_fname,                              /* fname */
445                 FILE_GENERIC_READ,                      /* access_mask */
446                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
447                 FILE_OPEN,                              /* create_disposition*/
448                 0,                                      /* create_options */
449                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
450                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
451                 0,                                      /* allocation_size */
452                 0,                                      /* private_flags */
453                 NULL,                                   /* sd */
454                 NULL,                                   /* ea_list */
455                 &fsp,                                   /* result */
456                 NULL);                                  /* pinfo */
457
458         if (!NT_STATUS_IS_OK(status)) {
459                 /* Old file not found, so by definition new file is in fact newer */
460                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
461                           "errno = %d\n", smb_fname_str_dbg(smb_fname),
462                           errno));
463                 ret = 1;
464                 goto done;
465
466         } else {
467                 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
468                 if (ret == -1) {
469                         goto error_exit;
470                 }
471
472                 if (!ret) {
473                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
474                                          old_file));
475                         use_version = false;
476                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
477                                  goto error_exit;
478                         }
479                         old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
480                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
481                                 (long)old_create_time));
482                 }
483         }
484         close_file(NULL, fsp, NORMAL_CLOSE);
485         fsp = NULL;
486
487         /* Get file version info (if available) for new file */
488         status = driver_unix_convert(conn, new_file, &smb_fname);
489         if (!NT_STATUS_IS_OK(status)) {
490                 goto error_exit;
491         }
492
493         status = SMB_VFS_CREATE_FILE(
494                 conn,                                   /* conn */
495                 NULL,                                   /* req */
496                 0,                                      /* root_dir_fid */
497                 smb_fname,                              /* fname */
498                 FILE_GENERIC_READ,                      /* access_mask */
499                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
500                 FILE_OPEN,                              /* create_disposition*/
501                 0,                                      /* create_options */
502                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
503                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
504                 0,                                      /* allocation_size */
505                 0,                                      /* private_flags */
506                 NULL,                                   /* sd */
507                 NULL,                                   /* ea_list */
508                 &fsp,                                   /* result */
509                 NULL);                                  /* pinfo */
510
511         if (!NT_STATUS_IS_OK(status)) {
512                 /* New file not found, this shouldn't occur if the caller did its job */
513                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
514                          "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
515                 goto error_exit;
516
517         } else {
518                 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
519                 if (ret == -1) {
520                         goto error_exit;
521                 }
522
523                 if (!ret) {
524                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
525                                          new_file));
526                         use_version = false;
527                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
528                                 goto error_exit;
529                         }
530                         new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
531                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
532                                 (long)new_create_time));
533                 }
534         }
535         close_file(NULL, fsp, NORMAL_CLOSE);
536         fsp = NULL;
537
538         if (use_version && (new_major != old_major || new_minor != old_minor)) {
539                 /* Compare versions and choose the larger version number */
540                 if (new_major > old_major ||
541                         (new_major == old_major && new_minor > old_minor)) {
542
543                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
544                         ret = 1;
545                         goto done;
546                 }
547                 else {
548                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
549                         ret = 0;
550                         goto done;
551                 }
552
553         } else {
554                 /* Compare modification time/dates and choose the newest time/date */
555                 if (new_create_time > old_create_time) {
556                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
557                         ret = 1;
558                         goto done;
559                 }
560                 else {
561                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
562                         ret = 0;
563                         goto done;
564                 }
565         }
566
567  error_exit:
568         if(fsp)
569                 close_file(NULL, fsp, NORMAL_CLOSE);
570         ret = -1;
571  done:
572         TALLOC_FREE(smb_fname);
573         return ret;
574 }
575
576 /****************************************************************************
577 Determine the correct cVersion associated with an architecture and driver
578 ****************************************************************************/
579 static uint32 get_correct_cversion(struct pipes_struct *p,
580                                    const char *architecture,
581                                    const char *driverpath_in,
582                                    WERROR *perr)
583 {
584         int cversion = -1;
585         NTSTATUS          nt_status;
586         struct smb_filename *smb_fname = NULL;
587         char *driverpath = NULL;
588         files_struct      *fsp = NULL;
589         connection_struct *conn = NULL;
590         char *oldcwd;
591         char *printdollar = NULL;
592         int printdollar_snum;
593
594         *perr = WERR_INVALID_PARAM;
595
596         /* If architecture is Windows 95/98/ME, the version is always 0. */
597         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
598                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
599                 *perr = WERR_OK;
600                 return 0;
601         }
602
603         /* If architecture is Windows x64, the version is always 3. */
604         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
605                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
606                 *perr = WERR_OK;
607                 return 3;
608         }
609
610         printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
611         if (!printdollar) {
612                 *perr = WERR_NOMEM;
613                 return -1;
614         }
615         if (printdollar_snum == -1) {
616                 *perr = WERR_NO_SUCH_SHARE;
617                 return -1;
618         }
619
620         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
621                                        lp_pathname(printdollar_snum),
622                                        p->session_info, &oldcwd);
623         if (!NT_STATUS_IS_OK(nt_status)) {
624                 DEBUG(0,("get_correct_cversion: create_conn_struct "
625                          "returned %s\n", nt_errstr(nt_status)));
626                 *perr = ntstatus_to_werror(nt_status);
627                 return -1;
628         }
629
630         nt_status = set_conn_force_user_group(conn, printdollar_snum);
631         if (!NT_STATUS_IS_OK(nt_status)) {
632                 DEBUG(0, ("failed set force user / group\n"));
633                 *perr = ntstatus_to_werror(nt_status);
634                 goto error_free_conn;
635         }
636
637         if (!become_user(conn, get_current_vuid(conn))) {
638                 DEBUG(0, ("failed to become user\n"));
639                 *perr = WERR_ACCESS_DENIED;
640                 goto error_free_conn;
641         }
642
643         /* Open the driver file (Portable Executable format) and determine the
644          * deriver the cversion. */
645         driverpath = talloc_asprintf(talloc_tos(),
646                                         "%s/%s",
647                                         architecture,
648                                         driverpath_in);
649         if (!driverpath) {
650                 *perr = WERR_NOMEM;
651                 goto error_exit;
652         }
653
654         nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
655         if (!NT_STATUS_IS_OK(nt_status)) {
656                 *perr = ntstatus_to_werror(nt_status);
657                 goto error_exit;
658         }
659
660         nt_status = vfs_file_exist(conn, smb_fname);
661         if (!NT_STATUS_IS_OK(nt_status)) {
662                 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
663                 *perr = WERR_BADFILE;
664                 goto error_exit;
665         }
666
667         nt_status = SMB_VFS_CREATE_FILE(
668                 conn,                                   /* conn */
669                 NULL,                                   /* req */
670                 0,                                      /* root_dir_fid */
671                 smb_fname,                              /* fname */
672                 FILE_GENERIC_READ,                      /* access_mask */
673                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
674                 FILE_OPEN,                              /* create_disposition*/
675                 0,                                      /* create_options */
676                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
677                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
678                 0,                                      /* private_flags */
679                 0,                                      /* allocation_size */
680                 NULL,                                   /* sd */
681                 NULL,                                   /* ea_list */
682                 &fsp,                                   /* result */
683                 NULL);                                  /* pinfo */
684
685         if (!NT_STATUS_IS_OK(nt_status)) {
686                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
687                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
688                 *perr = WERR_ACCESS_DENIED;
689                 goto error_exit;
690         } else {
691                 uint32 major;
692                 uint32 minor;
693                 int    ret;
694
695                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
696                 if (ret == -1) {
697                         *perr = WERR_INVALID_PARAM;
698                         goto error_exit;
699                 } else if (!ret) {
700                         DEBUG(6,("get_correct_cversion: Version info not "
701                                  "found [%s]\n",
702                                  smb_fname_str_dbg(smb_fname)));
703                         *perr = WERR_INVALID_PARAM;
704                         goto error_exit;
705                 }
706
707                 /*
708                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
709                  * for more details. Version in this case is not just the version of the
710                  * file, but the version in the sense of kernal mode (2) vs. user mode
711                  * (3) drivers. Other bits of the version fields are the version info.
712                  * JRR 010716
713                 */
714                 cversion = major & 0x0000ffff;
715                 switch (cversion) {
716                         case 2: /* WinNT drivers */
717                         case 3: /* Win2K drivers */
718                                 break;
719
720                         default:
721                                 DEBUG(6,("get_correct_cversion: cversion "
722                                          "invalid [%s]  cversion = %d\n",
723                                          smb_fname_str_dbg(smb_fname),
724                                          cversion));
725                                 goto error_exit;
726                 }
727
728                 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
729                           " = 0x%x  minor = 0x%x\n",
730                           smb_fname_str_dbg(smb_fname), major, minor));
731         }
732
733         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
734                   smb_fname_str_dbg(smb_fname), cversion));
735         *perr = WERR_OK;
736
737  error_exit:
738         unbecome_user();
739  error_free_conn:
740         TALLOC_FREE(smb_fname);
741         if (fsp != NULL) {
742                 close_file(NULL, fsp, NORMAL_CLOSE);
743         }
744         if (conn != NULL) {
745                 vfs_ChDir(conn, oldcwd);
746                 SMB_VFS_DISCONNECT(conn);
747                 conn_free(conn);
748         }
749         if (!NT_STATUS_IS_OK(*perr)) {
750                 cversion = -1;
751         }
752
753         return cversion;
754 }
755
756 /****************************************************************************
757 ****************************************************************************/
758
759 #define strip_driver_path(_mem_ctx, _element) do { \
760         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
761                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
762                 W_ERROR_HAVE_NO_MEMORY((_element)); \
763         } \
764 } while (0);
765
766 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
767                                            struct pipes_struct *rpc_pipe,
768                                            const char *architecture,
769                                            const char **driver_path,
770                                            const char **data_file,
771                                            const char **config_file,
772                                            const char **help_file,
773                                            struct spoolss_StringArray *dependent_files,
774                                            enum spoolss_DriverOSVersion *version)
775 {
776         const char *short_architecture;
777         int i;
778         WERROR err;
779         char *_p;
780
781         if (!*driver_path || !*data_file) {
782                 return WERR_INVALID_PARAM;
783         }
784
785         if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
786                 return WERR_INVALID_PARAM;
787         }
788
789         /* clean up the driver name.
790          * we can get .\driver.dll
791          * or worse c:\windows\system\driver.dll !
792          */
793         /* using an intermediate string to not have overlaping memcpy()'s */
794
795         strip_driver_path(mem_ctx, *driver_path);
796         strip_driver_path(mem_ctx, *data_file);
797         if (*config_file) {
798                 strip_driver_path(mem_ctx, *config_file);
799         }
800         if (help_file) {
801                 strip_driver_path(mem_ctx, *help_file);
802         }
803
804         if (dependent_files && dependent_files->string) {
805                 for (i=0; dependent_files->string[i]; i++) {
806                         strip_driver_path(mem_ctx, dependent_files->string[i]);
807                 }
808         }
809
810         short_architecture = get_short_archi(architecture);
811         if (!short_architecture) {
812                 return WERR_UNKNOWN_PRINTER_DRIVER;
813         }
814
815         /* jfm:7/16/2000 the client always sends the cversion=0.
816          * The server should check which version the driver is by reading
817          * the PE header of driver->driverpath.
818          *
819          * For Windows 95/98 the version is 0 (so the value sent is correct)
820          * For Windows NT (the architecture doesn't matter)
821          *      NT 3.1: cversion=0
822          *      NT 3.5/3.51: cversion=1
823          *      NT 4: cversion=2
824          *      NT2K: cversion=3
825          */
826
827         *version = get_correct_cversion(rpc_pipe, short_architecture,
828                                         *driver_path, &err);
829         if (*version == -1) {
830                 return err;
831         }
832
833         return WERR_OK;
834 }
835
836 /****************************************************************************
837 ****************************************************************************/
838
839 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
840                               struct pipes_struct *rpc_pipe,
841                               struct spoolss_AddDriverInfoCtr *r)
842 {
843         switch (r->level) {
844         case 3:
845                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
846                                                     r->info.info3->architecture,
847                                                     &r->info.info3->driver_path,
848                                                     &r->info.info3->data_file,
849                                                     &r->info.info3->config_file,
850                                                     &r->info.info3->help_file,
851                                                     r->info.info3->dependent_files,
852                                                     &r->info.info3->version);
853         case 6:
854                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
855                                                     r->info.info6->architecture,
856                                                     &r->info.info6->driver_path,
857                                                     &r->info.info6->data_file,
858                                                     &r->info.info6->config_file,
859                                                     &r->info.info6->help_file,
860                                                     r->info.info6->dependent_files,
861                                                     &r->info.info6->version);
862         default:
863                 return WERR_NOT_SUPPORTED;
864         }
865 }
866
867 /****************************************************************************
868  This function sucks and should be replaced. JRA.
869 ****************************************************************************/
870
871 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
872                                       const struct spoolss_AddDriverInfo6 *src)
873 {
874         dst->version            = src->version;
875
876         dst->driver_name        = src->driver_name;
877         dst->architecture       = src->architecture;
878         dst->driver_path        = src->driver_path;
879         dst->data_file          = src->data_file;
880         dst->config_file        = src->config_file;
881         dst->help_file          = src->help_file;
882         dst->monitor_name       = src->monitor_name;
883         dst->default_datatype   = src->default_datatype;
884         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
885         dst->dependent_files    = src->dependent_files;
886 }
887
888 /****************************************************************************
889 ****************************************************************************/
890
891 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
892                                                 connection_struct *conn,
893                                                 const char *driver_file,
894                                                 const char *short_architecture,
895                                                 uint32_t driver_version,
896                                                 uint32_t version)
897 {
898         struct smb_filename *smb_fname_old = NULL;
899         struct smb_filename *smb_fname_new = NULL;
900         char *old_name = NULL;
901         char *new_name = NULL;
902         NTSTATUS status;
903         WERROR ret;
904
905         old_name = talloc_asprintf(mem_ctx, "%s/%s",
906                                    short_architecture, driver_file);
907         W_ERROR_HAVE_NO_MEMORY(old_name);
908
909         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
910                                    short_architecture, driver_version, driver_file);
911         if (new_name == NULL) {
912                 TALLOC_FREE(old_name);
913                 return WERR_NOMEM;
914         }
915
916         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
917
918                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
919                 if (!NT_STATUS_IS_OK(status)) {
920                         ret = WERR_NOMEM;
921                         goto out;
922                 }
923
924                 /* Setup a synthetic smb_filename struct */
925                 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
926                 if (!smb_fname_new) {
927                         ret = WERR_NOMEM;
928                         goto out;
929                 }
930
931                 smb_fname_new->base_name = new_name;
932
933                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
934                           "'%s'\n", smb_fname_old->base_name,
935                           smb_fname_new->base_name));
936
937                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
938                                    OPENX_FILE_EXISTS_TRUNCATE |
939                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
940                                    0, false);
941
942                 if (!NT_STATUS_IS_OK(status)) {
943                         DEBUG(0,("move_driver_file_to_download_area: Unable "
944                                  "to rename [%s] to [%s]: %s\n",
945                                  smb_fname_old->base_name, new_name,
946                                  nt_errstr(status)));
947                         ret = WERR_ACCESS_DENIED;
948                         goto out;
949                 }
950         }
951
952         ret = WERR_OK;
953  out:
954         TALLOC_FREE(smb_fname_old);
955         TALLOC_FREE(smb_fname_new);
956         return ret;
957 }
958
959 WERROR move_driver_to_download_area(struct pipes_struct *p,
960                                     struct spoolss_AddDriverInfoCtr *r)
961 {
962         struct spoolss_AddDriverInfo3 *driver;
963         struct spoolss_AddDriverInfo3 converted_driver;
964         const char *short_architecture;
965         struct smb_filename *smb_dname = NULL;
966         char *new_dir = NULL;
967         connection_struct *conn = NULL;
968         NTSTATUS nt_status;
969         int i;
970         TALLOC_CTX *ctx = talloc_tos();
971         int ver = 0;
972         char *oldcwd;
973         char *printdollar = NULL;
974         int printdollar_snum;
975         WERROR err = WERR_OK;
976
977         switch (r->level) {
978         case 3:
979                 driver = r->info.info3;
980                 break;
981         case 6:
982                 convert_level_6_to_level3(&converted_driver, r->info.info6);
983                 driver = &converted_driver;
984                 break;
985         default:
986                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
987                 return WERR_UNKNOWN_LEVEL;
988         }
989
990         short_architecture = get_short_archi(driver->architecture);
991         if (!short_architecture) {
992                 return WERR_UNKNOWN_PRINTER_DRIVER;
993         }
994
995         printdollar_snum = find_service(ctx, "print$", &printdollar);
996         if (!printdollar) {
997                 return WERR_NOMEM;
998         }
999         if (printdollar_snum == -1) {
1000                 return WERR_NO_SUCH_SHARE;
1001         }
1002
1003         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1004                                        lp_pathname(printdollar_snum),
1005                                        p->session_info, &oldcwd);
1006         if (!NT_STATUS_IS_OK(nt_status)) {
1007                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1008                          "returned %s\n", nt_errstr(nt_status)));
1009                 err = ntstatus_to_werror(nt_status);
1010                 return err;
1011         }
1012
1013         nt_status = set_conn_force_user_group(conn, printdollar_snum);
1014         if (!NT_STATUS_IS_OK(nt_status)) {
1015                 DEBUG(0, ("failed set force user / group\n"));
1016                 err = ntstatus_to_werror(nt_status);
1017                 goto err_free_conn;
1018         }
1019
1020         if (!become_user(conn, get_current_vuid(conn))) {
1021                 DEBUG(0, ("failed to become user\n"));
1022                 err = WERR_ACCESS_DENIED;
1023                 goto err_free_conn;
1024         }
1025
1026         new_dir = talloc_asprintf(ctx,
1027                                 "%s/%d",
1028                                 short_architecture,
1029                                 driver->version);
1030         if (!new_dir) {
1031                 err = WERR_NOMEM;
1032                 goto err_exit;
1033         }
1034         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1035         if (!NT_STATUS_IS_OK(nt_status)) {
1036                 err = WERR_NOMEM;
1037                 goto err_exit;
1038         }
1039
1040         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1041
1042         nt_status = create_directory(conn, NULL, smb_dname);
1043         if (!NT_STATUS_IS_OK(nt_status)
1044          && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1045                 DEBUG(0, ("failed to create driver destination directory: %s\n",
1046                           nt_errstr(nt_status)));
1047                 err = ntstatus_to_werror(nt_status);
1048                 goto err_exit;
1049         }
1050
1051         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1052          * listed for this driver which has already been moved, skip it (note:
1053          * drivers may list the same file name several times. Then check if the
1054          * file already exists in archi\version\, if so, check that the version
1055          * info (or time stamps if version info is unavailable) is newer (or the
1056          * date is later). If it is, move it to archi\version\filexxx.yyy.
1057          * Otherwise, delete the file.
1058          *
1059          * If a file is not moved to archi\version\ because of an error, all the
1060          * rest of the 'unmoved' driver files are removed from archi\. If one or
1061          * more of the driver's files was already moved to archi\version\, it
1062          * potentially leaves the driver in a partially updated state. Version
1063          * trauma will most likely occur if an client attempts to use any printer
1064          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1065          * done is appropriate... later JRR
1066          */
1067
1068         DEBUG(5,("Moving files now !\n"));
1069
1070         if (driver->driver_path && strlen(driver->driver_path)) {
1071
1072                 err = move_driver_file_to_download_area(ctx,
1073                                                         conn,
1074                                                         driver->driver_path,
1075                                                         short_architecture,
1076                                                         driver->version,
1077                                                         ver);
1078                 if (!W_ERROR_IS_OK(err)) {
1079                         goto err_exit;
1080                 }
1081         }
1082
1083         if (driver->data_file && strlen(driver->data_file)) {
1084                 if (!strequal(driver->data_file, driver->driver_path)) {
1085
1086                         err = move_driver_file_to_download_area(ctx,
1087                                                                 conn,
1088                                                                 driver->data_file,
1089                                                                 short_architecture,
1090                                                                 driver->version,
1091                                                                 ver);
1092                         if (!W_ERROR_IS_OK(err)) {
1093                                 goto err_exit;
1094                         }
1095                 }
1096         }
1097
1098         if (driver->config_file && strlen(driver->config_file)) {
1099                 if (!strequal(driver->config_file, driver->driver_path) &&
1100                     !strequal(driver->config_file, driver->data_file)) {
1101
1102                         err = move_driver_file_to_download_area(ctx,
1103                                                                 conn,
1104                                                                 driver->config_file,
1105                                                                 short_architecture,
1106                                                                 driver->version,
1107                                                                 ver);
1108                         if (!W_ERROR_IS_OK(err)) {
1109                                 goto err_exit;
1110                         }
1111                 }
1112         }
1113
1114         if (driver->help_file && strlen(driver->help_file)) {
1115                 if (!strequal(driver->help_file, driver->driver_path) &&
1116                     !strequal(driver->help_file, driver->data_file) &&
1117                     !strequal(driver->help_file, driver->config_file)) {
1118
1119                         err = move_driver_file_to_download_area(ctx,
1120                                                                 conn,
1121                                                                 driver->help_file,
1122                                                                 short_architecture,
1123                                                                 driver->version,
1124                                                                 ver);
1125                         if (!W_ERROR_IS_OK(err)) {
1126                                 goto err_exit;
1127                         }
1128                 }
1129         }
1130
1131         if (driver->dependent_files && driver->dependent_files->string) {
1132                 for (i=0; driver->dependent_files->string[i]; i++) {
1133                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1134                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
1135                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
1136                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
1137                                 int j;
1138                                 for (j=0; j < i; j++) {
1139                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1140                                                 goto NextDriver;
1141                                         }
1142                                 }
1143
1144                                 err = move_driver_file_to_download_area(ctx,
1145                                                                         conn,
1146                                                                         driver->dependent_files->string[i],
1147                                                                         short_architecture,
1148                                                                         driver->version,
1149                                                                         ver);
1150                                 if (!W_ERROR_IS_OK(err)) {
1151                                         goto err_exit;
1152                                 }
1153                         }
1154                 NextDriver: ;
1155                 }
1156         }
1157
1158         err = WERR_OK;
1159  err_exit:
1160         unbecome_user();
1161  err_free_conn:
1162         TALLOC_FREE(smb_dname);
1163
1164         if (conn != NULL) {
1165                 vfs_ChDir(conn, oldcwd);
1166                 SMB_VFS_DISCONNECT(conn);
1167                 conn_free(conn);
1168         }
1169
1170         return err;
1171 }
1172
1173 /****************************************************************************
1174  Create and allocate a default devicemode.
1175 ****************************************************************************/
1176
1177 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
1178                                       const char *devicename,
1179                                       struct spoolss_DeviceMode **devmode)
1180 {
1181         struct spoolss_DeviceMode *dm;
1182         char *dname;
1183
1184         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
1185         if (dm == NULL) {
1186                 return WERR_NOMEM;
1187         }
1188
1189         dname = talloc_asprintf(dm, "%s", devicename);
1190         if (dname == NULL) {
1191                 return WERR_NOMEM;
1192         }
1193         if (strlen(dname) > MAXDEVICENAME) {
1194                 dname[MAXDEVICENAME] = '\0';
1195         }
1196         dm->devicename = dname;
1197
1198         dm->formname = talloc_strdup(dm, "Letter");
1199         if (dm->formname == NULL) {
1200                 return WERR_NOMEM;
1201         }
1202
1203         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
1204         dm->driverversion        = 0x0400;
1205         dm->size                 = 0x00DC;
1206         dm->__driverextra_length = 0;
1207         dm->fields               = DEVMODE_FORMNAME |
1208                                    DEVMODE_TTOPTION |
1209                                    DEVMODE_PRINTQUALITY |
1210                                    DEVMODE_DEFAULTSOURCE |
1211                                    DEVMODE_COPIES |
1212                                    DEVMODE_SCALE |
1213                                    DEVMODE_PAPERSIZE |
1214                                    DEVMODE_ORIENTATION;
1215         dm->orientation          = DMORIENT_PORTRAIT;
1216         dm->papersize            = DMPAPER_LETTER;
1217         dm->paperlength          = 0;
1218         dm->paperwidth           = 0;
1219         dm->scale                = 0x64;
1220         dm->copies               = 1;
1221         dm->defaultsource        = DMBIN_FORMSOURCE;
1222         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
1223         dm->color                = DMRES_MONOCHROME;
1224         dm->duplex               = DMDUP_SIMPLEX;
1225         dm->yresolution          = 0;
1226         dm->ttoption             = DMTT_SUBDEV;
1227         dm->collate              = DMCOLLATE_FALSE;
1228         dm->icmmethod            = 0;
1229         dm->icmintent            = 0;
1230         dm->mediatype            = 0;
1231         dm->dithertype           = 0;
1232
1233         dm->logpixels            = 0;
1234         dm->bitsperpel           = 0;
1235         dm->pelswidth            = 0;
1236         dm->pelsheight           = 0;
1237         dm->displayflags         = 0;
1238         dm->displayfrequency     = 0;
1239         dm->reserved1            = 0;
1240         dm->reserved2            = 0;
1241         dm->panningwidth         = 0;
1242         dm->panningheight        = 0;
1243
1244         dm->driverextra_data.data = NULL;
1245         dm->driverextra_data.length = 0;
1246
1247         *devmode = dm;
1248         return WERR_OK;
1249 }
1250
1251 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
1252                                       struct spoolss_security_descriptor **secdesc)
1253 {
1254         struct security_ace ace[7];     /* max number of ace entries */
1255         int i = 0;
1256         uint32_t sa;
1257         struct security_acl *psa = NULL;
1258         struct security_descriptor *psd = NULL;
1259         struct dom_sid adm_sid;
1260         size_t sd_size;
1261
1262         /* Create an ACE where Everyone is allowed to print */
1263
1264         sa = PRINTER_ACE_PRINT;
1265         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
1266                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1267
1268         /* Add the domain admins group if we are a DC */
1269
1270         if ( IS_DC ) {
1271                 struct dom_sid domadmins_sid;
1272
1273                 sid_compose(&domadmins_sid, get_global_sam_sid(),
1274                             DOMAIN_RID_ADMINS);
1275
1276                 sa = PRINTER_ACE_FULL_CONTROL;
1277                 init_sec_ace(&ace[i++], &domadmins_sid,
1278                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1279                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1280                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1281                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1282         }
1283         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
1284                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
1285
1286                 sa = PRINTER_ACE_FULL_CONTROL;
1287                 init_sec_ace(&ace[i++], &adm_sid,
1288                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1289                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1290                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
1291                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1292         }
1293
1294         /* add BUILTIN\Administrators as FULL CONTROL */
1295
1296         sa = PRINTER_ACE_FULL_CONTROL;
1297         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1298                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1299                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1300         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
1301                 SEC_ACE_TYPE_ACCESS_ALLOWED,
1302                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1303
1304         /* add BUILTIN\Print Operators as FULL CONTROL */
1305
1306         sa = PRINTER_ACE_FULL_CONTROL;
1307         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1308                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
1309                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
1310         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
1311                 SEC_ACE_TYPE_ACCESS_ALLOWED,
1312                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
1313
1314         /* Make the security descriptor owned by the BUILTIN\Administrators */
1315
1316         /* The ACL revision number in rpc_secdesc.h differs from the one
1317            created by NT when setting ACE entries in printer
1318            descriptors.  NT4 complains about the property being edited by a
1319            NT5 machine. */
1320
1321         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
1322                 psd = make_sec_desc(mem_ctx,
1323                                     SD_REVISION,
1324                                     SEC_DESC_SELF_RELATIVE,
1325                                     &global_sid_Builtin_Administrators,
1326                                     &global_sid_Builtin_Administrators,
1327                                     NULL,
1328                                     psa,
1329                                     &sd_size);
1330         }
1331
1332         if (psd == NULL) {
1333                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
1334                 return WERR_NOMEM;
1335         }
1336
1337         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
1338                  (unsigned int)sd_size));
1339
1340         *secdesc = psd;
1341
1342         return WERR_OK;
1343 }
1344
1345 /****************************************************************************
1346  ***************************************************************************/
1347
1348 static char *win_driver;
1349 static char *os2_driver;
1350
1351 static const char *get_win_driver(void)
1352 {
1353         if (win_driver == NULL) {
1354                 return "";
1355         }
1356         return win_driver;
1357 }
1358
1359 static const char *get_os2_driver(void)
1360 {
1361         if (os2_driver == NULL) {
1362                 return "";
1363         }
1364         return os2_driver;
1365 }
1366
1367 static bool set_driver_mapping(const char *from, const char *to)
1368 {
1369         SAFE_FREE(win_driver);
1370         SAFE_FREE(os2_driver);
1371
1372         win_driver = SMB_STRDUP(from);
1373         os2_driver = SMB_STRDUP(to);
1374
1375         if (win_driver == NULL || os2_driver == NULL) {
1376                 SAFE_FREE(win_driver);
1377                 SAFE_FREE(os2_driver);
1378                 return false;
1379         }
1380         return true;
1381 }
1382
1383 /**
1384  * @internal
1385  *
1386  * @brief Map a Windows driver to a OS/2 driver.
1387  *
1388  * @param[in]  mem_ctx  The memory context to use.
1389  *
1390  * @param[in,out] pdrivername The drivername of Windows to remap.
1391  *
1392  * @return              WERR_OK on success, a corresponding WERROR on failure.
1393  */
1394 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
1395 {
1396         const char *mapfile = lp_os2_driver_map();
1397         char **lines = NULL;
1398         const char *drivername;
1399         int numlines = 0;
1400         int i;
1401
1402         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
1403                 return WERR_INVALID_PARAMETER;
1404         }
1405
1406         drivername = *pdrivername;
1407
1408         if (mapfile[0] == '\0') {
1409                 return WERR_BADFILE;
1410         }
1411
1412         if (strequal(drivername, get_win_driver())) {
1413                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
1414                         drivername, get_os2_driver()));
1415                 drivername = talloc_strdup(mem_ctx, get_os2_driver());
1416                 if (drivername == NULL) {
1417                         return WERR_NOMEM;
1418                 }
1419                 *pdrivername = drivername;
1420                 return WERR_OK;
1421         }
1422
1423         lines = file_lines_load(mapfile, &numlines, 0, NULL);
1424         if (numlines == 0 || lines == NULL) {
1425                 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
1426                 TALLOC_FREE(lines);
1427                 return WERR_EMPTY;
1428         }
1429
1430         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
1431
1432         for( i = 0; i < numlines; i++) {
1433                 char *nt_name = lines[i];
1434                 char *os2_name = strchr(nt_name, '=');
1435
1436                 if (os2_name == NULL) {
1437                         continue;
1438                 }
1439
1440                 *os2_name++ = '\0';
1441
1442                 while (isspace(*nt_name)) {
1443                         nt_name++;
1444                 }
1445
1446                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
1447                         continue;
1448                 }
1449
1450                 {
1451                         int l = strlen(nt_name);
1452                         while (l && isspace(nt_name[l - 1])) {
1453                                 nt_name[l - 1] = 0;
1454                                 l--;
1455                         }
1456                 }
1457
1458                 while (isspace(*os2_name)) {
1459                         os2_name++;
1460                 }
1461
1462                 {
1463                         int l = strlen(os2_name);
1464                         while (l && isspace(os2_name[l-1])) {
1465                                 os2_name[l-1] = 0;
1466                                 l--;
1467                         }
1468                 }
1469
1470                 if (strequal(nt_name, drivername)) {
1471                         DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
1472                         set_driver_mapping(drivername, os2_name);
1473                         drivername = talloc_strdup(mem_ctx, os2_name);
1474                         TALLOC_FREE(lines);
1475                         if (drivername == NULL) {
1476                                 return WERR_NOMEM;
1477                         }
1478                         *pdrivername = drivername;
1479                         return WERR_OK;
1480                 }
1481         }
1482
1483         TALLOC_FREE(lines);
1484         return WERR_OK;
1485 }
1486
1487 /****************************************************************************
1488 ****************************************************************************/
1489
1490 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
1491                               struct spoolss_DriverInfo8 *_info8)
1492 {
1493         struct spoolss_DriverInfo8 info8;
1494
1495         ZERO_STRUCT(info8);
1496
1497         switch (r->level) {
1498         case 3:
1499                 info8.version           = r->info.info3->version;
1500                 info8.driver_name       = r->info.info3->driver_name;
1501                 info8.architecture      = r->info.info3->architecture;
1502                 info8.driver_path       = r->info.info3->driver_path;
1503                 info8.data_file         = r->info.info3->data_file;
1504                 info8.config_file       = r->info.info3->config_file;
1505                 info8.help_file         = r->info.info3->help_file;
1506                 info8.monitor_name      = r->info.info3->monitor_name;
1507                 info8.default_datatype  = r->info.info3->default_datatype;
1508                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
1509                         info8.dependent_files   = r->info.info3->dependent_files->string;
1510                 }
1511                 break;
1512         case 6:
1513                 info8.version           = r->info.info6->version;
1514                 info8.driver_name       = r->info.info6->driver_name;
1515                 info8.architecture      = r->info.info6->architecture;
1516                 info8.driver_path       = r->info.info6->driver_path;
1517                 info8.data_file         = r->info.info6->data_file;
1518                 info8.config_file       = r->info.info6->config_file;
1519                 info8.help_file         = r->info.info6->help_file;
1520                 info8.monitor_name      = r->info.info6->monitor_name;
1521                 info8.default_datatype  = r->info.info6->default_datatype;
1522                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
1523                         info8.dependent_files   = r->info.info6->dependent_files->string;
1524                 }
1525                 info8.driver_date       = r->info.info6->driver_date;
1526                 info8.driver_version    = r->info.info6->driver_version;
1527                 info8.manufacturer_name = r->info.info6->manufacturer_name;
1528                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
1529                 info8.hardware_id       = r->info.info6->hardware_id;
1530                 info8.provider          = r->info.info6->provider;
1531                 break;
1532         case 8:
1533                 info8.version           = r->info.info8->version;
1534                 info8.driver_name       = r->info.info8->driver_name;
1535                 info8.architecture      = r->info.info8->architecture;
1536                 info8.driver_path       = r->info.info8->driver_path;
1537                 info8.data_file         = r->info.info8->data_file;
1538                 info8.config_file       = r->info.info8->config_file;
1539                 info8.help_file         = r->info.info8->help_file;
1540                 info8.monitor_name      = r->info.info8->monitor_name;
1541                 info8.default_datatype  = r->info.info8->default_datatype;
1542                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
1543                         info8.dependent_files   = r->info.info8->dependent_files->string;
1544                 }
1545                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
1546                         info8.previous_names    = r->info.info8->previous_names->string;
1547                 }
1548                 info8.driver_date       = r->info.info8->driver_date;
1549                 info8.driver_version    = r->info.info8->driver_version;
1550                 info8.manufacturer_name = r->info.info8->manufacturer_name;
1551                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
1552                 info8.hardware_id       = r->info.info8->hardware_id;
1553                 info8.provider          = r->info.info8->provider;
1554                 info8.print_processor   = r->info.info8->print_processor;
1555                 info8.vendor_setup      = r->info.info8->vendor_setup;
1556                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
1557                         info8.color_profiles = r->info.info8->color_profiles->string;
1558                 }
1559                 info8.inf_path          = r->info.info8->inf_path;
1560                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
1561                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
1562                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
1563                 }
1564                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
1565                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
1566                 break;
1567         default:
1568                 return false;
1569         }
1570
1571         *_info8 = info8;
1572
1573         return true;
1574 }
1575
1576
1577 /****************************************************************************
1578   Determine whether or not a particular driver is currently assigned
1579   to a printer
1580 ****************************************************************************/
1581
1582 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1583                            const struct auth_serversupplied_info *session_info,
1584                            struct messaging_context *msg_ctx,
1585                            const struct spoolss_DriverInfo8 *r)
1586 {
1587         int snum;
1588         int n_services = lp_numservices();
1589         bool in_use = False;
1590         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1591         WERROR result;
1592
1593         if (!r) {
1594                 return false;
1595         }
1596
1597         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1598
1599         /* loop through the printers.tdb and check for the drivername */
1600
1601         for (snum=0; snum<n_services && !in_use; snum++) {
1602                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1603                         continue;
1604                 }
1605
1606                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
1607                                             lp_servicename(snum),
1608                                             &pinfo2);
1609                 if (!W_ERROR_IS_OK(result)) {
1610                         continue; /* skip */
1611                 }
1612
1613                 if (strequal(r->driver_name, pinfo2->drivername)) {
1614                         in_use = True;
1615                 }
1616
1617                 TALLOC_FREE(pinfo2);
1618         }
1619
1620         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1621
1622         if ( in_use ) {
1623                 struct spoolss_DriverInfo8 *driver;
1624                 WERROR werr;
1625
1626                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1627
1628                 /* we can still remove the driver if there is one of
1629                    "Windows NT x86" version 2 or 3 left */
1630
1631                 if (!strequal("Windows NT x86", r->architecture)) {
1632                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1633                                                  "Windows NT x86",
1634                                                  r->driver_name,
1635                                                  DRIVER_ANY_VERSION,
1636                                                  &driver);
1637                 } else if (r->version == 2) {
1638                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1639                                                  "Windows NT x86",
1640                                                  r->driver_name,
1641                                                  3, &driver);
1642                 } else if (r->version == 3) {
1643                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1644                                                  "Windows NT x86",
1645                                                  r->driver_name,
1646                                                  2, &driver);
1647                 } else {
1648                         DEBUG(0, ("printer_driver_in_use: ERROR!"
1649                                   " unknown driver version (%d)\n",
1650                                   r->version));
1651                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
1652                 }
1653
1654                 /* now check the error code */
1655
1656                 if ( W_ERROR_IS_OK(werr) ) {
1657                         /* it's ok to remove the driver, we have other architctures left */
1658                         in_use = False;
1659                         talloc_free(driver);
1660                 }
1661         }
1662
1663         /* report that the driver is not in use by default */
1664
1665         return in_use;
1666 }
1667
1668
1669 /**********************************************************************
1670  Check to see if a ogiven file is in use by *info
1671  *********************************************************************/
1672
1673 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1674 {
1675         int i = 0;
1676
1677         if ( !info )
1678                 return False;
1679
1680         /* mz: skip files that are in the list but already deleted */
1681         if (!file || !file[0]) {
1682                 return false;
1683         }
1684
1685         if (strequal(file, info->driver_path))
1686                 return True;
1687
1688         if (strequal(file, info->data_file))
1689                 return True;
1690
1691         if (strequal(file, info->config_file))
1692                 return True;
1693
1694         if (strequal(file, info->help_file))
1695                 return True;
1696
1697         /* see of there are any dependent files to examine */
1698
1699         if (!info->dependent_files)
1700                 return False;
1701
1702         while (info->dependent_files[i] && *info->dependent_files[i]) {
1703                 if (strequal(file, info->dependent_files[i]))
1704                         return True;
1705                 i++;
1706         }
1707
1708         return False;
1709
1710 }
1711
1712 /**********************************************************************
1713  Utility function to remove the dependent file pointed to by the
1714  input parameter from the list
1715  *********************************************************************/
1716
1717 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1718 {
1719
1720         /* bump everything down a slot */
1721
1722         while (files && files[idx+1]) {
1723                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1724                 idx++;
1725         }
1726
1727         files[idx] = NULL;
1728
1729         return;
1730 }
1731
1732 /**********************************************************************
1733  Check if any of the files used by src are also used by drv
1734  *********************************************************************/
1735
1736 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1737                                    struct spoolss_DriverInfo8 *src,
1738                                    const struct spoolss_DriverInfo8 *drv)
1739 {
1740         bool    in_use = False;
1741         int     i = 0;
1742
1743         if ( !src || !drv )
1744                 return False;
1745
1746         /* check each file.  Remove it from the src structure if it overlaps */
1747
1748         if (drv_file_in_use(src->driver_path, drv)) {
1749                 in_use = True;
1750                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1751                 src->driver_path = talloc_strdup(mem_ctx, "");
1752                 if (!src->driver_path) { return false; }
1753         }
1754
1755         if (drv_file_in_use(src->data_file, drv)) {
1756                 in_use = True;
1757                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1758                 src->data_file = talloc_strdup(mem_ctx, "");
1759                 if (!src->data_file) { return false; }
1760         }
1761
1762         if (drv_file_in_use(src->config_file, drv)) {
1763                 in_use = True;
1764                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1765                 src->config_file = talloc_strdup(mem_ctx, "");
1766                 if (!src->config_file) { return false; }
1767         }
1768
1769         if (drv_file_in_use(src->help_file, drv)) {
1770                 in_use = True;
1771                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1772                 src->help_file = talloc_strdup(mem_ctx, "");
1773                 if (!src->help_file) { return false; }
1774         }
1775
1776         /* are there any dependentfiles to examine? */
1777
1778         if (!src->dependent_files)
1779                 return in_use;
1780
1781         while (src->dependent_files[i] && *src->dependent_files[i]) {
1782                 if (drv_file_in_use(src->dependent_files[i], drv)) {
1783                         in_use = True;
1784                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1785                         trim_dependent_file(mem_ctx, src->dependent_files, i);
1786                 } else
1787                         i++;
1788         }
1789
1790         return in_use;
1791 }
1792
1793 /****************************************************************************
1794   Determine whether or not a particular driver files are currently being
1795   used by any other driver.
1796
1797   Return value is True if any files were in use by other drivers
1798   and False otherwise.
1799
1800   Upon return, *info has been modified to only contain the driver files
1801   which are not in use
1802
1803   Fix from mz:
1804
1805   This needs to check all drivers to ensure that all files in use
1806   have been removed from *info, not just the ones in the first
1807   match.
1808 ****************************************************************************/
1809
1810 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1811                                  const struct auth_serversupplied_info *session_info,
1812                                  struct messaging_context *msg_ctx,
1813                                  struct spoolss_DriverInfo8 *info)
1814 {
1815         int                             i;
1816         uint32                          version;
1817         struct spoolss_DriverInfo8      *driver;
1818         bool in_use = false;
1819         uint32_t num_drivers;
1820         const char **drivers;
1821         WERROR result;
1822
1823         if ( !info )
1824                 return False;
1825
1826         version = info->version;
1827
1828         /* loop over all driver versions */
1829
1830         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1831
1832         /* get the list of drivers */
1833
1834         result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
1835                                         info->architecture, version,
1836                                         &num_drivers, &drivers);
1837         if (!W_ERROR_IS_OK(result)) {
1838                 return true;
1839         }
1840
1841         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1842                      num_drivers, info->architecture, version));
1843
1844         /* check each driver for overlap in files */
1845
1846         for (i = 0; i < num_drivers; i++) {
1847                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1848
1849                 driver = NULL;
1850
1851                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1852                                            info->architecture, drivers[i],
1853                                            version, &driver);
1854                 if (!W_ERROR_IS_OK(result)) {
1855                         talloc_free(drivers);
1856                         return True;
1857                 }
1858
1859                 /* check if d2 uses any files from d1 */
1860                 /* only if this is a different driver than the one being deleted */
1861
1862                 if (!strequal(info->driver_name, driver->driver_name)) {
1863                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1864                                 /* mz: Do not instantly return -
1865                                  * we need to ensure this file isn't
1866                                  * also in use by other drivers. */
1867                                 in_use = true;
1868                         }
1869                 }
1870
1871                 talloc_free(driver);
1872         }
1873
1874         talloc_free(drivers);
1875
1876         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1877
1878         return in_use;
1879 }
1880
1881 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1882                                         const char *name)
1883 {
1884         struct smb_filename *smb_fname = NULL;
1885         NTSTATUS status;
1886
1887         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1888             &smb_fname);
1889         if (!NT_STATUS_IS_OK(status)) {
1890                 return status;
1891         }
1892
1893         status = unlink_internals(conn, NULL, 0, smb_fname, false);
1894
1895         TALLOC_FREE(smb_fname);
1896         return status;
1897 }
1898
1899 /****************************************************************************
1900   Actually delete the driver files.  Make sure that
1901   printer_driver_files_in_use() return False before calling
1902   this.
1903 ****************************************************************************/
1904
1905 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
1906                          const struct spoolss_DriverInfo8 *r)
1907 {
1908         int i = 0;
1909         char *s;
1910         const char *file;
1911         connection_struct *conn;
1912         NTSTATUS nt_status;
1913         char *oldcwd;
1914         char *printdollar = NULL;
1915         int printdollar_snum;
1916         bool ret = false;
1917
1918         if (!r) {
1919                 return false;
1920         }
1921
1922         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1923                 r->driver_name, r->version));
1924
1925         printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1926         if (!printdollar) {
1927                 return false;
1928         }
1929         if (printdollar_snum == -1) {
1930                 return false;
1931         }
1932
1933         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1934                                        lp_pathname(printdollar_snum),
1935                                        session_info, &oldcwd);
1936         if (!NT_STATUS_IS_OK(nt_status)) {
1937                 DEBUG(0,("delete_driver_files: create_conn_struct "
1938                          "returned %s\n", nt_errstr(nt_status)));
1939                 return false;
1940         }
1941
1942         nt_status = set_conn_force_user_group(conn, printdollar_snum);
1943         if (!NT_STATUS_IS_OK(nt_status)) {
1944                 DEBUG(0, ("failed set force user / group\n"));
1945                 ret = false;
1946                 goto err_free_conn;
1947         }
1948
1949         if (!become_user(conn, get_current_vuid(conn))) {
1950                 DEBUG(0, ("failed to become user\n"));
1951                 ret = false;
1952                 goto err_free_conn;
1953         }
1954
1955         if ( !CAN_WRITE(conn) ) {
1956                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1957                 ret = false;
1958                 goto err_out;
1959         }
1960
1961         /* now delete the files; must strip the '\print$' string from
1962            fron of path                                                */
1963
1964         if (r->driver_path && r->driver_path[0]) {
1965                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1966                         file = s;
1967                         DEBUG(10,("deleting driverfile [%s]\n", s));
1968                         driver_unlink_internals(conn, file);
1969                 }
1970         }
1971
1972         if (r->config_file && r->config_file[0]) {
1973                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1974                         file = s;
1975                         DEBUG(10,("deleting configfile [%s]\n", s));
1976                         driver_unlink_internals(conn, file);
1977                 }
1978         }
1979
1980         if (r->data_file && r->data_file[0]) {
1981                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1982                         file = s;
1983                         DEBUG(10,("deleting datafile [%s]\n", s));
1984                         driver_unlink_internals(conn, file);
1985                 }
1986         }
1987
1988         if (r->help_file && r->help_file[0]) {
1989                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1990                         file = s;
1991                         DEBUG(10,("deleting helpfile [%s]\n", s));
1992                         driver_unlink_internals(conn, file);
1993                 }
1994         }
1995
1996         /* check if we are done removing files */
1997
1998         if (r->dependent_files) {
1999                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2000                         char *p;
2001
2002                         /* bypass the "\print$" portion of the path */
2003
2004                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
2005                                 file = p;
2006                                 DEBUG(10,("deleting dependent file [%s]\n", file));
2007                                 driver_unlink_internals(conn, file);
2008                         }
2009
2010                         i++;
2011                 }
2012         }
2013
2014         ret = true;
2015  err_out:
2016         unbecome_user();
2017  err_free_conn:
2018         if (conn != NULL) {
2019                 vfs_ChDir(conn, oldcwd);
2020                 SMB_VFS_DISCONNECT(conn);
2021                 conn_free(conn);
2022         }
2023         return ret;
2024 }
2025
2026 /* error code:
2027         0: everything OK
2028         1: level not implemented
2029         2: file doesn't exist
2030         3: can't allocate memory
2031         4: can't free memory
2032         5: non existant struct
2033 */
2034
2035 /*
2036         A printer and a printer driver are 2 different things.
2037         NT manages them separatelly, Samba does the same.
2038         Why ? Simply because it's easier and it makes sense !
2039
2040         Now explanation: You have 3 printers behind your samba server,
2041         2 of them are the same make and model (laser A and B). But laser B
2042         has an 3000 sheet feeder and laser A doesn't such an option.
2043         Your third printer is an old dot-matrix model for the accounting :-).
2044
2045         If the /usr/local/samba/lib directory (default dir), you will have
2046         5 files to describe all of this.
2047
2048         3 files for the printers (1 by printer):
2049                 NTprinter_laser A
2050                 NTprinter_laser B
2051                 NTprinter_accounting
2052         2 files for the drivers (1 for the laser and 1 for the dot matrix)
2053                 NTdriver_printer model X
2054                 NTdriver_printer model Y
2055
2056 jfm: I should use this comment for the text file to explain
2057         same thing for the forms BTW.
2058         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2059
2060 */
2061
2062 /* Convert generic access rights to printer object specific access rights.
2063    It turns out that NT4 security descriptors use generic access rights and
2064    NT5 the object specific ones. */
2065
2066 void map_printer_permissions(struct security_descriptor *sd)
2067 {
2068         int i;
2069
2070         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2071                 se_map_generic(&sd->dacl->aces[i].access_mask,
2072                                &printer_generic_mapping);
2073         }
2074 }
2075
2076 void map_job_permissions(struct security_descriptor *sd)
2077 {
2078         int i;
2079
2080         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2081                 se_map_generic(&sd->dacl->aces[i].access_mask,
2082                                &job_generic_mapping);
2083         }
2084 }
2085
2086
2087 /****************************************************************************
2088  Check a user has permissions to perform the given operation.  We use the
2089  permission constants defined in include/rpc_spoolss.h to check the various
2090  actions we perform when checking printer access.
2091
2092    PRINTER_ACCESS_ADMINISTER:
2093        print_queue_pause, print_queue_resume, update_printer_sec,
2094        update_printer, spoolss_addprinterex_level_2,
2095        _spoolss_setprinterdata
2096
2097    PRINTER_ACCESS_USE:
2098        print_job_start
2099
2100    JOB_ACCESS_ADMINISTER:
2101        print_job_delete, print_job_pause, print_job_resume,
2102        print_queue_purge
2103
2104   Try access control in the following order (for performance reasons):
2105     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
2106     2)  check security descriptor (bit comparisons in memory)
2107     3)  "printer admins" (may result in numerous calls to winbind)
2108
2109  ****************************************************************************/
2110 bool print_access_check(const struct auth_serversupplied_info *session_info,
2111                         struct messaging_context *msg_ctx, int snum,
2112                         int access_type)
2113 {
2114         struct spoolss_security_descriptor *secdesc = NULL;
2115         uint32 access_granted;
2116         size_t sd_size;
2117         NTSTATUS status;
2118         WERROR result;
2119         const char *pname;
2120         TALLOC_CTX *mem_ctx = NULL;
2121
2122         /* If user is NULL then use the current_user structure */
2123
2124         /* Always allow root or SE_PRINT_OPERATROR to do anything */
2125
2126         if (session_info->utok.uid == sec_initial_uid()
2127             || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
2128                 return True;
2129         }
2130
2131         /* Get printer name */
2132
2133         pname = lp_printername(snum);
2134
2135         if (!pname || !*pname) {
2136                 errno = EACCES;
2137                 return False;
2138         }
2139
2140         /* Get printer security descriptor */
2141
2142         if(!(mem_ctx = talloc_init("print_access_check"))) {
2143                 errno = ENOMEM;
2144                 return False;
2145         }
2146
2147         result = winreg_get_printer_secdesc(mem_ctx,
2148                                             get_session_info_system(),
2149                                             msg_ctx,
2150                                             pname,
2151                                             &secdesc);
2152         if (!W_ERROR_IS_OK(result)) {
2153                 talloc_destroy(mem_ctx);
2154                 errno = ENOMEM;
2155                 return False;
2156         }
2157
2158         if (access_type == JOB_ACCESS_ADMINISTER) {
2159                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2160
2161                 /* Create a child security descriptor to check permissions
2162                    against.  This is because print jobs are child objects
2163                    objects of a printer. */
2164                 status = se_create_child_secdesc(mem_ctx,
2165                                                  &secdesc,
2166                                                  &sd_size,
2167                                                  parent_secdesc,
2168                                                  parent_secdesc->owner_sid,
2169                                                  parent_secdesc->group_sid,
2170                                                  false);
2171                 if (!NT_STATUS_IS_OK(status)) {
2172                         talloc_destroy(mem_ctx);
2173                         errno = map_errno_from_nt_status(status);
2174                         return False;
2175                 }
2176
2177                 map_job_permissions(secdesc);
2178         } else {
2179                 map_printer_permissions(secdesc);
2180         }
2181
2182         /* Check access */
2183         status = se_access_check(secdesc, session_info->security_token, access_type,
2184                                  &access_granted);
2185
2186         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2187
2188         /* see if we need to try the printer admin list */
2189
2190         if (!NT_STATUS_IS_OK(status) &&
2191             (token_contains_name_in_list(uidtoname(session_info->utok.uid),
2192                                          session_info->info3->base.domain.string,
2193                                          NULL, session_info->security_token,
2194                                          lp_printer_admin(snum)))) {
2195                 talloc_destroy(mem_ctx);
2196                 return True;
2197         }
2198
2199         talloc_destroy(mem_ctx);
2200
2201         if (!NT_STATUS_IS_OK(status)) {
2202                 errno = EACCES;
2203         }
2204
2205         return NT_STATUS_IS_OK(status);
2206 }
2207
2208 /****************************************************************************
2209  Check the time parameters allow a print operation.
2210 *****************************************************************************/
2211
2212 bool print_time_access_check(const struct auth_serversupplied_info *session_info,
2213                              struct messaging_context *msg_ctx,
2214                              const char *servicename)
2215 {
2216         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2217         WERROR result;
2218         bool ok = False;
2219         time_t now = time(NULL);
2220         struct tm *t;
2221         uint32 mins;
2222
2223         result = winreg_get_printer(NULL, session_info, msg_ctx,
2224                                     servicename, &pinfo2);
2225         if (!W_ERROR_IS_OK(result)) {
2226                 return False;
2227         }
2228
2229         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2230                 ok = True;
2231         }
2232
2233         t = gmtime(&now);
2234         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2235
2236         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2237                 ok = True;
2238         }
2239
2240         TALLOC_FREE(pinfo2);
2241
2242         if (!ok) {
2243                 errno = EACCES;
2244         }
2245
2246         return ok;
2247 }
2248
2249 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2250                         const struct auth_serversupplied_info *session_info,
2251                         struct messaging_context *msg_ctx,
2252                         const char *printer)
2253 {
2254         WERROR result;
2255
2256         result = winreg_delete_printer_key(mem_ctx, session_info, msg_ctx,
2257                                            printer, "");
2258         if (!W_ERROR_IS_OK(result)) {
2259                 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",
2260                           printer));
2261         }
2262 }