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