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