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