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