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