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