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