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