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