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