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