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