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