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