printing: convert get_correct_cversion() to use create_conn_struct_tos_cwd()
[samba.git] / source3 / printing / nt_printing.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Jean François Micouleau      1998-2000.
6  *  Copyright (C) Gerald Carter                2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "printing/nt_printing_tdb.h"
24 #include "../librpc/gen_ndr/ndr_spoolss.h"
25 #include "rpc_server/spoolss/srv_spoolss_util.h"
26 #include "nt_printing.h"
27 #include "secrets.h"
28 #include "../librpc/gen_ndr/netlogon.h"
29 #include "../libcli/security/security.h"
30 #include "passdb/machine_sid.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "auth.h"
34 #include "messages.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "rpc_client/cli_winreg_spoolss.h"
37
38 /* Map generic permissions to printer object specific permissions */
39
40 const struct generic_mapping printer_generic_mapping = {
41         PRINTER_READ,
42         PRINTER_WRITE,
43         PRINTER_EXECUTE,
44         PRINTER_ALL_ACCESS
45 };
46
47 /* Map generic permissions to print server object specific permissions */
48
49 const struct generic_mapping printserver_generic_mapping = {
50         SERVER_READ,
51         SERVER_WRITE,
52         SERVER_EXECUTE,
53         SERVER_ALL_ACCESS
54 };
55
56 /* Map generic permissions to job object specific permissions */
57
58 const struct generic_mapping job_generic_mapping = {
59         JOB_READ,
60         JOB_WRITE,
61         JOB_EXECUTE,
62         JOB_ALL_ACCESS
63 };
64
65 static const struct print_architecture_table_node archi_table[]= {
66
67         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
68         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
69         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
70         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
71         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
72         {"Windows IA64",         SPL_ARCH_IA64,         3 },
73         {"Windows x64",          SPL_ARCH_X64,          3 },
74         {NULL,                   "",            -1 }
75 };
76
77 static bool print_driver_directories_init(void)
78 {
79         int service, i;
80         char *driver_path;
81         bool ok;
82         TALLOC_CTX *mem_ctx = talloc_stackframe();
83         const 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         struct conn_struct_tos *c = NULL;
995         connection_struct *conn = 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_tos_cwd(server_messaging_context(),
1054                                                printdollar_snum,
1055                                                working_dir,
1056                                                session_info,
1057                                                &c);
1058         if (!NT_STATUS_IS_OK(nt_status)) {
1059                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1060                          "returned %s\n", nt_errstr(nt_status)));
1061                 *perr = ntstatus_to_werror(nt_status);
1062                 TALLOC_FREE(frame);
1063                 return -1;
1064         }
1065         conn = c->conn;
1066
1067         nt_status = set_conn_force_user_group(conn, printdollar_snum);
1068         if (!NT_STATUS_IS_OK(nt_status)) {
1069                 DEBUG(0, ("failed set force user / group\n"));
1070                 *perr = ntstatus_to_werror(nt_status);
1071                 goto error_free_conn;
1072         }
1073
1074         if (!become_user_by_session(conn, session_info)) {
1075                 DEBUG(0, ("failed to become user\n"));
1076                 *perr = WERR_ACCESS_DENIED;
1077                 goto error_free_conn;
1078         }
1079
1080         /*
1081          * We switch to the directory where the driver files are located,
1082          * so only work on the file names
1083          */
1084         nt_status = driver_unix_convert(conn, driverpath_in, &smb_fname);
1085         if (!NT_STATUS_IS_OK(nt_status)) {
1086                 *perr = ntstatus_to_werror(nt_status);
1087                 goto error_exit;
1088         }
1089
1090         nt_status = vfs_file_exist(conn, smb_fname);
1091         if (!NT_STATUS_IS_OK(nt_status)) {
1092                 DEBUG(3,("get_correct_cversion: vfs_file_exist failed\n"));
1093                 *perr = WERR_FILE_NOT_FOUND;
1094                 goto error_exit;
1095         }
1096
1097         nt_status = SMB_VFS_CREATE_FILE(
1098                 conn,                                   /* conn */
1099                 NULL,                                   /* req */
1100                 0,                                      /* root_dir_fid */
1101                 smb_fname,                              /* fname */
1102                 FILE_GENERIC_READ,                      /* access_mask */
1103                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1104                 FILE_OPEN,                              /* create_disposition*/
1105                 0,                                      /* create_options */
1106                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1107                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1108                 NULL,                                   /* lease */
1109                 0,                                      /* private_flags */
1110                 0,                                      /* allocation_size */
1111                 NULL,                                   /* sd */
1112                 NULL,                                   /* ea_list */
1113                 &fsp,                                   /* result */
1114                 NULL,                                   /* pinfo */
1115                 NULL, NULL);                            /* create context */
1116
1117         if (!NT_STATUS_IS_OK(nt_status)) {
1118                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1119                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
1120                 *perr = WERR_ACCESS_DENIED;
1121                 goto error_exit;
1122         } else {
1123                 uint32_t major;
1124                 uint32_t minor;
1125                 int    ret;
1126
1127                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1128                 if (ret == -1) {
1129                         *perr = WERR_INVALID_PARAMETER;
1130                         goto error_exit;
1131                 } else if (!ret) {
1132                         DEBUG(6,("get_correct_cversion: Version info not "
1133                                  "found [%s]\n",
1134                                  smb_fname_str_dbg(smb_fname)));
1135                         *perr = WERR_INVALID_PARAMETER;
1136                         goto error_exit;
1137                 }
1138
1139                 /*
1140                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1141                  * for more details. Version in this case is not just the version of the
1142                  * file, but the version in the sense of kernal mode (2) vs. user mode
1143                  * (3) drivers. Other bits of the version fields are the version info.
1144                  * JRR 010716
1145                 */
1146                 cversion = major & 0x0000ffff;
1147                 switch (cversion) {
1148                         case 2: /* WinNT drivers */
1149                         case 3: /* Win2K drivers */
1150                                 break;
1151
1152                         default:
1153                                 DEBUG(6,("get_correct_cversion: cversion "
1154                                          "invalid [%s]  cversion = %d\n",
1155                                          smb_fname_str_dbg(smb_fname),
1156                                          cversion));
1157                                 goto error_exit;
1158                 }
1159
1160                 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1161                           " = 0x%x  minor = 0x%x\n",
1162                           smb_fname_str_dbg(smb_fname), major, minor));
1163         }
1164
1165         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1166                   smb_fname_str_dbg(smb_fname), cversion));
1167         *perr = WERR_OK;
1168
1169  error_exit:
1170         unbecome_user();
1171  error_free_conn:
1172         if (fsp != NULL) {
1173                 close_file(NULL, fsp, NORMAL_CLOSE);
1174         }
1175         if (!W_ERROR_IS_OK(*perr)) {
1176                 cversion = -1;
1177         }
1178
1179         TALLOC_FREE(frame);
1180         return cversion;
1181 }
1182
1183 /****************************************************************************
1184 ****************************************************************************/
1185
1186 #define strip_driver_path(_mem_ctx, _element) do { \
1187         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1188                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1189                 W_ERROR_HAVE_NO_MEMORY((_element)); \
1190         } \
1191 } while (0);
1192
1193 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1194                                            const struct auth_session_info *session_info,
1195                                            const char *architecture,
1196                                            const char **driver_path,
1197                                            const char **data_file,
1198                                            const char **config_file,
1199                                            const char **help_file,
1200                                            struct spoolss_StringArray *dependent_files,
1201                                            enum spoolss_DriverOSVersion *version,
1202                                            uint32_t flags,
1203                                            const char **driver_directory)
1204 {
1205         const char *short_architecture;
1206         int i;
1207         WERROR err;
1208         char *_p;
1209
1210         if (!*driver_path || !*data_file) {
1211                 return WERR_INVALID_PARAMETER;
1212         }
1213
1214         if (!strequal(architecture, SPOOLSS_ARCHITECTURE_4_0) && !*config_file) {
1215                 return WERR_INVALID_PARAMETER;
1216         }
1217
1218         if (flags & APD_COPY_FROM_DIRECTORY) {
1219                 char *path;
1220                 char *q;
1221
1222                 /*
1223                  * driver_path is set to:
1224                  *
1225                  * \\PRINTSRV\print$\x64\{279245b0-a8bd-4431-bf6f-baee92ac15c0}\pscript5.dll
1226                  */
1227                 path = talloc_strdup(mem_ctx, *driver_path);
1228                 if (path == NULL) {
1229                         return WERR_NOT_ENOUGH_MEMORY;
1230                 }
1231
1232                 /* Remove pscript5.dll */
1233                 q = strrchr_m(path, '\\');
1234                 if (q == NULL) {
1235                         return WERR_INVALID_PARAMETER;
1236                 }
1237                 *q = '\0';
1238
1239                 /* Get \{279245b0-a8bd-4431-bf6f-baee92ac15c0} */
1240                 q = strrchr_m(path, '\\');
1241                 if (q == NULL) {
1242                         return WERR_INVALID_PARAMETER;
1243                 }
1244
1245                 /*
1246                  * Set driver_directory to:
1247                  *
1248                  * {279245b0-a8bd-4431-bf6f-baee92ac15c0}
1249                  *
1250                  * This is the directory where all the files have been uploaded
1251                  */
1252                 *driver_directory = q + 1;
1253         }
1254
1255         /* clean up the driver name.
1256          * we can get .\driver.dll
1257          * or worse c:\windows\system\driver.dll !
1258          */
1259         /* using an intermediate string to not have overlaping memcpy()'s */
1260
1261         strip_driver_path(mem_ctx, *driver_path);
1262         strip_driver_path(mem_ctx, *data_file);
1263         if (*config_file) {
1264                 strip_driver_path(mem_ctx, *config_file);
1265         }
1266         if (help_file) {
1267                 strip_driver_path(mem_ctx, *help_file);
1268         }
1269
1270         if (dependent_files && dependent_files->string) {
1271                 for (i=0; dependent_files->string[i]; i++) {
1272                         strip_driver_path(mem_ctx, dependent_files->string[i]);
1273                 }
1274         }
1275
1276         short_architecture = get_short_archi(architecture);
1277         if (!short_architecture) {
1278                 return WERR_UNKNOWN_PRINTER_DRIVER;
1279         }
1280
1281         /* jfm:7/16/2000 the client always sends the cversion=0.
1282          * The server should check which version the driver is by reading
1283          * the PE header of driver->driverpath.
1284          *
1285          * For Windows 95/98 the version is 0 (so the value sent is correct)
1286          * For Windows NT (the architecture doesn't matter)
1287          *      NT 3.1: cversion=0
1288          *      NT 3.5/3.51: cversion=1
1289          *      NT 4: cversion=2
1290          *      NT2K: cversion=3
1291          */
1292
1293         *version = get_correct_cversion(session_info,
1294                                         short_architecture,
1295                                         *driver_path,
1296                                         *driver_directory,
1297                                         &err);
1298         if (*version == -1) {
1299                 return err;
1300         }
1301
1302         return WERR_OK;
1303 }
1304
1305 /****************************************************************************
1306 ****************************************************************************/
1307
1308 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1309                               const struct auth_session_info *session_info,
1310                               const struct spoolss_AddDriverInfoCtr *r,
1311                               uint32_t flags,
1312                               const char **driver_directory)
1313 {
1314         switch (r->level) {
1315         case 3:
1316                 return clean_up_driver_struct_level(mem_ctx, session_info,
1317                                                     r->info.info3->architecture,
1318                                                     &r->info.info3->driver_path,
1319                                                     &r->info.info3->data_file,
1320                                                     &r->info.info3->config_file,
1321                                                     &r->info.info3->help_file,
1322                                                     r->info.info3->dependent_files,
1323                                                     &r->info.info3->version,
1324                                                     flags,
1325                                                     driver_directory);
1326         case 6:
1327                 return clean_up_driver_struct_level(mem_ctx, session_info,
1328                                                     r->info.info6->architecture,
1329                                                     &r->info.info6->driver_path,
1330                                                     &r->info.info6->data_file,
1331                                                     &r->info.info6->config_file,
1332                                                     &r->info.info6->help_file,
1333                                                     r->info.info6->dependent_files,
1334                                                     &r->info.info6->version,
1335                                                     flags,
1336                                                     driver_directory);
1337         case 8:
1338                 return clean_up_driver_struct_level(mem_ctx, session_info,
1339                                                     r->info.info8->architecture,
1340                                                     &r->info.info8->driver_path,
1341                                                     &r->info.info8->data_file,
1342                                                     &r->info.info8->config_file,
1343                                                     &r->info.info8->help_file,
1344                                                     r->info.info8->dependent_files,
1345                                                     &r->info.info8->version,
1346                                                     flags,
1347                                                     driver_directory);
1348         default:
1349                 return WERR_NOT_SUPPORTED;
1350         }
1351 }
1352
1353 /****************************************************************************
1354  This function sucks and should be replaced. JRA.
1355 ****************************************************************************/
1356
1357 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1358                                       const struct spoolss_AddDriverInfo6 *src)
1359 {
1360         dst->version            = src->version;
1361
1362         dst->driver_name        = src->driver_name;
1363         dst->architecture       = src->architecture;
1364         dst->driver_path        = src->driver_path;
1365         dst->data_file          = src->data_file;
1366         dst->config_file        = src->config_file;
1367         dst->help_file          = src->help_file;
1368         dst->monitor_name       = src->monitor_name;
1369         dst->default_datatype   = src->default_datatype;
1370         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1371         dst->dependent_files    = src->dependent_files;
1372 }
1373
1374 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1375                                       const struct spoolss_AddDriverInfo8 *src)
1376 {
1377         dst->version            = src->version;
1378
1379         dst->driver_name        = src->driver_name;
1380         dst->architecture       = src->architecture;
1381         dst->driver_path        = src->driver_path;
1382         dst->data_file          = src->data_file;
1383         dst->config_file        = src->config_file;
1384         dst->help_file          = src->help_file;
1385         dst->monitor_name       = src->monitor_name;
1386         dst->default_datatype   = src->default_datatype;
1387         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1388         dst->dependent_files    = src->dependent_files;
1389 }
1390
1391 /****************************************************************************
1392 ****************************************************************************/
1393
1394 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1395                                                 connection_struct *conn,
1396                                                 const char *driver_file,
1397                                                 const char *short_architecture,
1398                                                 uint32_t driver_version,
1399                                                 uint32_t version,
1400                                                 const char *driver_directory)
1401 {
1402         struct smb_filename *smb_fname_old = NULL;
1403         struct smb_filename *smb_fname_new = NULL;
1404         char *old_name = NULL;
1405         char *new_name = NULL;
1406         NTSTATUS status;
1407         WERROR ret;
1408
1409         if (driver_directory != NULL) {
1410                 old_name = talloc_asprintf(mem_ctx,
1411                                            "%s/%s/%s",
1412                                            short_architecture,
1413                                            driver_directory,
1414                                            driver_file);
1415         } else {
1416                 old_name = talloc_asprintf(mem_ctx,
1417                                            "%s/%s",
1418                                            short_architecture,
1419                                            driver_file);
1420         }
1421         if (old_name == NULL) {
1422                 return WERR_NOT_ENOUGH_MEMORY;
1423         }
1424
1425         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1426                                    short_architecture, driver_version, driver_file);
1427         if (new_name == NULL) {
1428                 TALLOC_FREE(old_name);
1429                 return WERR_NOT_ENOUGH_MEMORY;
1430         }
1431
1432         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1433
1434                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1435                 if (!NT_STATUS_IS_OK(status)) {
1436                         ret = WERR_NOT_ENOUGH_MEMORY;
1437                         goto out;
1438                 }
1439
1440                 /* Setup a synthetic smb_filename struct */
1441                 smb_fname_new = talloc_zero(mem_ctx, struct smb_filename);
1442                 if (!smb_fname_new) {
1443                         ret = WERR_NOT_ENOUGH_MEMORY;
1444                         goto out;
1445                 }
1446
1447                 smb_fname_new->base_name = new_name;
1448
1449                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1450                           "'%s'\n", smb_fname_old->base_name,
1451                           smb_fname_new->base_name));
1452
1453                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1454                                    OPENX_FILE_EXISTS_TRUNCATE |
1455                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1456                                    0, false);
1457
1458                 if (!NT_STATUS_IS_OK(status)) {
1459                         DEBUG(0,("move_driver_file_to_download_area: Unable "
1460                                  "to rename [%s] to [%s]: %s\n",
1461                                  smb_fname_old->base_name, new_name,
1462                                  nt_errstr(status)));
1463                         ret = WERR_APP_INIT_FAILURE;
1464                         goto out;
1465                 }
1466         }
1467
1468         ret = WERR_OK;
1469  out:
1470         TALLOC_FREE(smb_fname_old);
1471         TALLOC_FREE(smb_fname_new);
1472         return ret;
1473 }
1474
1475 WERROR move_driver_to_download_area(const struct auth_session_info *session_info,
1476                                     const struct spoolss_AddDriverInfoCtr *r,
1477                                     const char *driver_directory)
1478 {
1479         TALLOC_CTX *frame = talloc_stackframe();
1480         struct spoolss_AddDriverInfo3 *driver;
1481         struct spoolss_AddDriverInfo3 converted_driver;
1482         const char *short_architecture;
1483         struct smb_filename *smb_dname = NULL;
1484         char *new_dir = NULL;
1485         connection_struct *conn = NULL;
1486         NTSTATUS nt_status;
1487         int i;
1488         int ver = 0;
1489         struct smb_filename *oldcwd_fname = NULL;
1490         char *printdollar = NULL;
1491         int printdollar_snum;
1492         WERROR err = WERR_OK;
1493
1494         switch (r->level) {
1495         case 3:
1496                 driver = r->info.info3;
1497                 break;
1498         case 6:
1499                 convert_level_6_to_level3(&converted_driver, r->info.info6);
1500                 driver = &converted_driver;
1501                 break;
1502         case 8:
1503                 convert_level_8_to_level3(&converted_driver, r->info.info8);
1504                 driver = &converted_driver;
1505                 break;
1506         default:
1507                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1508                 TALLOC_FREE(frame);
1509                 return WERR_INVALID_LEVEL;
1510         }
1511
1512         short_architecture = get_short_archi(driver->architecture);
1513         if (!short_architecture) {
1514                 TALLOC_FREE(frame);
1515                 return WERR_UNKNOWN_PRINTER_DRIVER;
1516         }
1517
1518         printdollar_snum = find_service(frame, "print$", &printdollar);
1519         if (!printdollar) {
1520                 TALLOC_FREE(frame);
1521                 return WERR_NOT_ENOUGH_MEMORY;
1522         }
1523         if (printdollar_snum == -1) {
1524                 TALLOC_FREE(frame);
1525                 return WERR_BAD_NET_NAME;
1526         }
1527
1528         nt_status = create_conn_struct_cwd(frame,
1529                                            server_event_context(),
1530                                            server_messaging_context(),
1531                                            &conn,
1532                                            printdollar_snum,
1533                                            lp_path(frame, printdollar_snum),
1534                                            session_info, &oldcwd_fname);
1535         if (!NT_STATUS_IS_OK(nt_status)) {
1536                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1537                          "returned %s\n", nt_errstr(nt_status)));
1538                 err = ntstatus_to_werror(nt_status);
1539                 TALLOC_FREE(frame);
1540                 return err;
1541         }
1542
1543         nt_status = set_conn_force_user_group(conn, printdollar_snum);
1544         if (!NT_STATUS_IS_OK(nt_status)) {
1545                 DEBUG(0, ("failed set force user / group\n"));
1546                 err = ntstatus_to_werror(nt_status);
1547                 goto err_free_conn;
1548         }
1549
1550         if (!become_user_by_session(conn, session_info)) {
1551                 DEBUG(0, ("failed to become user\n"));
1552                 err = WERR_ACCESS_DENIED;
1553                 goto err_free_conn;
1554         }
1555
1556         new_dir = talloc_asprintf(frame,
1557                                 "%s/%d",
1558                                 short_architecture,
1559                                 driver->version);
1560         if (!new_dir) {
1561                 err = WERR_NOT_ENOUGH_MEMORY;
1562                 goto err_exit;
1563         }
1564         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1565         if (!NT_STATUS_IS_OK(nt_status)) {
1566                 err = WERR_NOT_ENOUGH_MEMORY;
1567                 goto err_exit;
1568         }
1569
1570         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1571
1572         nt_status = create_directory(conn, NULL, smb_dname);
1573         if (!NT_STATUS_IS_OK(nt_status)
1574          && !NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1575                 DEBUG(0, ("failed to create driver destination directory: %s\n",
1576                           nt_errstr(nt_status)));
1577                 err = ntstatus_to_werror(nt_status);
1578                 goto err_exit;
1579         }
1580
1581         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1582          * listed for this driver which has already been moved, skip it (note:
1583          * drivers may list the same file name several times. Then check if the
1584          * file already exists in archi\version\, if so, check that the version
1585          * info (or time stamps if version info is unavailable) is newer (or the
1586          * date is later). If it is, move it to archi\version\filexxx.yyy.
1587          * Otherwise, delete the file.
1588          *
1589          * If a file is not moved to archi\version\ because of an error, all the
1590          * rest of the 'unmoved' driver files are removed from archi\. If one or
1591          * more of the driver's files was already moved to archi\version\, it
1592          * potentially leaves the driver in a partially updated state. Version
1593          * trauma will most likely occur if an client attempts to use any printer
1594          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1595          * done is appropriate... later JRR
1596          */
1597
1598         DEBUG(5,("Moving files now !\n"));
1599
1600         if (driver->driver_path && strlen(driver->driver_path)) {
1601
1602                 err = move_driver_file_to_download_area(frame,
1603                                                         conn,
1604                                                         driver->driver_path,
1605                                                         short_architecture,
1606                                                         driver->version,
1607                                                         ver,
1608                                                         driver_directory);
1609                 if (!W_ERROR_IS_OK(err)) {
1610                         goto err_exit;
1611                 }
1612         }
1613
1614         if (driver->data_file && strlen(driver->data_file)) {
1615                 if (!strequal(driver->data_file, driver->driver_path)) {
1616
1617                         err = move_driver_file_to_download_area(frame,
1618                                                                 conn,
1619                                                                 driver->data_file,
1620                                                                 short_architecture,
1621                                                                 driver->version,
1622                                                                 ver,
1623                                                                 driver_directory);
1624                         if (!W_ERROR_IS_OK(err)) {
1625                                 goto err_exit;
1626                         }
1627                 }
1628         }
1629
1630         if (driver->config_file && strlen(driver->config_file)) {
1631                 if (!strequal(driver->config_file, driver->driver_path) &&
1632                     !strequal(driver->config_file, driver->data_file)) {
1633
1634                         err = move_driver_file_to_download_area(frame,
1635                                                                 conn,
1636                                                                 driver->config_file,
1637                                                                 short_architecture,
1638                                                                 driver->version,
1639                                                                 ver,
1640                                                                 driver_directory);
1641                         if (!W_ERROR_IS_OK(err)) {
1642                                 goto err_exit;
1643                         }
1644                 }
1645         }
1646
1647         if (driver->help_file && strlen(driver->help_file)) {
1648                 if (!strequal(driver->help_file, driver->driver_path) &&
1649                     !strequal(driver->help_file, driver->data_file) &&
1650                     !strequal(driver->help_file, driver->config_file)) {
1651
1652                         err = move_driver_file_to_download_area(frame,
1653                                                                 conn,
1654                                                                 driver->help_file,
1655                                                                 short_architecture,
1656                                                                 driver->version,
1657                                                                 ver,
1658                                                                 driver_directory);
1659                         if (!W_ERROR_IS_OK(err)) {
1660                                 goto err_exit;
1661                         }
1662                 }
1663         }
1664
1665         if (driver->dependent_files && driver->dependent_files->string) {
1666                 for (i=0; driver->dependent_files->string[i]; i++) {
1667                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1668                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
1669                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
1670                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
1671                                 int j;
1672                                 for (j=0; j < i; j++) {
1673                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1674                                                 goto NextDriver;
1675                                         }
1676                                 }
1677
1678                                 err = move_driver_file_to_download_area(frame,
1679                                                                         conn,
1680                                                                         driver->dependent_files->string[i],
1681                                                                         short_architecture,
1682                                                                         driver->version,
1683                                                                         ver,
1684                                                                         driver_directory);
1685                                 if (!W_ERROR_IS_OK(err)) {
1686                                         goto err_exit;
1687                                 }
1688                         }
1689                 NextDriver: ;
1690                 }
1691         }
1692
1693         err = WERR_OK;
1694  err_exit:
1695         unbecome_user();
1696  err_free_conn:
1697         if (conn != NULL) {
1698                 vfs_ChDir(conn, oldcwd_fname);
1699                 SMB_VFS_DISCONNECT(conn);
1700                 conn_free(conn);
1701         }
1702
1703         TALLOC_FREE(frame);
1704         return err;
1705 }
1706
1707 /****************************************************************************
1708   Determine whether or not a particular driver is currently assigned
1709   to a printer
1710 ****************************************************************************/
1711
1712 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
1713                            struct dcerpc_binding_handle *b,
1714                            const struct spoolss_DriverInfo8 *r)
1715 {
1716         int snum;
1717         int n_services = lp_numservices();
1718         bool in_use = false;
1719         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1720         WERROR result;
1721
1722         if (!r) {
1723                 return false;
1724         }
1725
1726         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1727
1728         /* loop through the printers.tdb and check for the drivername */
1729
1730         for (snum=0; snum<n_services && !in_use; snum++) {
1731                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1732                         continue;
1733                 }
1734
1735                 result = winreg_get_printer(mem_ctx, b,
1736                                             lp_servicename(talloc_tos(), snum),
1737                                             &pinfo2);
1738                 if (!W_ERROR_IS_OK(result)) {
1739                         continue; /* skip */
1740                 }
1741
1742                 if (strequal(r->driver_name, pinfo2->drivername)) {
1743                         in_use = true;
1744                 }
1745
1746                 TALLOC_FREE(pinfo2);
1747         }
1748
1749         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1750
1751         if ( in_use ) {
1752                 struct spoolss_DriverInfo8 *driver = NULL;
1753                 WERROR werr;
1754
1755                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1756
1757                 /* we can still remove the driver if there is one of
1758                    "Windows NT x86" version 2 or 3 left */
1759
1760                 if (strequal(SPOOLSS_ARCHITECTURE_NT_X86, r->architecture)) {
1761                         if (r->version == 2) {
1762                                 werr = winreg_get_driver(mem_ctx, b,
1763                                                          r->architecture,
1764                                                          r->driver_name,
1765                                                          3, &driver);
1766                         } else if (r->version == 3) {
1767                                 werr = winreg_get_driver(mem_ctx, b,
1768                                                          r->architecture,
1769                                                          r->driver_name,
1770                                                          2, &driver);
1771                         } else {
1772                                 DBG_ERR("Unknown driver version (%d)\n",
1773                                         r->version);
1774                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
1775                         }
1776                 } else if (strequal(SPOOLSS_ARCHITECTURE_x64, r->architecture)) {
1777                         werr = winreg_get_driver(mem_ctx, b,
1778                                                  SPOOLSS_ARCHITECTURE_NT_X86,
1779                                                  r->driver_name,
1780                                                  DRIVER_ANY_VERSION,
1781                                                  &driver);
1782                 } else {
1783                         DBG_ERR("Unknown driver architecture: %s\n",
1784                                 r->architecture);
1785                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
1786                 }
1787
1788                 /* now check the error code */
1789
1790                 if ( W_ERROR_IS_OK(werr) ) {
1791                         /* it's ok to remove the driver, we have other architctures left */
1792                         in_use = false;
1793                         talloc_free(driver);
1794                 }
1795         }
1796
1797         /* report that the driver is not in use by default */
1798
1799         return in_use;
1800 }
1801
1802
1803 /**********************************************************************
1804  Check to see if a ogiven file is in use by *info
1805  *********************************************************************/
1806
1807 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1808 {
1809         int i = 0;
1810
1811         if ( !info )
1812                 return False;
1813
1814         /* mz: skip files that are in the list but already deleted */
1815         if (!file || !file[0]) {
1816                 return false;
1817         }
1818
1819         if (strequal(file, info->driver_path))
1820                 return True;
1821
1822         if (strequal(file, info->data_file))
1823                 return True;
1824
1825         if (strequal(file, info->config_file))
1826                 return True;
1827
1828         if (strequal(file, info->help_file))
1829                 return True;
1830
1831         /* see of there are any dependent files to examine */
1832
1833         if (!info->dependent_files)
1834                 return False;
1835
1836         while (info->dependent_files[i] && *info->dependent_files[i]) {
1837                 if (strequal(file, info->dependent_files[i]))
1838                         return True;
1839                 i++;
1840         }
1841
1842         return False;
1843
1844 }
1845
1846 /**********************************************************************
1847  Utility function to remove the dependent file pointed to by the
1848  input parameter from the list
1849  *********************************************************************/
1850
1851 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1852 {
1853
1854         /* bump everything down a slot */
1855
1856         while (files && files[idx+1]) {
1857                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1858                 idx++;
1859         }
1860
1861         files[idx] = NULL;
1862
1863         return;
1864 }
1865
1866 /**********************************************************************
1867  Check if any of the files used by src are also used by drv
1868  *********************************************************************/
1869
1870 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1871                                    struct spoolss_DriverInfo8 *src,
1872                                    const struct spoolss_DriverInfo8 *drv)
1873 {
1874         bool    in_use = False;
1875         int     i = 0;
1876
1877         if ( !src || !drv )
1878                 return False;
1879
1880         /* check each file.  Remove it from the src structure if it overlaps */
1881
1882         if (drv_file_in_use(src->driver_path, drv)) {
1883                 in_use = True;
1884                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1885                 src->driver_path = talloc_strdup(mem_ctx, "");
1886                 if (!src->driver_path) { return false; }
1887         }
1888
1889         if (drv_file_in_use(src->data_file, drv)) {
1890                 in_use = True;
1891                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1892                 src->data_file = talloc_strdup(mem_ctx, "");
1893                 if (!src->data_file) { return false; }
1894         }
1895
1896         if (drv_file_in_use(src->config_file, drv)) {
1897                 in_use = True;
1898                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1899                 src->config_file = talloc_strdup(mem_ctx, "");
1900                 if (!src->config_file) { return false; }
1901         }
1902
1903         if (drv_file_in_use(src->help_file, drv)) {
1904                 in_use = True;
1905                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1906                 src->help_file = talloc_strdup(mem_ctx, "");
1907                 if (!src->help_file) { return false; }
1908         }
1909
1910         /* are there any dependentfiles to examine? */
1911
1912         if (!src->dependent_files)
1913                 return in_use;
1914
1915         while (src->dependent_files[i] && *src->dependent_files[i]) {
1916                 if (drv_file_in_use(src->dependent_files[i], drv)) {
1917                         in_use = True;
1918                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1919                         trim_dependent_file(mem_ctx, src->dependent_files, i);
1920                 } else
1921                         i++;
1922         }
1923
1924         return in_use;
1925 }
1926
1927 /****************************************************************************
1928   Determine whether or not a particular driver files are currently being
1929   used by any other driver.
1930
1931   Return value is True if any files were in use by other drivers
1932   and False otherwise.
1933
1934   Upon return, *info has been modified to only contain the driver files
1935   which are not in use
1936
1937   Fix from mz:
1938
1939   This needs to check all drivers to ensure that all files in use
1940   have been removed from *info, not just the ones in the first
1941   match.
1942 ****************************************************************************/
1943
1944 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1945                                  struct dcerpc_binding_handle *b,
1946                                  struct spoolss_DriverInfo8 *info)
1947 {
1948         int                             i;
1949         uint32_t                                version;
1950         struct spoolss_DriverInfo8      *driver;
1951         bool in_use = false;
1952         uint32_t num_drivers;
1953         const char **drivers;
1954         WERROR result;
1955
1956         if ( !info )
1957                 return False;
1958
1959         version = info->version;
1960
1961         /* loop over all driver versions */
1962
1963         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1964
1965         /* get the list of drivers */
1966
1967         result = winreg_get_driver_list(mem_ctx, b,
1968                                         info->architecture, version,
1969                                         &num_drivers, &drivers);
1970         if (!W_ERROR_IS_OK(result)) {
1971                 return true;
1972         }
1973
1974         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1975                      num_drivers, info->architecture, version));
1976
1977         /* check each driver for overlap in files */
1978
1979         for (i = 0; i < num_drivers; i++) {
1980                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1981
1982                 driver = NULL;
1983
1984                 result = winreg_get_driver(mem_ctx, b,
1985                                            info->architecture, drivers[i],
1986                                            version, &driver);
1987                 if (!W_ERROR_IS_OK(result)) {
1988                         talloc_free(drivers);
1989                         return True;
1990                 }
1991
1992                 /* check if d2 uses any files from d1 */
1993                 /* only if this is a different driver than the one being deleted */
1994
1995                 if (!strequal(info->driver_name, driver->driver_name)) {
1996                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1997                                 /* mz: Do not instantly return -
1998                                  * we need to ensure this file isn't
1999                                  * also in use by other drivers. */
2000                                 in_use = true;
2001                         }
2002                 }
2003
2004                 talloc_free(driver);
2005         }
2006
2007         talloc_free(drivers);
2008
2009         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
2010
2011         return in_use;
2012 }
2013
2014 static NTSTATUS driver_unlink_internals(connection_struct *conn,
2015                                         const char *short_arch,
2016                                         int vers,
2017                                         const char *fname)
2018 {
2019         TALLOC_CTX *tmp_ctx = talloc_new(conn);
2020         struct smb_filename *smb_fname = NULL;
2021         char *print_dlr_path;
2022         NTSTATUS status = NT_STATUS_NO_MEMORY;
2023
2024         print_dlr_path = talloc_asprintf(tmp_ctx, "%s/%d/%s",
2025                                          short_arch, vers, fname);
2026         if (print_dlr_path == NULL) {
2027                 goto err_out;
2028         }
2029
2030         smb_fname = synthetic_smb_fname(tmp_ctx, print_dlr_path, NULL, NULL, 0);
2031         if (smb_fname == NULL) {
2032                 goto err_out;
2033         }
2034
2035         status = unlink_internals(conn, NULL, 0, smb_fname, false);
2036 err_out:
2037         talloc_free(tmp_ctx);
2038         return status;
2039 }
2040
2041 /****************************************************************************
2042   Actually delete the driver files.  Make sure that
2043   printer_driver_files_in_use() return False before calling
2044   this.
2045 ****************************************************************************/
2046
2047 bool delete_driver_files(const struct auth_session_info *session_info,
2048                          const struct spoolss_DriverInfo8 *r)
2049 {
2050         TALLOC_CTX *frame = talloc_stackframe();
2051         const char *short_arch;
2052         connection_struct *conn;
2053         NTSTATUS nt_status;
2054         struct smb_filename *oldcwd_fname = NULL;
2055         char *printdollar = NULL;
2056         int printdollar_snum;
2057         bool ret = false;
2058
2059         if (!r) {
2060                 TALLOC_FREE(frame);
2061                 return false;
2062         }
2063
2064         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
2065                 r->driver_name, r->version));
2066
2067         printdollar_snum = find_service(frame, "print$", &printdollar);
2068         if (!printdollar) {
2069                 TALLOC_FREE(frame);
2070                 return false;
2071         }
2072         if (printdollar_snum == -1) {
2073                 TALLOC_FREE(frame);
2074                 return false;
2075         }
2076
2077         nt_status = create_conn_struct_cwd(frame,
2078                                            server_event_context(),
2079                                            server_messaging_context(),
2080                                            &conn,
2081                                            printdollar_snum,
2082                                            lp_path(frame, printdollar_snum),
2083                                            session_info, &oldcwd_fname);
2084         if (!NT_STATUS_IS_OK(nt_status)) {
2085                 DEBUG(0,("delete_driver_files: create_conn_struct "
2086                          "returned %s\n", nt_errstr(nt_status)));
2087                 TALLOC_FREE(frame);
2088                 return false;
2089         }
2090
2091         nt_status = set_conn_force_user_group(conn, printdollar_snum);
2092         if (!NT_STATUS_IS_OK(nt_status)) {
2093                 DEBUG(0, ("failed set force user / group\n"));
2094                 ret = false;
2095                 goto err_free_conn;
2096         }
2097
2098         if (!become_user_by_session(conn, session_info)) {
2099                 DEBUG(0, ("failed to become user\n"));
2100                 ret = false;
2101                 goto err_free_conn;
2102         }
2103
2104         if ( !CAN_WRITE(conn) ) {
2105                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
2106                 ret = false;
2107                 goto err_out;
2108         }
2109
2110         short_arch = get_short_archi(r->architecture);
2111         if (short_arch == NULL) {
2112                 DEBUG(0, ("bad architecture %s\n", r->architecture));
2113                 ret = false;
2114                 goto err_out;
2115         }
2116
2117         /* now delete the files */
2118
2119         if (r->driver_path && r->driver_path[0]) {
2120                 DEBUG(10,("deleting driverfile [%s]\n", r->driver_path));
2121                 driver_unlink_internals(conn, short_arch, r->version, r->driver_path);
2122         }
2123
2124         if (r->config_file && r->config_file[0]) {
2125                 DEBUG(10,("deleting configfile [%s]\n", r->config_file));
2126                 driver_unlink_internals(conn, short_arch, r->version, r->config_file);
2127         }
2128
2129         if (r->data_file && r->data_file[0]) {
2130                 DEBUG(10,("deleting datafile [%s]\n", r->data_file));
2131                 driver_unlink_internals(conn, short_arch, r->version, r->data_file);
2132         }
2133
2134         if (r->help_file && r->help_file[0]) {
2135                 DEBUG(10,("deleting helpfile [%s]\n", r->help_file));
2136                 driver_unlink_internals(conn, short_arch, r->version, r->help_file);
2137         }
2138
2139         if (r->dependent_files) {
2140                 int i = 0;
2141                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
2142                         DEBUG(10,("deleting dependent file [%s]\n", r->dependent_files[i]));
2143                         driver_unlink_internals(conn, short_arch, r->version, r->dependent_files[i]);
2144                         i++;
2145                 }
2146         }
2147
2148         ret = true;
2149  err_out:
2150         unbecome_user();
2151  err_free_conn:
2152         if (conn != NULL) {
2153                 vfs_ChDir(conn, oldcwd_fname);
2154                 SMB_VFS_DISCONNECT(conn);
2155                 conn_free(conn);
2156         }
2157         TALLOC_FREE(frame);
2158         return ret;
2159 }
2160
2161 /* error code:
2162         0: everything OK
2163         1: level not implemented
2164         2: file doesn't exist
2165         3: can't allocate memory
2166         4: can't free memory
2167         5: non existent struct
2168 */
2169
2170 /*
2171         A printer and a printer driver are 2 different things.
2172         NT manages them separatelly, Samba does the same.
2173         Why ? Simply because it's easier and it makes sense !
2174
2175         Now explanation: You have 3 printers behind your samba server,
2176         2 of them are the same make and model (laser A and B). But laser B
2177         has an 3000 sheet feeder and laser A doesn't such an option.
2178         Your third printer is an old dot-matrix model for the accounting :-).
2179
2180         If the /usr/local/samba/lib directory (default dir), you will have
2181         5 files to describe all of this.
2182
2183         3 files for the printers (1 by printer):
2184                 NTprinter_laser A
2185                 NTprinter_laser B
2186                 NTprinter_accounting
2187         2 files for the drivers (1 for the laser and 1 for the dot matrix)
2188                 NTdriver_printer model X
2189                 NTdriver_printer model Y
2190
2191 jfm: I should use this comment for the text file to explain
2192         same thing for the forms BTW.
2193         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2194
2195 */
2196
2197 /* Convert generic access rights to printer object specific access rights.
2198    It turns out that NT4 security descriptors use generic access rights and
2199    NT5 the object specific ones. */
2200
2201 void map_printer_permissions(struct security_descriptor *sd)
2202 {
2203         int i;
2204
2205         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2206                 se_map_generic(&sd->dacl->aces[i].access_mask,
2207                                &printer_generic_mapping);
2208         }
2209 }
2210
2211 void map_job_permissions(struct security_descriptor *sd)
2212 {
2213         int i;
2214
2215         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2216                 se_map_generic(&sd->dacl->aces[i].access_mask,
2217                                &job_generic_mapping);
2218         }
2219 }
2220
2221
2222 /****************************************************************************
2223  Check a user has permissions to perform the given operation.  We use the
2224  permission constants defined in include/rpc_spoolss.h to check the various
2225  actions we perform when checking printer access.
2226
2227    PRINTER_ACCESS_ADMINISTER:
2228        print_queue_pause, print_queue_resume, update_printer_sec,
2229        update_printer, spoolss_addprinterex_level_2,
2230        _spoolss_setprinterdata
2231
2232    PRINTER_ACCESS_USE:
2233        print_job_start
2234
2235    JOB_ACCESS_ADMINISTER:
2236        print_job_delete, print_job_pause, print_job_resume,
2237        print_queue_purge
2238
2239   Try access control in the following order (for performance reasons):
2240     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
2241     2)  check security descriptor (bit comparisons in memory)
2242     3)  "printer admins" (may result in numerous calls to winbind)
2243
2244  ****************************************************************************/
2245 WERROR print_access_check(const struct auth_session_info *session_info,
2246                           struct messaging_context *msg_ctx, int snum,
2247                           int access_type)
2248 {
2249         struct spoolss_security_descriptor *secdesc = NULL;
2250         uint32_t access_granted;
2251         size_t sd_size;
2252         NTSTATUS status;
2253         WERROR result;
2254         const char *pname;
2255         TALLOC_CTX *mem_ctx = NULL;
2256
2257         /* If user is NULL then use the current_user structure */
2258
2259         /* Always allow root or SE_PRINT_OPERATROR to do anything */
2260
2261         if ((session_info->unix_token->uid == sec_initial_uid())
2262             || security_token_has_privilege(session_info->security_token,
2263                                             SEC_PRIV_PRINT_OPERATOR)) {
2264                 return WERR_OK;
2265         }
2266
2267         /* Get printer name */
2268
2269         pname = lp_printername(talloc_tos(), snum);
2270
2271         if (!pname || !*pname) {
2272                 return WERR_ACCESS_DENIED;
2273         }
2274
2275         /* Get printer security descriptor */
2276
2277         if(!(mem_ctx = talloc_init("print_access_check"))) {
2278                 return WERR_NOT_ENOUGH_MEMORY;
2279         }
2280
2281         result = winreg_get_printer_secdesc_internal(mem_ctx,
2282                                             get_session_info_system(),
2283                                             msg_ctx,
2284                                             pname,
2285                                             &secdesc);
2286         if (!W_ERROR_IS_OK(result)) {
2287                 talloc_destroy(mem_ctx);
2288                 return WERR_NOT_ENOUGH_MEMORY;
2289         }
2290
2291         if (access_type == JOB_ACCESS_ADMINISTER) {
2292                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2293
2294                 /* Create a child security descriptor to check permissions
2295                    against.  This is because print jobs are child objects
2296                    objects of a printer. */
2297                 status = se_create_child_secdesc(mem_ctx,
2298                                                  &secdesc,
2299                                                  &sd_size,
2300                                                  parent_secdesc,
2301                                                  parent_secdesc->owner_sid,
2302                                                  parent_secdesc->group_sid,
2303                                                  false);
2304                 if (!NT_STATUS_IS_OK(status)) {
2305                         talloc_destroy(mem_ctx);
2306                         return ntstatus_to_werror(status);
2307                 }
2308
2309                 map_job_permissions(secdesc);
2310         } else {
2311                 map_printer_permissions(secdesc);
2312         }
2313
2314         /* Check access */
2315         status = se_access_check(secdesc, session_info->security_token, access_type,
2316                                  &access_granted);
2317
2318         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2319
2320         talloc_destroy(mem_ctx);
2321
2322         return ntstatus_to_werror(status);
2323 }
2324
2325 /****************************************************************************
2326  Check the time parameters allow a print operation.
2327 *****************************************************************************/
2328
2329 bool print_time_access_check(const struct auth_session_info *session_info,
2330                              struct messaging_context *msg_ctx,
2331                              const char *servicename)
2332 {
2333         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2334         WERROR result;
2335         bool ok = False;
2336         time_t now = time(NULL);
2337         struct tm *t;
2338         uint32_t mins;
2339
2340         result = winreg_get_printer_internal(NULL, session_info, msg_ctx,
2341                                     servicename, &pinfo2);
2342         if (!W_ERROR_IS_OK(result)) {
2343                 return False;
2344         }
2345
2346         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2347                 ok = True;
2348         }
2349
2350         t = gmtime(&now);
2351         mins = (uint32_t)t->tm_hour*60 + (uint32_t)t->tm_min;
2352
2353         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2354                 ok = True;
2355         }
2356
2357         TALLOC_FREE(pinfo2);
2358
2359         if (!ok) {
2360                 errno = EACCES;
2361         }
2362
2363         return ok;
2364 }
2365
2366 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2367                         const struct auth_session_info *session_info,
2368                         struct messaging_context *msg_ctx,
2369                         const char *printer)
2370 {
2371         WERROR result;
2372
2373         result = winreg_delete_printer_key_internal(mem_ctx, session_info, msg_ctx,
2374                                            printer, "");
2375         if (!W_ERROR_IS_OK(result)) {
2376                 DEBUG(0, ("nt_printer_remove: failed to remove printer %s: "
2377                 "%s\n", printer, win_errstr(result)));
2378         }
2379 }
2380
2381 void nt_printer_add(TALLOC_CTX *mem_ctx,
2382                     const struct auth_session_info *session_info,
2383                     struct messaging_context *msg_ctx,
2384                     const char *printer)
2385 {
2386         WERROR result;
2387
2388         result = winreg_create_printer_internal(mem_ctx, session_info, msg_ctx,
2389                                                 printer);
2390         if (!W_ERROR_IS_OK(result)) {
2391                 DEBUG(0, ("nt_printer_add: failed to add printer %s: %s\n",
2392                           printer, win_errstr(result)));
2393         }
2394 }