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