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