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