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