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