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