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