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