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