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