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