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