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