bff91b47fbd7dbbad0b17dc1524862387715cf4a
[amitay/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   Determine whether or not a particular driver is currently assigned
1172   to a printer
1173 ****************************************************************************/
1174
1175 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1176                            const struct auth_serversupplied_info *session_info,
1177                            struct messaging_context *msg_ctx,
1178                            const struct spoolss_DriverInfo8 *r)
1179 {
1180         int snum;
1181         int n_services = lp_numservices();
1182         bool in_use = False;
1183         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1184         WERROR result;
1185
1186         if (!r) {
1187                 return false;
1188         }
1189
1190         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1191
1192         /* loop through the printers.tdb and check for the drivername */
1193
1194         for (snum=0; snum<n_services && !in_use; snum++) {
1195                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1196                         continue;
1197                 }
1198
1199                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
1200                                             lp_servicename(snum),
1201                                             &pinfo2);
1202                 if (!W_ERROR_IS_OK(result)) {
1203                         continue; /* skip */
1204                 }
1205
1206                 if (strequal(r->driver_name, pinfo2->drivername)) {
1207                         in_use = True;
1208                 }
1209
1210                 TALLOC_FREE(pinfo2);
1211         }
1212
1213         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1214
1215         if ( in_use ) {
1216                 struct spoolss_DriverInfo8 *driver;
1217                 WERROR werr;
1218
1219                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1220
1221                 /* we can still remove the driver if there is one of
1222                    "Windows NT x86" version 2 or 3 left */
1223
1224                 if (!strequal("Windows NT x86", r->architecture)) {
1225                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1226                                                  "Windows NT x86",
1227                                                  r->driver_name,
1228                                                  DRIVER_ANY_VERSION,
1229                                                  &driver);
1230                 } else if (r->version == 2) {
1231                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1232                                                  "Windows NT x86",
1233                                                  r->driver_name,
1234                                                  3, &driver);
1235                 } else if (r->version == 3) {
1236                         werr = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1237                                                  "Windows NT x86",
1238                                                  r->driver_name,
1239                                                  2, &driver);
1240                 } else {
1241                         DEBUG(0, ("printer_driver_in_use: ERROR!"
1242                                   " unknown driver version (%d)\n",
1243                                   r->version));
1244                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
1245                 }
1246
1247                 /* now check the error code */
1248
1249                 if ( W_ERROR_IS_OK(werr) ) {
1250                         /* it's ok to remove the driver, we have other architctures left */
1251                         in_use = False;
1252                         talloc_free(driver);
1253                 }
1254         }
1255
1256         /* report that the driver is not in use by default */
1257
1258         return in_use;
1259 }
1260
1261
1262 /**********************************************************************
1263  Check to see if a ogiven file is in use by *info
1264  *********************************************************************/
1265
1266 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1267 {
1268         int i = 0;
1269
1270         if ( !info )
1271                 return False;
1272
1273         /* mz: skip files that are in the list but already deleted */
1274         if (!file || !file[0]) {
1275                 return false;
1276         }
1277
1278         if (strequal(file, info->driver_path))
1279                 return True;
1280
1281         if (strequal(file, info->data_file))
1282                 return True;
1283
1284         if (strequal(file, info->config_file))
1285                 return True;
1286
1287         if (strequal(file, info->help_file))
1288                 return True;
1289
1290         /* see of there are any dependent files to examine */
1291
1292         if (!info->dependent_files)
1293                 return False;
1294
1295         while (info->dependent_files[i] && *info->dependent_files[i]) {
1296                 if (strequal(file, info->dependent_files[i]))
1297                         return True;
1298                 i++;
1299         }
1300
1301         return False;
1302
1303 }
1304
1305 /**********************************************************************
1306  Utility function to remove the dependent file pointed to by the
1307  input parameter from the list
1308  *********************************************************************/
1309
1310 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1311 {
1312
1313         /* bump everything down a slot */
1314
1315         while (files && files[idx+1]) {
1316                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1317                 idx++;
1318         }
1319
1320         files[idx] = NULL;
1321
1322         return;
1323 }
1324
1325 /**********************************************************************
1326  Check if any of the files used by src are also used by drv
1327  *********************************************************************/
1328
1329 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1330                                    struct spoolss_DriverInfo8 *src,
1331                                    const struct spoolss_DriverInfo8 *drv)
1332 {
1333         bool    in_use = False;
1334         int     i = 0;
1335
1336         if ( !src || !drv )
1337                 return False;
1338
1339         /* check each file.  Remove it from the src structure if it overlaps */
1340
1341         if (drv_file_in_use(src->driver_path, drv)) {
1342                 in_use = True;
1343                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1344                 src->driver_path = talloc_strdup(mem_ctx, "");
1345                 if (!src->driver_path) { return false; }
1346         }
1347
1348         if (drv_file_in_use(src->data_file, drv)) {
1349                 in_use = True;
1350                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1351                 src->data_file = talloc_strdup(mem_ctx, "");
1352                 if (!src->data_file) { return false; }
1353         }
1354
1355         if (drv_file_in_use(src->config_file, drv)) {
1356                 in_use = True;
1357                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1358                 src->config_file = talloc_strdup(mem_ctx, "");
1359                 if (!src->config_file) { return false; }
1360         }
1361
1362         if (drv_file_in_use(src->help_file, drv)) {
1363                 in_use = True;
1364                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1365                 src->help_file = talloc_strdup(mem_ctx, "");
1366                 if (!src->help_file) { return false; }
1367         }
1368
1369         /* are there any dependentfiles to examine? */
1370
1371         if (!src->dependent_files)
1372                 return in_use;
1373
1374         while (src->dependent_files[i] && *src->dependent_files[i]) {
1375                 if (drv_file_in_use(src->dependent_files[i], drv)) {
1376                         in_use = True;
1377                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1378                         trim_dependent_file(mem_ctx, src->dependent_files, i);
1379                 } else
1380                         i++;
1381         }
1382
1383         return in_use;
1384 }
1385
1386 /****************************************************************************
1387   Determine whether or not a particular driver files are currently being
1388   used by any other driver.
1389
1390   Return value is True if any files were in use by other drivers
1391   and False otherwise.
1392
1393   Upon return, *info has been modified to only contain the driver files
1394   which are not in use
1395
1396   Fix from mz:
1397
1398   This needs to check all drivers to ensure that all files in use
1399   have been removed from *info, not just the ones in the first
1400   match.
1401 ****************************************************************************/
1402
1403 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1404                                  const struct auth_serversupplied_info *session_info,
1405                                  struct messaging_context *msg_ctx,
1406                                  struct spoolss_DriverInfo8 *info)
1407 {
1408         int                             i;
1409         uint32                          version;
1410         struct spoolss_DriverInfo8      *driver;
1411         bool in_use = false;
1412         uint32_t num_drivers;
1413         const char **drivers;
1414         WERROR result;
1415
1416         if ( !info )
1417                 return False;
1418
1419         version = info->version;
1420
1421         /* loop over all driver versions */
1422
1423         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1424
1425         /* get the list of drivers */
1426
1427         result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
1428                                         info->architecture, version,
1429                                         &num_drivers, &drivers);
1430         if (!W_ERROR_IS_OK(result)) {
1431                 return true;
1432         }
1433
1434         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1435                      num_drivers, info->architecture, version));
1436
1437         /* check each driver for overlap in files */
1438
1439         for (i = 0; i < num_drivers; i++) {
1440                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1441
1442                 driver = NULL;
1443
1444                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
1445                                            info->architecture, drivers[i],
1446                                            version, &driver);
1447                 if (!W_ERROR_IS_OK(result)) {
1448                         talloc_free(drivers);
1449                         return True;
1450                 }
1451
1452                 /* check if d2 uses any files from d1 */
1453                 /* only if this is a different driver than the one being deleted */
1454
1455                 if (!strequal(info->driver_name, driver->driver_name)) {
1456                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1457                                 /* mz: Do not instantly return -
1458                                  * we need to ensure this file isn't
1459                                  * also in use by other drivers. */
1460                                 in_use = true;
1461                         }
1462                 }
1463
1464                 talloc_free(driver);
1465         }
1466
1467         talloc_free(drivers);
1468
1469         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1470
1471         return in_use;
1472 }
1473
1474 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1475                                         const char *name)
1476 {
1477         struct smb_filename *smb_fname = NULL;
1478         NTSTATUS status;
1479
1480         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1481             &smb_fname);
1482         if (!NT_STATUS_IS_OK(status)) {
1483                 return status;
1484         }
1485
1486         status = unlink_internals(conn, NULL, 0, smb_fname, false);
1487
1488         TALLOC_FREE(smb_fname);
1489         return status;
1490 }
1491
1492 /****************************************************************************
1493   Actually delete the driver files.  Make sure that
1494   printer_driver_files_in_use() return False before calling
1495   this.
1496 ****************************************************************************/
1497
1498 bool delete_driver_files(const struct auth_serversupplied_info *session_info,
1499                          const struct spoolss_DriverInfo8 *r)
1500 {
1501         int i = 0;
1502         char *s;
1503         const char *file;
1504         connection_struct *conn;
1505         NTSTATUS nt_status;
1506         char *oldcwd;
1507         char *printdollar = NULL;
1508         int printdollar_snum;
1509         bool ret = false;
1510
1511         if (!r) {
1512                 return false;
1513         }
1514
1515         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1516                 r->driver_name, r->version));
1517
1518         printdollar_snum = find_service(talloc_tos(), "print$", &printdollar);
1519         if (!printdollar) {
1520                 return false;
1521         }
1522         if (printdollar_snum == -1) {
1523                 return false;
1524         }
1525
1526         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1527                                        lp_pathname(printdollar_snum),
1528                                        session_info, &oldcwd);
1529         if (!NT_STATUS_IS_OK(nt_status)) {
1530                 DEBUG(0,("delete_driver_files: create_conn_struct "
1531                          "returned %s\n", nt_errstr(nt_status)));
1532                 return false;
1533         }
1534
1535         nt_status = set_conn_force_user_group(conn, printdollar_snum);
1536         if (!NT_STATUS_IS_OK(nt_status)) {
1537                 DEBUG(0, ("failed set force user / group\n"));
1538                 ret = false;
1539                 goto err_free_conn;
1540         }
1541
1542         if (!become_user_by_session(conn, session_info)) {
1543                 DEBUG(0, ("failed to become user\n"));
1544                 ret = false;
1545                 goto err_free_conn;
1546         }
1547
1548         if ( !CAN_WRITE(conn) ) {
1549                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1550                 ret = false;
1551                 goto err_out;
1552         }
1553
1554         /* now delete the files; must strip the '\print$' string from
1555            fron of path                                                */
1556
1557         if (r->driver_path && r->driver_path[0]) {
1558                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1559                         file = s;
1560                         DEBUG(10,("deleting driverfile [%s]\n", s));
1561                         driver_unlink_internals(conn, file);
1562                 }
1563         }
1564
1565         if (r->config_file && r->config_file[0]) {
1566                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1567                         file = s;
1568                         DEBUG(10,("deleting configfile [%s]\n", s));
1569                         driver_unlink_internals(conn, file);
1570                 }
1571         }
1572
1573         if (r->data_file && r->data_file[0]) {
1574                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1575                         file = s;
1576                         DEBUG(10,("deleting datafile [%s]\n", s));
1577                         driver_unlink_internals(conn, file);
1578                 }
1579         }
1580
1581         if (r->help_file && r->help_file[0]) {
1582                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1583                         file = s;
1584                         DEBUG(10,("deleting helpfile [%s]\n", s));
1585                         driver_unlink_internals(conn, file);
1586                 }
1587         }
1588
1589         /* check if we are done removing files */
1590
1591         if (r->dependent_files) {
1592                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1593                         char *p;
1594
1595                         /* bypass the "\print$" portion of the path */
1596
1597                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1598                                 file = p;
1599                                 DEBUG(10,("deleting dependent file [%s]\n", file));
1600                                 driver_unlink_internals(conn, file);
1601                         }
1602
1603                         i++;
1604                 }
1605         }
1606
1607         ret = true;
1608  err_out:
1609         unbecome_user();
1610  err_free_conn:
1611         if (conn != NULL) {
1612                 vfs_ChDir(conn, oldcwd);
1613                 SMB_VFS_DISCONNECT(conn);
1614                 conn_free(conn);
1615         }
1616         return ret;
1617 }
1618
1619 /* error code:
1620         0: everything OK
1621         1: level not implemented
1622         2: file doesn't exist
1623         3: can't allocate memory
1624         4: can't free memory
1625         5: non existant struct
1626 */
1627
1628 /*
1629         A printer and a printer driver are 2 different things.
1630         NT manages them separatelly, Samba does the same.
1631         Why ? Simply because it's easier and it makes sense !
1632
1633         Now explanation: You have 3 printers behind your samba server,
1634         2 of them are the same make and model (laser A and B). But laser B
1635         has an 3000 sheet feeder and laser A doesn't such an option.
1636         Your third printer is an old dot-matrix model for the accounting :-).
1637
1638         If the /usr/local/samba/lib directory (default dir), you will have
1639         5 files to describe all of this.
1640
1641         3 files for the printers (1 by printer):
1642                 NTprinter_laser A
1643                 NTprinter_laser B
1644                 NTprinter_accounting
1645         2 files for the drivers (1 for the laser and 1 for the dot matrix)
1646                 NTdriver_printer model X
1647                 NTdriver_printer model Y
1648
1649 jfm: I should use this comment for the text file to explain
1650         same thing for the forms BTW.
1651         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1652
1653 */
1654
1655 /* Convert generic access rights to printer object specific access rights.
1656    It turns out that NT4 security descriptors use generic access rights and
1657    NT5 the object specific ones. */
1658
1659 void map_printer_permissions(struct security_descriptor *sd)
1660 {
1661         int i;
1662
1663         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1664                 se_map_generic(&sd->dacl->aces[i].access_mask,
1665                                &printer_generic_mapping);
1666         }
1667 }
1668
1669 void map_job_permissions(struct security_descriptor *sd)
1670 {
1671         int i;
1672
1673         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
1674                 se_map_generic(&sd->dacl->aces[i].access_mask,
1675                                &job_generic_mapping);
1676         }
1677 }
1678
1679
1680 /****************************************************************************
1681  Check a user has permissions to perform the given operation.  We use the
1682  permission constants defined in include/rpc_spoolss.h to check the various
1683  actions we perform when checking printer access.
1684
1685    PRINTER_ACCESS_ADMINISTER:
1686        print_queue_pause, print_queue_resume, update_printer_sec,
1687        update_printer, spoolss_addprinterex_level_2,
1688        _spoolss_setprinterdata
1689
1690    PRINTER_ACCESS_USE:
1691        print_job_start
1692
1693    JOB_ACCESS_ADMINISTER:
1694        print_job_delete, print_job_pause, print_job_resume,
1695        print_queue_purge
1696
1697   Try access control in the following order (for performance reasons):
1698     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
1699     2)  check security descriptor (bit comparisons in memory)
1700     3)  "printer admins" (may result in numerous calls to winbind)
1701
1702  ****************************************************************************/
1703 bool print_access_check(const struct auth_serversupplied_info *session_info,
1704                         struct messaging_context *msg_ctx, int snum,
1705                         int access_type)
1706 {
1707         struct spoolss_security_descriptor *secdesc = NULL;
1708         uint32 access_granted;
1709         size_t sd_size;
1710         NTSTATUS status;
1711         WERROR result;
1712         const char *pname;
1713         TALLOC_CTX *mem_ctx = NULL;
1714
1715         /* If user is NULL then use the current_user structure */
1716
1717         /* Always allow root or SE_PRINT_OPERATROR to do anything */
1718
1719         if (session_info->utok.uid == sec_initial_uid()
1720             || security_token_has_privilege(session_info->security_token, SEC_PRIV_PRINT_OPERATOR)) {
1721                 return True;
1722         }
1723
1724         /* Get printer name */
1725
1726         pname = lp_printername(snum);
1727
1728         if (!pname || !*pname) {
1729                 errno = EACCES;
1730                 return False;
1731         }
1732
1733         /* Get printer security descriptor */
1734
1735         if(!(mem_ctx = talloc_init("print_access_check"))) {
1736                 errno = ENOMEM;
1737                 return False;
1738         }
1739
1740         result = winreg_get_printer_secdesc(mem_ctx,
1741                                             get_session_info_system(),
1742                                             msg_ctx,
1743                                             pname,
1744                                             &secdesc);
1745         if (!W_ERROR_IS_OK(result)) {
1746                 talloc_destroy(mem_ctx);
1747                 errno = ENOMEM;
1748                 return False;
1749         }
1750
1751         if (access_type == JOB_ACCESS_ADMINISTER) {
1752                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
1753
1754                 /* Create a child security descriptor to check permissions
1755                    against.  This is because print jobs are child objects
1756                    objects of a printer. */
1757                 status = se_create_child_secdesc(mem_ctx,
1758                                                  &secdesc,
1759                                                  &sd_size,
1760                                                  parent_secdesc,
1761                                                  parent_secdesc->owner_sid,
1762                                                  parent_secdesc->group_sid,
1763                                                  false);
1764                 if (!NT_STATUS_IS_OK(status)) {
1765                         talloc_destroy(mem_ctx);
1766                         errno = map_errno_from_nt_status(status);
1767                         return False;
1768                 }
1769
1770                 map_job_permissions(secdesc);
1771         } else {
1772                 map_printer_permissions(secdesc);
1773         }
1774
1775         /* Check access */
1776         status = se_access_check(secdesc, session_info->security_token, access_type,
1777                                  &access_granted);
1778
1779         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
1780
1781         /* see if we need to try the printer admin list */
1782
1783         if (!NT_STATUS_IS_OK(status) &&
1784             (token_contains_name_in_list(uidtoname(session_info->utok.uid),
1785                                          session_info->info3->base.domain.string,
1786                                          NULL, session_info->security_token,
1787                                          lp_printer_admin(snum)))) {
1788                 talloc_destroy(mem_ctx);
1789                 return True;
1790         }
1791
1792         talloc_destroy(mem_ctx);
1793
1794         if (!NT_STATUS_IS_OK(status)) {
1795                 errno = EACCES;
1796         }
1797
1798         return NT_STATUS_IS_OK(status);
1799 }
1800
1801 /****************************************************************************
1802  Check the time parameters allow a print operation.
1803 *****************************************************************************/
1804
1805 bool print_time_access_check(const struct auth_serversupplied_info *session_info,
1806                              struct messaging_context *msg_ctx,
1807                              const char *servicename)
1808 {
1809         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1810         WERROR result;
1811         bool ok = False;
1812         time_t now = time(NULL);
1813         struct tm *t;
1814         uint32 mins;
1815
1816         result = winreg_get_printer(NULL, session_info, msg_ctx,
1817                                     servicename, &pinfo2);
1818         if (!W_ERROR_IS_OK(result)) {
1819                 return False;
1820         }
1821
1822         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
1823                 ok = True;
1824         }
1825
1826         t = gmtime(&now);
1827         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
1828
1829         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
1830                 ok = True;
1831         }
1832
1833         TALLOC_FREE(pinfo2);
1834
1835         if (!ok) {
1836                 errno = EACCES;
1837         }
1838
1839         return ok;
1840 }
1841
1842 void nt_printer_remove(TALLOC_CTX *mem_ctx,
1843                         const struct auth_serversupplied_info *session_info,
1844                         struct messaging_context *msg_ctx,
1845                         const char *printer)
1846 {
1847         WERROR result;
1848
1849         result = winreg_delete_printer_key(mem_ctx, session_info, msg_ctx,
1850                                            printer, "");
1851         if (!W_ERROR_IS_OK(result)) {
1852                 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",
1853                           printer));
1854         }
1855 }