s3: Lift the smbd_messaging_context from winreg_get_printer_secdesc
[kai/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();
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                            const struct spoolss_DriverInfo8 *r)
1557 {
1558         int snum;
1559         int n_services = lp_numservices();
1560         bool in_use = False;
1561         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
1562         WERROR result;
1563
1564         if (!r) {
1565                 return false;
1566         }
1567
1568         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
1569
1570         /* loop through the printers.tdb and check for the drivername */
1571
1572         for (snum=0; snum<n_services && !in_use; snum++) {
1573                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1574                         continue;
1575                 }
1576
1577                 result = winreg_get_printer(mem_ctx, server_info,
1578                                             smbd_messaging_context(), NULL,
1579                                             lp_servicename(snum), &pinfo2);
1580                 if (!W_ERROR_IS_OK(result)) {
1581                         continue; /* skip */
1582                 }
1583
1584                 if (strequal(r->driver_name, pinfo2->drivername)) {
1585                         in_use = True;
1586                 }
1587
1588                 TALLOC_FREE(pinfo2);
1589         }
1590
1591         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
1592
1593         if ( in_use ) {
1594                 struct spoolss_DriverInfo8 *driver;
1595                 WERROR werr;
1596
1597                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
1598
1599                 /* we can still remove the driver if there is one of
1600                    "Windows NT x86" version 2 or 3 left */
1601
1602                 if (!strequal("Windows NT x86", r->architecture)) {
1603                         werr = winreg_get_driver(mem_ctx, server_info,
1604                                                  "Windows NT x86",
1605                                                  r->driver_name,
1606                                                  DRIVER_ANY_VERSION,
1607                                                  &driver);
1608                 } else if (r->version == 2) {
1609                         werr = winreg_get_driver(mem_ctx, server_info,
1610                                                  "Windows NT x86",
1611                                                  r->driver_name,
1612                                                  3, &driver);
1613                 } else if (r->version == 3) {
1614                         werr = winreg_get_driver(mem_ctx, server_info,
1615                                                  "Windows NT x86",
1616                                                  r->driver_name,
1617                                                  2, &driver);
1618                 } else {
1619                         DEBUG(0, ("printer_driver_in_use: ERROR!"
1620                                   " unknown driver version (%d)\n",
1621                                   r->version));
1622                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
1623                 }
1624
1625                 /* now check the error code */
1626
1627                 if ( W_ERROR_IS_OK(werr) ) {
1628                         /* it's ok to remove the driver, we have other architctures left */
1629                         in_use = False;
1630                         talloc_free(driver);
1631                 }
1632         }
1633
1634         /* report that the driver is not in use by default */
1635
1636         return in_use;
1637 }
1638
1639
1640 /**********************************************************************
1641  Check to see if a ogiven file is in use by *info
1642  *********************************************************************/
1643
1644 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
1645 {
1646         int i = 0;
1647
1648         if ( !info )
1649                 return False;
1650
1651         /* mz: skip files that are in the list but already deleted */
1652         if (!file || !file[0]) {
1653                 return false;
1654         }
1655
1656         if (strequal(file, info->driver_path))
1657                 return True;
1658
1659         if (strequal(file, info->data_file))
1660                 return True;
1661
1662         if (strequal(file, info->config_file))
1663                 return True;
1664
1665         if (strequal(file, info->help_file))
1666                 return True;
1667
1668         /* see of there are any dependent files to examine */
1669
1670         if (!info->dependent_files)
1671                 return False;
1672
1673         while (info->dependent_files[i] && *info->dependent_files[i]) {
1674                 if (strequal(file, info->dependent_files[i]))
1675                         return True;
1676                 i++;
1677         }
1678
1679         return False;
1680
1681 }
1682
1683 /**********************************************************************
1684  Utility function to remove the dependent file pointed to by the
1685  input parameter from the list
1686  *********************************************************************/
1687
1688 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
1689 {
1690
1691         /* bump everything down a slot */
1692
1693         while (files && files[idx+1]) {
1694                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
1695                 idx++;
1696         }
1697
1698         files[idx] = NULL;
1699
1700         return;
1701 }
1702
1703 /**********************************************************************
1704  Check if any of the files used by src are also used by drv
1705  *********************************************************************/
1706
1707 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
1708                                    struct spoolss_DriverInfo8 *src,
1709                                    const struct spoolss_DriverInfo8 *drv)
1710 {
1711         bool    in_use = False;
1712         int     i = 0;
1713
1714         if ( !src || !drv )
1715                 return False;
1716
1717         /* check each file.  Remove it from the src structure if it overlaps */
1718
1719         if (drv_file_in_use(src->driver_path, drv)) {
1720                 in_use = True;
1721                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
1722                 src->driver_path = talloc_strdup(mem_ctx, "");
1723                 if (!src->driver_path) { return false; }
1724         }
1725
1726         if (drv_file_in_use(src->data_file, drv)) {
1727                 in_use = True;
1728                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
1729                 src->data_file = talloc_strdup(mem_ctx, "");
1730                 if (!src->data_file) { return false; }
1731         }
1732
1733         if (drv_file_in_use(src->config_file, drv)) {
1734                 in_use = True;
1735                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
1736                 src->config_file = talloc_strdup(mem_ctx, "");
1737                 if (!src->config_file) { return false; }
1738         }
1739
1740         if (drv_file_in_use(src->help_file, drv)) {
1741                 in_use = True;
1742                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
1743                 src->help_file = talloc_strdup(mem_ctx, "");
1744                 if (!src->help_file) { return false; }
1745         }
1746
1747         /* are there any dependentfiles to examine? */
1748
1749         if (!src->dependent_files)
1750                 return in_use;
1751
1752         while (src->dependent_files[i] && *src->dependent_files[i]) {
1753                 if (drv_file_in_use(src->dependent_files[i], drv)) {
1754                         in_use = True;
1755                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
1756                         trim_dependent_file(mem_ctx, src->dependent_files, i);
1757                 } else
1758                         i++;
1759         }
1760
1761         return in_use;
1762 }
1763
1764 /****************************************************************************
1765   Determine whether or not a particular driver files are currently being
1766   used by any other driver.
1767
1768   Return value is True if any files were in use by other drivers
1769   and False otherwise.
1770
1771   Upon return, *info has been modified to only contain the driver files
1772   which are not in use
1773
1774   Fix from mz:
1775
1776   This needs to check all drivers to ensure that all files in use
1777   have been removed from *info, not just the ones in the first
1778   match.
1779 ****************************************************************************/
1780
1781 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
1782                                  struct auth_serversupplied_info *server_info,
1783                                  struct spoolss_DriverInfo8 *info)
1784 {
1785         int                             i;
1786         uint32                          version;
1787         struct spoolss_DriverInfo8      *driver;
1788         bool in_use = false;
1789         uint32_t num_drivers;
1790         const char **drivers;
1791         WERROR result;
1792
1793         if ( !info )
1794                 return False;
1795
1796         version = info->version;
1797
1798         /* loop over all driver versions */
1799
1800         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
1801
1802         /* get the list of drivers */
1803
1804         result = winreg_get_driver_list(mem_ctx, server_info,
1805                                         info->architecture, version,
1806                                         &num_drivers, &drivers);
1807         if (!W_ERROR_IS_OK(result)) {
1808                 return true;
1809         }
1810
1811         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
1812                      num_drivers, info->architecture, version));
1813
1814         /* check each driver for overlap in files */
1815
1816         for (i = 0; i < num_drivers; i++) {
1817                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
1818
1819                 driver = NULL;
1820
1821                 result = winreg_get_driver(mem_ctx, server_info,
1822                                            info->architecture, drivers[i],
1823                                            version, &driver);
1824                 if (!W_ERROR_IS_OK(result)) {
1825                         talloc_free(drivers);
1826                         return True;
1827                 }
1828
1829                 /* check if d2 uses any files from d1 */
1830                 /* only if this is a different driver than the one being deleted */
1831
1832                 if (!strequal(info->driver_name, driver->driver_name)) {
1833                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
1834                                 /* mz: Do not instantly return -
1835                                  * we need to ensure this file isn't
1836                                  * also in use by other drivers. */
1837                                 in_use = true;
1838                         }
1839                 }
1840
1841                 talloc_free(driver);
1842         }
1843
1844         talloc_free(drivers);
1845
1846         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
1847
1848         return in_use;
1849 }
1850
1851 static NTSTATUS driver_unlink_internals(connection_struct *conn,
1852                                         const char *name)
1853 {
1854         struct smb_filename *smb_fname = NULL;
1855         NTSTATUS status;
1856
1857         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
1858             &smb_fname);
1859         if (!NT_STATUS_IS_OK(status)) {
1860                 return status;
1861         }
1862
1863         status = unlink_internals(conn, NULL, 0, smb_fname, false);
1864
1865         TALLOC_FREE(smb_fname);
1866         return status;
1867 }
1868
1869 /****************************************************************************
1870   Actually delete the driver files.  Make sure that
1871   printer_driver_files_in_use() return False before calling
1872   this.
1873 ****************************************************************************/
1874
1875 bool delete_driver_files(struct auth_serversupplied_info *server_info,
1876                          const struct spoolss_DriverInfo8 *r)
1877 {
1878         int i = 0;
1879         char *s;
1880         const char *file;
1881         connection_struct *conn;
1882         NTSTATUS nt_status;
1883         char *oldcwd;
1884         fstring printdollar;
1885         int printdollar_snum;
1886         bool ret = false;
1887
1888         if (!r) {
1889                 return false;
1890         }
1891
1892         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
1893                 r->driver_name, r->version));
1894
1895         fstrcpy(printdollar, "print$");
1896
1897         printdollar_snum = find_service(printdollar);
1898         if (printdollar_snum == -1) {
1899                 return false;
1900         }
1901
1902         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1903                                        lp_pathname(printdollar_snum),
1904                                        server_info, &oldcwd);
1905         if (!NT_STATUS_IS_OK(nt_status)) {
1906                 DEBUG(0,("delete_driver_files: create_conn_struct "
1907                          "returned %s\n", nt_errstr(nt_status)));
1908                 return false;
1909         }
1910
1911         if ( !CAN_WRITE(conn) ) {
1912                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
1913                 goto fail;
1914         }
1915
1916         /* now delete the files; must strip the '\print$' string from
1917            fron of path                                                */
1918
1919         if (r->driver_path && r->driver_path[0]) {
1920                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
1921                         file = s;
1922                         DEBUG(10,("deleting driverfile [%s]\n", s));
1923                         driver_unlink_internals(conn, file);
1924                 }
1925         }
1926
1927         if (r->config_file && r->config_file[0]) {
1928                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
1929                         file = s;
1930                         DEBUG(10,("deleting configfile [%s]\n", s));
1931                         driver_unlink_internals(conn, file);
1932                 }
1933         }
1934
1935         if (r->data_file && r->data_file[0]) {
1936                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
1937                         file = s;
1938                         DEBUG(10,("deleting datafile [%s]\n", s));
1939                         driver_unlink_internals(conn, file);
1940                 }
1941         }
1942
1943         if (r->help_file && r->help_file[0]) {
1944                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
1945                         file = s;
1946                         DEBUG(10,("deleting helpfile [%s]\n", s));
1947                         driver_unlink_internals(conn, file);
1948                 }
1949         }
1950
1951         /* check if we are done removing files */
1952
1953         if (r->dependent_files) {
1954                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
1955                         char *p;
1956
1957                         /* bypass the "\print$" portion of the path */
1958
1959                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
1960                                 file = p;
1961                                 DEBUG(10,("deleting dependent file [%s]\n", file));
1962                                 driver_unlink_internals(conn, file);
1963                         }
1964
1965                         i++;
1966                 }
1967         }
1968
1969         goto done;
1970  fail:
1971         ret = false;
1972  done:
1973         if (conn != NULL) {
1974                 vfs_ChDir(conn, oldcwd);
1975                 conn_free(conn);
1976         }
1977         return ret;
1978 }
1979
1980 /* error code:
1981         0: everything OK
1982         1: level not implemented
1983         2: file doesn't exist
1984         3: can't allocate memory
1985         4: can't free memory
1986         5: non existant struct
1987 */
1988
1989 /*
1990         A printer and a printer driver are 2 different things.
1991         NT manages them separatelly, Samba does the same.
1992         Why ? Simply because it's easier and it makes sense !
1993
1994         Now explanation: You have 3 printers behind your samba server,
1995         2 of them are the same make and model (laser A and B). But laser B
1996         has an 3000 sheet feeder and laser A doesn't such an option.
1997         Your third printer is an old dot-matrix model for the accounting :-).
1998
1999         If the /usr/local/samba/lib directory (default dir), you will have
2000         5 files to describe all of this.
2001
2002         3 files for the printers (1 by printer):
2003                 NTprinter_laser A
2004                 NTprinter_laser B
2005                 NTprinter_accounting
2006         2 files for the drivers (1 for the laser and 1 for the dot matrix)
2007                 NTdriver_printer model X
2008                 NTdriver_printer model Y
2009
2010 jfm: I should use this comment for the text file to explain
2011         same thing for the forms BTW.
2012         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2013
2014 */
2015
2016 /* Convert generic access rights to printer object specific access rights.
2017    It turns out that NT4 security descriptors use generic access rights and
2018    NT5 the object specific ones. */
2019
2020 void map_printer_permissions(struct security_descriptor *sd)
2021 {
2022         int i;
2023
2024         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2025                 se_map_generic(&sd->dacl->aces[i].access_mask,
2026                                &printer_generic_mapping);
2027         }
2028 }
2029
2030 void map_job_permissions(struct security_descriptor *sd)
2031 {
2032         int i;
2033
2034         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2035                 se_map_generic(&sd->dacl->aces[i].access_mask,
2036                                &job_generic_mapping);
2037         }
2038 }
2039
2040
2041 /****************************************************************************
2042  Check a user has permissions to perform the given operation.  We use the
2043  permission constants defined in include/rpc_spoolss.h to check the various
2044  actions we perform when checking printer access.
2045
2046    PRINTER_ACCESS_ADMINISTER:
2047        print_queue_pause, print_queue_resume, update_printer_sec,
2048        update_printer, spoolss_addprinterex_level_2,
2049        _spoolss_setprinterdata
2050
2051    PRINTER_ACCESS_USE:
2052        print_job_start
2053
2054    JOB_ACCESS_ADMINISTER:
2055        print_job_delete, print_job_pause, print_job_resume,
2056        print_queue_purge
2057
2058   Try access control in the following order (for performance reasons):
2059     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
2060     2)  check security descriptor (bit comparisons in memory)
2061     3)  "printer admins" (may result in numerous calls to winbind)
2062
2063  ****************************************************************************/
2064 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
2065                         int access_type)
2066 {
2067         struct spoolss_security_descriptor *secdesc = NULL;
2068         uint32 access_granted;
2069         size_t sd_size;
2070         NTSTATUS status;
2071         WERROR result;
2072         const char *pname;
2073         TALLOC_CTX *mem_ctx = NULL;
2074         SE_PRIV se_printop = SE_PRINT_OPERATOR;
2075
2076         /* If user is NULL then use the current_user structure */
2077
2078         /* Always allow root or SE_PRINT_OPERATROR to do anything */
2079
2080         if (server_info->utok.uid == sec_initial_uid()
2081             || user_has_privileges(server_info->ptok, &se_printop ) ) {
2082                 return True;
2083         }
2084
2085         /* Get printer name */
2086
2087         pname = lp_printername(snum);
2088
2089         if (!pname || !*pname) {
2090                 errno = EACCES;
2091                 return False;
2092         }
2093
2094         /* Get printer security descriptor */
2095
2096         if(!(mem_ctx = talloc_init("print_access_check"))) {
2097                 errno = ENOMEM;
2098                 return False;
2099         }
2100
2101         result = winreg_get_printer_secdesc(mem_ctx,
2102                                             server_info,
2103                                             smbd_messaging_context(),
2104                                             pname,
2105                                             &secdesc);
2106         if (!W_ERROR_IS_OK(result)) {
2107                 talloc_destroy(mem_ctx);
2108                 errno = ENOMEM;
2109                 return False;
2110         }
2111
2112         if (access_type == JOB_ACCESS_ADMINISTER) {
2113                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
2114
2115                 /* Create a child security descriptor to check permissions
2116                    against.  This is because print jobs are child objects
2117                    objects of a printer. */
2118                 status = se_create_child_secdesc(mem_ctx,
2119                                                  &secdesc,
2120                                                  &sd_size,
2121                                                  parent_secdesc,
2122                                                  parent_secdesc->owner_sid,
2123                                                  parent_secdesc->group_sid,
2124                                                  false);
2125                 if (!NT_STATUS_IS_OK(status)) {
2126                         talloc_destroy(mem_ctx);
2127                         errno = map_errno_from_nt_status(status);
2128                         return False;
2129                 }
2130
2131                 map_job_permissions(secdesc);
2132         } else {
2133                 map_printer_permissions(secdesc);
2134         }
2135
2136         /* Check access */
2137         status = se_access_check(secdesc, server_info->ptok, access_type,
2138                                  &access_granted);
2139
2140         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
2141
2142         /* see if we need to try the printer admin list */
2143
2144         if (!NT_STATUS_IS_OK(status) &&
2145             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
2146                                          server_info->info3->base.domain.string,
2147                                          NULL, server_info->ptok,
2148                                          lp_printer_admin(snum)))) {
2149                 talloc_destroy(mem_ctx);
2150                 return True;
2151         }
2152
2153         talloc_destroy(mem_ctx);
2154
2155         if (!NT_STATUS_IS_OK(status)) {
2156                 errno = EACCES;
2157         }
2158
2159         return NT_STATUS_IS_OK(status);
2160 }
2161
2162 /****************************************************************************
2163  Check the time parameters allow a print operation.
2164 *****************************************************************************/
2165
2166 bool print_time_access_check(struct auth_serversupplied_info *server_info,
2167                              const char *servicename)
2168 {
2169         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2170         WERROR result;
2171         bool ok = False;
2172         time_t now = time(NULL);
2173         struct tm *t;
2174         uint32 mins;
2175
2176         result = winreg_get_printer(NULL, server_info,
2177                                     smbd_messaging_context(),
2178                                     NULL, servicename, &pinfo2);
2179         if (!W_ERROR_IS_OK(result)) {
2180                 return False;
2181         }
2182
2183         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
2184                 ok = True;
2185         }
2186
2187         t = gmtime(&now);
2188         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2189
2190         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
2191                 ok = True;
2192         }
2193
2194         TALLOC_FREE(pinfo2);
2195
2196         if (!ok) {
2197                 errno = EACCES;
2198         }
2199
2200         return ok;
2201 }
2202
2203 void nt_printer_remove(TALLOC_CTX *mem_ctx,
2204                         struct auth_serversupplied_info *server_info,
2205                         const char *printer)
2206 {
2207         WERROR result;
2208
2209         result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
2210         if (!W_ERROR_IS_OK(result)) {
2211                 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",
2212                           printer));
2213         }
2214 }