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