s3-printing: Removed unused free_a_printer function.
[ira/wip.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 "registry.h"
26 #include "registry/reg_objects.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "rpc_server/srv_spoolss_util.h"
29
30 #include "../rpc_server/srv_spoolss_util.h"
31
32 static TDB_CONTEXT *tdb_forms; /* used for forms files */
33 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
34 static TDB_CONTEXT *tdb_printers; /* used for printers files */
35
36 #define FORMS_PREFIX "FORMS/"
37 #define DRIVERS_PREFIX "DRIVERS/"
38 #define PRINTERS_PREFIX "PRINTERS/"
39 #define SECDESC_PREFIX "SECDESC/"
40 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
41
42 #define NTDRIVERS_DATABASE_VERSION_1 1
43 #define NTDRIVERS_DATABASE_VERSION_2 2
44 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
45 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
46 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
47
48 /* Map generic permissions to printer object specific permissions */
49
50 const struct generic_mapping printer_generic_mapping = {
51         PRINTER_READ,
52         PRINTER_WRITE,
53         PRINTER_EXECUTE,
54         PRINTER_ALL_ACCESS
55 };
56
57 const struct standard_mapping printer_std_mapping = {
58         PRINTER_READ,
59         PRINTER_WRITE,
60         PRINTER_EXECUTE,
61         PRINTER_ALL_ACCESS
62 };
63
64 /* Map generic permissions to print server object specific permissions */
65
66 const struct generic_mapping printserver_generic_mapping = {
67         SERVER_READ,
68         SERVER_WRITE,
69         SERVER_EXECUTE,
70         SERVER_ALL_ACCESS
71 };
72
73 const struct generic_mapping printserver_std_mapping = {
74         SERVER_READ,
75         SERVER_WRITE,
76         SERVER_EXECUTE,
77         SERVER_ALL_ACCESS
78 };
79
80 /* Map generic permissions to job object specific permissions */
81
82 const struct generic_mapping job_generic_mapping = {
83         JOB_READ,
84         JOB_WRITE,
85         JOB_EXECUTE,
86         JOB_ALL_ACCESS
87 };
88
89 /* We need one default form to support our default printer. Msoft adds the
90 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
91 array index). Letter is always first, so (for the current code) additions
92 always put things in the correct order. */
93 static const nt_forms_struct default_forms[] = {
94         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
95         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
96         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
98         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
99         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
100         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
101         {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
102         {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
103         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
104         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
105         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
106         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
107         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
108         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
109         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
110         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
111         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
112         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
113         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
114         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
115         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
116         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
117         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
118         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
119         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
120         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
121         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
122         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
123         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
124         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
125         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
126         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
127         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
128         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
129         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
130         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
131         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
132         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
133         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
134         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
135         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
136         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
137         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
138         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
139         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
140         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
141         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
142         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
143         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
144         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
145         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
146         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
147         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
148         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
149         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
150         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
151         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
152         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
153         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
154         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
155         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
156         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
157         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
158         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
159         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
160         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
161         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
162         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
163         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
164         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
165         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
166         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
167         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
168         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
169         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
170         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
171         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
172         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
173         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
174         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
175         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
176         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
177         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
178         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
179         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
180         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
181         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
182         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
183         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
184         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
185         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
186         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
187         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
188         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
189         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
190         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
191         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
192         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
193         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
194         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
195         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
196         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
197         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
198         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
199         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
200         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
201         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
202         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
203         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
204         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
205         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
206         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
207         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
208         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
209         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
210         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
211         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
212         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
213         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
214 };
215
216 static const struct print_architecture_table_node archi_table[]= {
217
218         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
219         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
220         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
221         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
222         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
223         {"Windows IA64",         SPL_ARCH_IA64,         3 },
224         {"Windows x64",          SPL_ARCH_X64,          3 },
225         {NULL,                   "",            -1 }
226 };
227
228
229 /****************************************************************************
230  generate a new TDB_DATA key for storing a printer
231 ****************************************************************************/
232
233 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
234 {
235         fstring share;
236         char *keystr = NULL;
237         TDB_DATA key;
238
239         fstrcpy(share, sharename);
240         strlower_m(share);
241
242         keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
243         key = string_term_tdb_data(keystr ? keystr : "");
244
245         return key;
246 }
247
248 /****************************************************************************
249  generate a new TDB_DATA key for storing a printer security descriptor
250 ****************************************************************************/
251
252 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
253                                         const char* sharename  )
254 {
255         fstring share;
256         char *keystr = NULL;
257         TDB_DATA key;
258
259         fstrcpy(share, sharename );
260         strlower_m(share);
261
262         keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
263         key = string_term_tdb_data(keystr ? keystr : "");
264
265         return key;
266 }
267
268 /****************************************************************************
269 ****************************************************************************/
270
271 static bool upgrade_to_version_3(void)
272 {
273         TDB_DATA kbuf, newkey, dbuf;
274
275         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
276
277         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
278                         newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
279
280                 dbuf = tdb_fetch(tdb_drivers, kbuf);
281
282                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
283                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
284                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
285                                 SAFE_FREE(dbuf.dptr);
286                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
287                                 return False;
288                         }
289                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
290                                 SAFE_FREE(dbuf.dptr);
291                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
292                                 return False;
293                         }
294                 }
295
296                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
297                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
298                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
299                                 SAFE_FREE(dbuf.dptr);
300                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
301                                 return False;
302                         }
303                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
304                                 SAFE_FREE(dbuf.dptr);
305                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
306                                 return False;
307                         }
308                 }
309
310                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
311                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
312                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
313                                 SAFE_FREE(dbuf.dptr);
314                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
315                                 return False;
316                         }
317                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
318                                 SAFE_FREE(dbuf.dptr);
319                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
320                                 return False;
321                         }
322                 }
323
324                 SAFE_FREE(dbuf.dptr);
325         }
326
327         return True;
328 }
329
330 /*******************************************************************
331  Fix an issue with security descriptors.  Printer sec_desc must
332  use more than the generic bits that were previously used
333  in <= 3.0.14a.  They must also have a owner and group SID assigned.
334  Otherwise, any printers than have been migrated to a Windows
335  host using printmig.exe will not be accessible.
336 *******************************************************************/
337
338 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
339                             TDB_DATA data, void *state )
340 {
341         NTSTATUS status;
342         struct sec_desc_buf *sd_orig = NULL;
343         struct sec_desc_buf *sd_new, *sd_store;
344         struct security_descriptor *sec, *new_sec;
345         TALLOC_CTX *ctx = state;
346         int result, i;
347         uint32 sd_size;
348         size_t size_new_sec;
349
350         if (!data.dptr || data.dsize == 0) {
351                 return 0;
352         }
353
354         if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
355                 return 0;
356         }
357
358         /* upgrade the security descriptor */
359
360         status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
361         if (!NT_STATUS_IS_OK(status)) {
362                 /* delete bad entries */
363                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
364                         (const char *)key.dptr ));
365                 tdb_delete( tdb_printers, key );
366                 return 0;
367         }
368
369         if (!sd_orig) {
370                 return 0;
371         }
372         sec = sd_orig->sd;
373
374         /* is this even valid? */
375
376         if ( !sec->dacl ) {
377                 return 0;
378         }
379
380         /* update access masks */
381
382         for ( i=0; i<sec->dacl->num_aces; i++ ) {
383                 switch ( sec->dacl->aces[i].access_mask ) {
384                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
385                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
386                                 break;
387
388                         case GENERIC_ALL_ACCESS:
389                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
390                                 break;
391
392                         case READ_CONTROL_ACCESS:
393                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
394
395                         default:        /* no change */
396                                 break;
397                 }
398         }
399
400         /* create a new struct security_descriptor with the appropriate owner and group SIDs */
401
402         new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
403                                  &global_sid_Builtin_Administrators,
404                                  &global_sid_Builtin_Administrators,
405                                  NULL, NULL, &size_new_sec );
406         if (!new_sec) {
407                 return 0;
408         }
409         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
410         if (!sd_new) {
411                 return 0;
412         }
413
414         if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
415                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
416                 return 0;
417         }
418
419         /* store it back */
420
421         sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
422                 + sizeof(struct sec_desc_buf);
423
424         status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
425         if (!NT_STATUS_IS_OK(status)) {
426                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
427                 return 0;
428         }
429
430         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
431
432         /* 0 to continue and non-zero to stop traversal */
433
434         return (result == -1);
435 }
436
437 /*******************************************************************
438 *******************************************************************/
439
440 static bool upgrade_to_version_4(void)
441 {
442         TALLOC_CTX *ctx;
443         int result;
444
445         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
446
447         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
448                 return False;
449
450         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
451
452         talloc_destroy( ctx );
453
454         return ( result != -1 );
455 }
456
457 /*******************************************************************
458  Fix an issue with security descriptors.  Printer sec_desc must
459  use more than the generic bits that were previously used
460  in <= 3.0.14a.  They must also have a owner and group SID assigned.
461  Otherwise, any printers than have been migrated to a Windows
462  host using printmig.exe will not be accessible.
463 *******************************************************************/
464
465 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
466                                   TDB_DATA data, void *state )
467 {
468         TALLOC_CTX *ctx = talloc_tos();
469         TDB_DATA new_key;
470
471         if (!data.dptr || data.dsize == 0)
472                 return 0;
473
474         /* upgrade printer records and security descriptors */
475
476         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
477                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
478         }
479         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
480                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
481         }
482         else {
483                 /* ignore this record */
484                 return 0;
485         }
486
487         /* delete the original record and store under the normalized key */
488
489         if ( tdb_delete( the_tdb, key ) != 0 ) {
490                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
491                         key.dptr));
492                 return 1;
493         }
494
495         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
496                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
497                         key.dptr));
498                 return 1;
499         }
500
501         return 0;
502 }
503
504 /*******************************************************************
505 *******************************************************************/
506
507 static bool upgrade_to_version_5(void)
508 {
509         TALLOC_CTX *ctx;
510         int result;
511
512         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
513
514         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
515                 return False;
516
517         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
518
519         talloc_destroy( ctx );
520
521         return ( result != -1 );
522 }
523
524 /****************************************************************************
525  Open the NT printing tdbs. Done once before fork().
526 ****************************************************************************/
527
528 bool nt_printing_init(struct messaging_context *msg_ctx)
529 {
530         const char *vstring = "INFO/version";
531         WERROR win_rc;
532         int32 vers_id;
533
534         if ( tdb_drivers && tdb_printers && tdb_forms )
535                 return True;
536
537         if (tdb_drivers)
538                 tdb_close(tdb_drivers);
539         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
540         if (!tdb_drivers) {
541                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
542                         state_path("ntdrivers.tdb"), strerror(errno) ));
543                 return False;
544         }
545
546         if (tdb_printers)
547                 tdb_close(tdb_printers);
548         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
549         if (!tdb_printers) {
550                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
551                         state_path("ntprinters.tdb"), strerror(errno) ));
552                 return False;
553         }
554
555         if (tdb_forms)
556                 tdb_close(tdb_forms);
557         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
558         if (!tdb_forms) {
559                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
560                         state_path("ntforms.tdb"), strerror(errno) ));
561                 return False;
562         }
563
564         /* handle a Samba upgrade */
565
566         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
567         if (vers_id == -1) {
568                 DEBUG(10, ("Fresh database\n"));
569                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
570                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
571         }
572
573         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
574
575                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
576                         if (!upgrade_to_version_3())
577                                 return False;
578                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
580                 }
581
582                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
583                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
584                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
585                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
586                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
587                 }
588
589                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
590                         if ( !upgrade_to_version_4() )
591                                 return False;
592                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
593                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
594                 }
595
596                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
597                         if ( !upgrade_to_version_5() )
598                                 return False;
599                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
600                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
601                 }
602
603
604                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
605                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
606                         return False;
607                 }
608         }
609
610         /*
611          * register callback to handle updating printers as new
612          * drivers are installed
613          */
614
615         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
616                            do_drv_upgrade_printer);
617
618         /* of course, none of the message callbacks matter if you don't
619            tell messages.c that you interested in receiving PRINT_GENERAL
620            msgs.  This is done in serverid_register() */
621
622
623         if ( lp_security() == SEC_ADS ) {
624                 win_rc = check_published_printers();
625                 if (!W_ERROR_IS_OK(win_rc))
626                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
627         }
628
629         return True;
630 }
631
632 /*******************************************************************
633  Function to allow filename parsing "the old way".
634 ********************************************************************/
635
636 static NTSTATUS driver_unix_convert(connection_struct *conn,
637                                     const char *old_name,
638                                     struct smb_filename **smb_fname)
639 {
640         NTSTATUS status;
641         TALLOC_CTX *ctx = talloc_tos();
642         char *name = talloc_strdup(ctx, old_name);
643
644         if (!name) {
645                 return NT_STATUS_NO_MEMORY;
646         }
647         unix_format(name);
648         name = unix_clean_name(ctx, name);
649         if (!name) {
650                 return NT_STATUS_NO_MEMORY;
651         }
652         trim_string(name,"/","/");
653
654         status = unix_convert(ctx, conn, name, smb_fname, 0);
655         if (!NT_STATUS_IS_OK(status)) {
656                 return NT_STATUS_NO_MEMORY;
657         }
658
659         return NT_STATUS_OK;
660 }
661
662 /*******************************************************************
663  tdb traversal function for counting printers.
664 ********************************************************************/
665
666 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
667                                       TDB_DATA data, void *context)
668 {
669         int *printer_count = (int*)context;
670
671         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
672                 (*printer_count)++;
673                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
674         }
675
676         return 0;
677 }
678
679 /*******************************************************************
680  Update the spooler global c_setprinter. This variable is initialized
681  when the parent smbd starts with the number of existing printers. It
682  is monotonically increased by the current number of printers *after*
683  each add or delete printer RPC. Only Microsoft knows why... JRR020119
684 ********************************************************************/
685
686 uint32 update_c_setprinter(bool initialize)
687 {
688         int32 c_setprinter;
689         int32 printer_count = 0;
690
691         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
692
693         /* Traverse the tdb, counting the printers */
694         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
695
696         /* If initializing, set c_setprinter to current printers count
697          * otherwise, bump it by the current printer count
698          */
699         if (!initialize)
700                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
701         else
702                 c_setprinter = printer_count;
703
704         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
705         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
706
707         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
708
709         return (uint32)c_setprinter;
710 }
711
712 /*******************************************************************
713  Get the spooler global c_setprinter, accounting for initialization.
714 ********************************************************************/
715
716 uint32 get_c_setprinter(void)
717 {
718         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
719
720         if (c_setprinter == (int32)-1)
721                 c_setprinter = update_c_setprinter(True);
722
723         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
724
725         return (uint32)c_setprinter;
726 }
727
728 /****************************************************************************
729  Get builtin form struct list.
730 ****************************************************************************/
731
732 int get_builtin_ntforms(nt_forms_struct **list)
733 {
734         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
735         if (!*list) {
736                 return 0;
737         }
738         return ARRAY_SIZE(default_forms);
739 }
740
741 /****************************************************************************
742  get a builtin form struct
743 ****************************************************************************/
744
745 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
746 {
747         int i;
748         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
749         for (i=0; i<ARRAY_SIZE(default_forms); i++) {
750                 if (strequal(form_name,default_forms[i].name)) {
751                         DEBUGADD(6,("Found builtin form %s \n", form_name));
752                         memcpy(form,&default_forms[i],sizeof(*form));
753                         return true;
754                 }
755         }
756
757         return false;
758 }
759
760 /****************************************************************************
761  get a form struct list.
762 ****************************************************************************/
763
764 int get_ntforms(nt_forms_struct **list)
765 {
766         TDB_DATA kbuf, newkey, dbuf;
767         nt_forms_struct form;
768         int ret;
769         int i;
770         int n = 0;
771
772         *list = NULL;
773
774         for (kbuf = tdb_firstkey(tdb_forms);
775              kbuf.dptr;
776              newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
777         {
778                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
779                         continue;
780
781                 dbuf = tdb_fetch(tdb_forms, kbuf);
782                 if (!dbuf.dptr)
783                         continue;
784
785                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
786                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
787                                  &i, &form.flag, &form.width, &form.length, &form.left,
788                                  &form.top, &form.right, &form.bottom);
789                 SAFE_FREE(dbuf.dptr);
790                 if (ret != dbuf.dsize)
791                         continue;
792
793                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
794                 if (!*list) {
795                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
796                         return 0;
797                 }
798                 (*list)[n] = form;
799                 n++;
800         }
801
802
803         return n;
804 }
805
806 /****************************************************************************
807 write a form struct list
808 ****************************************************************************/
809
810 int write_ntforms(nt_forms_struct **list, int number)
811 {
812         TALLOC_CTX *ctx = talloc_tos();
813         char *buf = NULL;
814         char *key = NULL;
815         int len;
816         TDB_DATA dbuf;
817         int i;
818
819         for (i=0;i<number;i++) {
820                 /* save index, so list is rebuilt in correct order */
821                 len = tdb_pack(NULL, 0, "dddddddd",
822                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
823                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
824                                (*list)[i].bottom);
825                 if (!len) {
826                         continue;
827                 }
828                 buf = TALLOC_ARRAY(ctx, char, len);
829                 if (!buf) {
830                         return 0;
831                 }
832                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
833                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
834                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
835                                (*list)[i].bottom);
836                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
837                 if (!key) {
838                         return 0;
839                 }
840                 dbuf.dsize = len;
841                 dbuf.dptr = (uint8 *)buf;
842                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
843                         TALLOC_FREE(key);
844                         TALLOC_FREE(buf);
845                         break;
846                 }
847                 TALLOC_FREE(key);
848                 TALLOC_FREE(buf);
849        }
850
851        return i;
852 }
853
854 /****************************************************************************
855 add a form struct at the end of the list
856 ****************************************************************************/
857 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
858 {
859         int n=0;
860         bool update;
861
862         /*
863          * NT tries to add forms even when
864          * they are already in the base
865          * only update the values if already present
866          */
867
868         update=False;
869
870         for (n=0; n<*count; n++) {
871                 if ( strequal((*list)[n].name, form->form_name) ) {
872                         update=True;
873                         break;
874                 }
875         }
876
877         if (update==False) {
878                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
879                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
880                         return False;
881                 }
882                 fstrcpy((*list)[n].name, form->form_name);
883                 (*count)++;
884         }
885
886         (*list)[n].flag         = form->flags;
887         (*list)[n].width        = form->size.width;
888         (*list)[n].length       = form->size.height;
889         (*list)[n].left         = form->area.left;
890         (*list)[n].top          = form->area.top;
891         (*list)[n].right        = form->area.right;
892         (*list)[n].bottom       = form->area.bottom;
893
894         DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
895                 update ? "updated" : "added", form->form_name));
896
897         return True;
898 }
899
900 /****************************************************************************
901  Delete a named form struct.
902 ****************************************************************************/
903
904 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
905 {
906         char *key = NULL;
907         int n=0;
908
909         *ret = WERR_OK;
910
911         for (n=0; n<*count; n++) {
912                 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
913                         DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
914                         break;
915                 }
916         }
917
918         if (n == *count) {
919                 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
920                 *ret = WERR_INVALID_FORM_NAME;
921                 return False;
922         }
923
924         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
925                 *ret = WERR_NOMEM;
926                 return false;
927         }
928         if (tdb_delete_bystring(tdb_forms, key) != 0) {
929                 SAFE_FREE(key);
930                 *ret = WERR_NOMEM;
931                 return False;
932         }
933         SAFE_FREE(key);
934         return true;
935 }
936
937 /****************************************************************************
938  Update a form struct.
939 ****************************************************************************/
940
941 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
942 {
943         int n=0;
944
945         DEBUG(106, ("[%s]\n", form->form_name));
946         for (n=0; n<count; n++) {
947                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
948                 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
949                         break;
950         }
951
952         if (n==count) return;
953
954         (*list)[n].flag         = form->flags;
955         (*list)[n].width        = form->size.width;
956         (*list)[n].length       = form->size.height;
957         (*list)[n].left         = form->area.left;
958         (*list)[n].top          = form->area.top;
959         (*list)[n].right        = form->area.right;
960         (*list)[n].bottom       = form->area.bottom;
961 }
962
963 /****************************************************************************
964  Function to do the mapping between the long architecture name and
965  the short one.
966 ****************************************************************************/
967
968 const char *get_short_archi(const char *long_archi)
969 {
970         int i=-1;
971
972         DEBUG(107,("Getting architecture dependant directory\n"));
973         do {
974                 i++;
975         } while ( (archi_table[i].long_archi!=NULL ) &&
976                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
977
978         if (archi_table[i].long_archi==NULL) {
979                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
980                 return NULL;
981         }
982
983         /* this might be client code - but shouldn't this be an fstrcpy etc? */
984
985         DEBUGADD(108,("index: [%d]\n", i));
986         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
987         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
988
989         return archi_table[i].short_archi;
990 }
991
992 /****************************************************************************
993  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
994  There are two case to be covered here: PE (Portable Executable) and NE (New
995  Executable) files. Both files support the same INFO structure, but PE files
996  store the signature in unicode, and NE files store it as !unicode.
997  returns -1 on error, 1 on version info found, and 0 on no version info found.
998 ****************************************************************************/
999
1000 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1001 {
1002         int     i;
1003         char    *buf = NULL;
1004         ssize_t byte_count;
1005
1006         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1007                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1008                                 fname, DOS_HEADER_SIZE));
1009                 goto error_exit;
1010         }
1011
1012         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1013                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1014                          fname, (unsigned long)byte_count));
1015                 goto no_version_info;
1016         }
1017
1018         /* Is this really a DOS header? */
1019         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1020                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1021                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1022                 goto no_version_info;
1023         }
1024
1025         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1026         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1027                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1028                                 fname, errno));
1029                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1030                 goto no_version_info;
1031         }
1032
1033         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1034         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1035                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1036                          fname, (unsigned long)byte_count));
1037                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1038                 goto no_version_info;
1039         }
1040
1041         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1042         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1043                 unsigned int num_sections;
1044                 unsigned int section_table_bytes;
1045
1046                 /* Just skip over optional header to get to section table */
1047                 if (SMB_VFS_LSEEK(fsp,
1048                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1049                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1050                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1051                                 fname, errno));
1052                         goto error_exit;
1053                 }
1054
1055                 /* get the section table */
1056                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1057                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1058                 if (section_table_bytes == 0)
1059                         goto error_exit;
1060
1061                 SAFE_FREE(buf);
1062                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1063                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1064                                         fname, section_table_bytes));
1065                         goto error_exit;
1066                 }
1067
1068                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1069                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1070                                  fname, (unsigned long)byte_count));
1071                         goto error_exit;
1072                 }
1073
1074                 /* Iterate the section table looking for the resource section ".rsrc" */
1075                 for (i = 0; i < num_sections; i++) {
1076                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1077
1078                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1079                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1080                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1081
1082                                 if (section_bytes == 0)
1083                                         goto error_exit;
1084
1085                                 SAFE_FREE(buf);
1086                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1087                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1088                                                         fname, section_bytes));
1089                                         goto error_exit;
1090                                 }
1091
1092                                 /* Seek to the start of the .rsrc section info */
1093                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1094                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1095                                                         fname, errno));
1096                                         goto error_exit;
1097                                 }
1098
1099                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1100                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1101                                                  fname, (unsigned long)byte_count));
1102                                         goto error_exit;
1103                                 }
1104
1105                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1106                                         goto error_exit;
1107
1108                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1109                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1110                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1111                                                 /* Align to next long address */
1112                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1113
1114                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1115                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1116                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1117
1118                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1119                                                                           fname, *major, *minor,
1120                                                                           (*major>>16)&0xffff, *major&0xffff,
1121                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1122                                                         SAFE_FREE(buf);
1123                                                         return 1;
1124                                                 }
1125                                         }
1126                                 }
1127                         }
1128                 }
1129
1130                 /* Version info not found, fall back to origin date/time */
1131                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1132                 SAFE_FREE(buf);
1133                 return 0;
1134
1135         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1136                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1137                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1138                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1139                         /* At this point, we assume the file is in error. It still could be somthing
1140                          * else besides a NE file, but it unlikely at this point. */
1141                         goto error_exit;
1142                 }
1143
1144                 /* Allocate a bit more space to speed up things */
1145                 SAFE_FREE(buf);
1146                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1147                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1148                                         fname, PE_HEADER_SIZE));
1149                         goto error_exit;
1150                 }
1151
1152                 /* This is a HACK! I got tired of trying to sort through the messy
1153                  * 'NE' file format. If anyone wants to clean this up please have at
1154                  * it, but this works. 'NE' files will eventually fade away. JRR */
1155                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1156                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1157                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1158
1159                         for(i=0; i<byte_count; i++) {
1160                                 /* Fast skip past data that can't possibly match */
1161                                 if (buf[i] != 'V') continue;
1162
1163                                 /* Potential match data crosses buf boundry, move it to beginning
1164                                  * of buf, and fill the buf with as much as it will hold. */
1165                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1166                                         int bc;
1167
1168                                         memcpy(buf, &buf[i], byte_count-i);
1169                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1170                                                                    (byte_count-i))) < 0) {
1171
1172                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1173                                                                  fname, errno));
1174                                                 goto error_exit;
1175                                         }
1176
1177                                         byte_count = bc + (byte_count - i);
1178                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1179
1180                                         i = 0;
1181                                 }
1182
1183                                 /* Check that the full signature string and the magic number that
1184                                  * follows exist (not a perfect solution, but the chances that this
1185                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1186                                  * twice, as it is simpler to read the code. */
1187                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1188                                         /* Compute skip alignment to next long address */
1189                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1190                                                                  sizeof(VS_SIGNATURE)) & 3;
1191                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1192
1193                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1194                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1195                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1196                                                           fname, *major, *minor,
1197                                                           (*major>>16)&0xffff, *major&0xffff,
1198                                                           (*minor>>16)&0xffff, *minor&0xffff));
1199                                         SAFE_FREE(buf);
1200                                         return 1;
1201                                 }
1202                         }
1203                 }
1204
1205                 /* Version info not found, fall back to origin date/time */
1206                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1207                 SAFE_FREE(buf);
1208                 return 0;
1209
1210         } else
1211                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1212                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1213                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1214
1215         no_version_info:
1216                 SAFE_FREE(buf);
1217                 return 0;
1218
1219         error_exit:
1220                 SAFE_FREE(buf);
1221                 return -1;
1222 }
1223
1224 /****************************************************************************
1225 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1226 share one or more files. During the MS installation process files are checked
1227 to insure that only a newer version of a shared file is installed over an
1228 older version. There are several possibilities for this comparison. If there
1229 is no previous version, the new one is newer (obviously). If either file is
1230 missing the version info structure, compare the creation date (on Unix use
1231 the modification date). Otherwise chose the numerically larger version number.
1232 ****************************************************************************/
1233
1234 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1235 {
1236         bool use_version = true;
1237
1238         uint32 new_major;
1239         uint32 new_minor;
1240         time_t new_create_time;
1241
1242         uint32 old_major;
1243         uint32 old_minor;
1244         time_t old_create_time;
1245
1246         struct smb_filename *smb_fname = NULL;
1247         files_struct    *fsp = NULL;
1248         SMB_STRUCT_STAT st;
1249
1250         NTSTATUS status;
1251         int ret;
1252
1253         SET_STAT_INVALID(st);
1254         new_create_time = (time_t)0;
1255         old_create_time = (time_t)0;
1256
1257         /* Get file version info (if available) for previous file (if it exists) */
1258         status = driver_unix_convert(conn, old_file, &smb_fname);
1259         if (!NT_STATUS_IS_OK(status)) {
1260                 goto error_exit;
1261         }
1262
1263         status = SMB_VFS_CREATE_FILE(
1264                 conn,                                   /* conn */
1265                 NULL,                                   /* req */
1266                 0,                                      /* root_dir_fid */
1267                 smb_fname,                              /* fname */
1268                 FILE_GENERIC_READ,                      /* access_mask */
1269                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1270                 FILE_OPEN,                              /* create_disposition*/
1271                 0,                                      /* create_options */
1272                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1273                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1274                 0,                                      /* allocation_size */
1275                 0,                                      /* private_flags */
1276                 NULL,                                   /* sd */
1277                 NULL,                                   /* ea_list */
1278                 &fsp,                                   /* result */
1279                 NULL);                                  /* pinfo */
1280
1281         if (!NT_STATUS_IS_OK(status)) {
1282                 /* Old file not found, so by definition new file is in fact newer */
1283                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1284                           "errno = %d\n", smb_fname_str_dbg(smb_fname),
1285                           errno));
1286                 ret = 1;
1287                 goto done;
1288
1289         } else {
1290                 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1291                 if (ret == -1) {
1292                         goto error_exit;
1293                 }
1294
1295                 if (!ret) {
1296                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1297                                          old_file));
1298                         use_version = false;
1299                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1300                                  goto error_exit;
1301                         }
1302                         old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1303                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1304                                 (long)old_create_time));
1305                 }
1306         }
1307         close_file(NULL, fsp, NORMAL_CLOSE);
1308         fsp = NULL;
1309
1310         /* Get file version info (if available) for new file */
1311         status = driver_unix_convert(conn, new_file, &smb_fname);
1312         if (!NT_STATUS_IS_OK(status)) {
1313                 goto error_exit;
1314         }
1315
1316         status = SMB_VFS_CREATE_FILE(
1317                 conn,                                   /* conn */
1318                 NULL,                                   /* req */
1319                 0,                                      /* root_dir_fid */
1320                 smb_fname,                              /* fname */
1321                 FILE_GENERIC_READ,                      /* access_mask */
1322                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1323                 FILE_OPEN,                              /* create_disposition*/
1324                 0,                                      /* create_options */
1325                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1326                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1327                 0,                                      /* allocation_size */
1328                 0,                                      /* private_flags */
1329                 NULL,                                   /* sd */
1330                 NULL,                                   /* ea_list */
1331                 &fsp,                                   /* result */
1332                 NULL);                                  /* pinfo */
1333
1334         if (!NT_STATUS_IS_OK(status)) {
1335                 /* New file not found, this shouldn't occur if the caller did its job */
1336                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1337                          "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1338                 goto error_exit;
1339
1340         } else {
1341                 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1342                 if (ret == -1) {
1343                         goto error_exit;
1344                 }
1345
1346                 if (!ret) {
1347                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1348                                          new_file));
1349                         use_version = false;
1350                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1351                                 goto error_exit;
1352                         }
1353                         new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1354                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1355                                 (long)new_create_time));
1356                 }
1357         }
1358         close_file(NULL, fsp, NORMAL_CLOSE);
1359         fsp = NULL;
1360
1361         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1362                 /* Compare versions and choose the larger version number */
1363                 if (new_major > old_major ||
1364                         (new_major == old_major && new_minor > old_minor)) {
1365
1366                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1367                         ret = 1;
1368                         goto done;
1369                 }
1370                 else {
1371                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1372                         ret = 0;
1373                         goto done;
1374                 }
1375
1376         } else {
1377                 /* Compare modification time/dates and choose the newest time/date */
1378                 if (new_create_time > old_create_time) {
1379                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1380                         ret = 1;
1381                         goto done;
1382                 }
1383                 else {
1384                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1385                         ret = 0;
1386                         goto done;
1387                 }
1388         }
1389
1390  error_exit:
1391         if(fsp)
1392                 close_file(NULL, fsp, NORMAL_CLOSE);
1393         ret = -1;
1394  done:
1395         TALLOC_FREE(smb_fname);
1396         return ret;
1397 }
1398
1399 /****************************************************************************
1400 Determine the correct cVersion associated with an architecture and driver
1401 ****************************************************************************/
1402 static uint32 get_correct_cversion(struct pipes_struct *p,
1403                                    const char *architecture,
1404                                    const char *driverpath_in,
1405                                    WERROR *perr)
1406 {
1407         int               cversion;
1408         NTSTATUS          nt_status;
1409         struct smb_filename *smb_fname = NULL;
1410         char *driverpath = NULL;
1411         files_struct      *fsp = NULL;
1412         connection_struct *conn = NULL;
1413         NTSTATUS status;
1414         char *oldcwd;
1415         fstring printdollar;
1416         int printdollar_snum;
1417
1418         *perr = WERR_INVALID_PARAM;
1419
1420         /* If architecture is Windows 95/98/ME, the version is always 0. */
1421         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1422                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1423                 *perr = WERR_OK;
1424                 return 0;
1425         }
1426
1427         /* If architecture is Windows x64, the version is always 3. */
1428         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1429                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1430                 *perr = WERR_OK;
1431                 return 3;
1432         }
1433
1434         fstrcpy(printdollar, "print$");
1435
1436         printdollar_snum = find_service(printdollar);
1437         if (printdollar_snum == -1) {
1438                 *perr = WERR_NO_SUCH_SHARE;
1439                 return -1;
1440         }
1441
1442         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1443                                        lp_pathname(printdollar_snum),
1444                                        p->server_info, &oldcwd);
1445         if (!NT_STATUS_IS_OK(nt_status)) {
1446                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1447                          "returned %s\n", nt_errstr(nt_status)));
1448                 *perr = ntstatus_to_werror(nt_status);
1449                 return -1;
1450         }
1451
1452         /* Open the driver file (Portable Executable format) and determine the
1453          * deriver the cversion. */
1454         driverpath = talloc_asprintf(talloc_tos(),
1455                                         "%s/%s",
1456                                         architecture,
1457                                         driverpath_in);
1458         if (!driverpath) {
1459                 *perr = WERR_NOMEM;
1460                 goto error_exit;
1461         }
1462
1463         nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1464         if (!NT_STATUS_IS_OK(nt_status)) {
1465                 *perr = ntstatus_to_werror(nt_status);
1466                 goto error_exit;
1467         }
1468
1469         nt_status = vfs_file_exist(conn, smb_fname);
1470         if (!NT_STATUS_IS_OK(nt_status)) {
1471                 *perr = WERR_BADFILE;
1472                 goto error_exit;
1473         }
1474
1475         status = SMB_VFS_CREATE_FILE(
1476                 conn,                                   /* conn */
1477                 NULL,                                   /* req */
1478                 0,                                      /* root_dir_fid */
1479                 smb_fname,                              /* fname */
1480                 FILE_GENERIC_READ,                      /* access_mask */
1481                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1482                 FILE_OPEN,                              /* create_disposition*/
1483                 0,                                      /* create_options */
1484                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1485                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1486                 0,                                      /* private_flags */
1487                 0,                                      /* allocation_size */
1488                 NULL,                                   /* sd */
1489                 NULL,                                   /* ea_list */
1490                 &fsp,                                   /* result */
1491                 NULL);                                  /* pinfo */
1492
1493         if (!NT_STATUS_IS_OK(status)) {
1494                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1495                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
1496                 *perr = WERR_ACCESS_DENIED;
1497                 goto error_exit;
1498         } else {
1499                 uint32 major;
1500                 uint32 minor;
1501                 int    ret;
1502
1503                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1504                 if (ret == -1) goto error_exit;
1505
1506                 if (!ret) {
1507                         DEBUG(6,("get_correct_cversion: Version info not "
1508                                  "found [%s]\n",
1509                                  smb_fname_str_dbg(smb_fname)));
1510                         goto error_exit;
1511                 }
1512
1513                 /*
1514                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1515                  * for more details. Version in this case is not just the version of the
1516                  * file, but the version in the sense of kernal mode (2) vs. user mode
1517                  * (3) drivers. Other bits of the version fields are the version info.
1518                  * JRR 010716
1519                 */
1520                 cversion = major & 0x0000ffff;
1521                 switch (cversion) {
1522                         case 2: /* WinNT drivers */
1523                         case 3: /* Win2K drivers */
1524                                 break;
1525
1526                         default:
1527                                 DEBUG(6,("get_correct_cversion: cversion "
1528                                          "invalid [%s]  cversion = %d\n",
1529                                          smb_fname_str_dbg(smb_fname),
1530                                          cversion));
1531                                 goto error_exit;
1532                 }
1533
1534                 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1535                           " = 0x%x  minor = 0x%x\n",
1536                           smb_fname_str_dbg(smb_fname), major, minor));
1537         }
1538
1539         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1540                   smb_fname_str_dbg(smb_fname), cversion));
1541
1542         goto done;
1543
1544  error_exit:
1545         cversion = -1;
1546  done:
1547         TALLOC_FREE(smb_fname);
1548         if (fsp != NULL) {
1549                 close_file(NULL, fsp, NORMAL_CLOSE);
1550         }
1551         if (conn != NULL) {
1552                 vfs_ChDir(conn, oldcwd);
1553                 conn_free(conn);
1554         }
1555         if (cversion != -1) {
1556                 *perr = WERR_OK;
1557         }
1558         return cversion;
1559 }
1560
1561 /****************************************************************************
1562 ****************************************************************************/
1563
1564 #define strip_driver_path(_mem_ctx, _element) do { \
1565         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1566                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1567                 W_ERROR_HAVE_NO_MEMORY((_element)); \
1568         } \
1569 } while (0);
1570
1571 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1572                                            struct pipes_struct *rpc_pipe,
1573                                            const char *architecture,
1574                                            const char **driver_path,
1575                                            const char **data_file,
1576                                            const char **config_file,
1577                                            const char **help_file,
1578                                            struct spoolss_StringArray *dependent_files,
1579                                            uint32_t *version)
1580 {
1581         const char *short_architecture;
1582         int i;
1583         WERROR err;
1584         char *_p;
1585
1586         if (!*driver_path || !*data_file || !*config_file) {
1587                 return WERR_INVALID_PARAM;
1588         }
1589
1590         /* clean up the driver name.
1591          * we can get .\driver.dll
1592          * or worse c:\windows\system\driver.dll !
1593          */
1594         /* using an intermediate string to not have overlaping memcpy()'s */
1595
1596         strip_driver_path(mem_ctx, *driver_path);
1597         strip_driver_path(mem_ctx, *data_file);
1598         strip_driver_path(mem_ctx, *config_file);
1599         if (help_file) {
1600                 strip_driver_path(mem_ctx, *help_file);
1601         }
1602
1603         if (dependent_files && dependent_files->string) {
1604                 for (i=0; dependent_files->string[i]; i++) {
1605                         strip_driver_path(mem_ctx, dependent_files->string[i]);
1606                 }
1607         }
1608
1609         short_architecture = get_short_archi(architecture);
1610         if (!short_architecture) {
1611                 return WERR_UNKNOWN_PRINTER_DRIVER;
1612         }
1613
1614         /* jfm:7/16/2000 the client always sends the cversion=0.
1615          * The server should check which version the driver is by reading
1616          * the PE header of driver->driverpath.
1617          *
1618          * For Windows 95/98 the version is 0 (so the value sent is correct)
1619          * For Windows NT (the architecture doesn't matter)
1620          *      NT 3.1: cversion=0
1621          *      NT 3.5/3.51: cversion=1
1622          *      NT 4: cversion=2
1623          *      NT2K: cversion=3
1624          */
1625
1626         *version = get_correct_cversion(rpc_pipe, short_architecture,
1627                                         *driver_path, &err);
1628         if (*version == -1) {
1629                 return err;
1630         }
1631
1632         return WERR_OK;
1633 }
1634
1635 /****************************************************************************
1636 ****************************************************************************/
1637
1638 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1639                               struct pipes_struct *rpc_pipe,
1640                               struct spoolss_AddDriverInfoCtr *r)
1641 {
1642         switch (r->level) {
1643         case 3:
1644                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1645                                                     r->info.info3->architecture,
1646                                                     &r->info.info3->driver_path,
1647                                                     &r->info.info3->data_file,
1648                                                     &r->info.info3->config_file,
1649                                                     &r->info.info3->help_file,
1650                                                     r->info.info3->dependent_files,
1651                                                     &r->info.info3->version);
1652         case 6:
1653                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1654                                                     r->info.info6->architecture,
1655                                                     &r->info.info6->driver_path,
1656                                                     &r->info.info6->data_file,
1657                                                     &r->info.info6->config_file,
1658                                                     &r->info.info6->help_file,
1659                                                     r->info.info6->dependent_files,
1660                                                     &r->info.info6->version);
1661         default:
1662                 return WERR_NOT_SUPPORTED;
1663         }
1664 }
1665
1666 /****************************************************************************
1667  This function sucks and should be replaced. JRA.
1668 ****************************************************************************/
1669
1670 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1671                                       const struct spoolss_AddDriverInfo6 *src)
1672 {
1673         dst->version            = src->version;
1674
1675         dst->driver_name        = src->driver_name;
1676         dst->architecture       = src->architecture;
1677         dst->driver_path        = src->driver_path;
1678         dst->data_file          = src->data_file;
1679         dst->config_file        = src->config_file;
1680         dst->help_file          = src->help_file;
1681         dst->monitor_name       = src->monitor_name;
1682         dst->default_datatype   = src->default_datatype;
1683         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1684         dst->dependent_files    = src->dependent_files;
1685 }
1686
1687 /****************************************************************************
1688 ****************************************************************************/
1689
1690 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1691                                                 connection_struct *conn,
1692                                                 const char *driver_file,
1693                                                 const char *short_architecture,
1694                                                 uint32_t driver_version,
1695                                                 uint32_t version)
1696 {
1697         struct smb_filename *smb_fname_old = NULL;
1698         struct smb_filename *smb_fname_new = NULL;
1699         char *old_name = NULL;
1700         char *new_name = NULL;
1701         NTSTATUS status;
1702         WERROR ret;
1703
1704         old_name = talloc_asprintf(mem_ctx, "%s/%s",
1705                                    short_architecture, driver_file);
1706         W_ERROR_HAVE_NO_MEMORY(old_name);
1707
1708         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1709                                    short_architecture, driver_version, driver_file);
1710         if (new_name == NULL) {
1711                 TALLOC_FREE(old_name);
1712                 return WERR_NOMEM;
1713         }
1714
1715         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1716
1717                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1718                 if (!NT_STATUS_IS_OK(status)) {
1719                         ret = WERR_NOMEM;
1720                         goto out;
1721                 }
1722
1723                 /* Setup a synthetic smb_filename struct */
1724                 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1725                 if (!smb_fname_new) {
1726                         ret = WERR_NOMEM;
1727                         goto out;
1728                 }
1729
1730                 smb_fname_new->base_name = new_name;
1731
1732                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1733                           "'%s'\n", smb_fname_old->base_name,
1734                           smb_fname_new->base_name));
1735
1736                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1737                                    OPENX_FILE_EXISTS_TRUNCATE |
1738                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1739                                    0, false);
1740
1741                 if (!NT_STATUS_IS_OK(status)) {
1742                         DEBUG(0,("move_driver_file_to_download_area: Unable "
1743                                  "to rename [%s] to [%s]: %s\n",
1744                                  smb_fname_old->base_name, new_name,
1745                                  nt_errstr(status)));
1746                         ret = WERR_ACCESS_DENIED;
1747                         goto out;
1748                 }
1749         }
1750
1751         ret = WERR_OK;
1752  out:
1753         TALLOC_FREE(smb_fname_old);
1754         TALLOC_FREE(smb_fname_new);
1755         return ret;
1756 }
1757
1758 WERROR move_driver_to_download_area(struct pipes_struct *p,
1759                                     struct spoolss_AddDriverInfoCtr *r,
1760                                     WERROR *perr)
1761 {
1762         struct spoolss_AddDriverInfo3 *driver;
1763         struct spoolss_AddDriverInfo3 converted_driver;
1764         const char *short_architecture;
1765         struct smb_filename *smb_dname = NULL;
1766         char *new_dir = NULL;
1767         connection_struct *conn = NULL;
1768         NTSTATUS nt_status;
1769         int i;
1770         TALLOC_CTX *ctx = talloc_tos();
1771         int ver = 0;
1772         char *oldcwd;
1773         fstring printdollar;
1774         int printdollar_snum;
1775
1776         *perr = WERR_OK;
1777
1778         switch (r->level) {
1779         case 3:
1780                 driver = r->info.info3;
1781                 break;
1782         case 6:
1783                 convert_level_6_to_level3(&converted_driver, r->info.info6);
1784                 driver = &converted_driver;
1785                 break;
1786         default:
1787                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1788                 return WERR_UNKNOWN_LEVEL;
1789         }
1790
1791         short_architecture = get_short_archi(driver->architecture);
1792         if (!short_architecture) {
1793                 return WERR_UNKNOWN_PRINTER_DRIVER;
1794         }
1795
1796         fstrcpy(printdollar, "print$");
1797
1798         printdollar_snum = find_service(printdollar);
1799         if (printdollar_snum == -1) {
1800                 *perr = WERR_NO_SUCH_SHARE;
1801                 return WERR_NO_SUCH_SHARE;
1802         }
1803
1804         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1805                                        lp_pathname(printdollar_snum),
1806                                        p->server_info, &oldcwd);
1807         if (!NT_STATUS_IS_OK(nt_status)) {
1808                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1809                          "returned %s\n", nt_errstr(nt_status)));
1810                 *perr = ntstatus_to_werror(nt_status);
1811                 return *perr;
1812         }
1813
1814         new_dir = talloc_asprintf(ctx,
1815                                 "%s/%d",
1816                                 short_architecture,
1817                                 driver->version);
1818         if (!new_dir) {
1819                 *perr = WERR_NOMEM;
1820                 goto err_exit;
1821         }
1822         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1823         if (!NT_STATUS_IS_OK(nt_status)) {
1824                 *perr = WERR_NOMEM;
1825                 goto err_exit;
1826         }
1827
1828         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1829
1830         create_directory(conn, NULL, smb_dname);
1831
1832         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1833          * listed for this driver which has already been moved, skip it (note:
1834          * drivers may list the same file name several times. Then check if the
1835          * file already exists in archi\version\, if so, check that the version
1836          * info (or time stamps if version info is unavailable) is newer (or the
1837          * date is later). If it is, move it to archi\version\filexxx.yyy.
1838          * Otherwise, delete the file.
1839          *
1840          * If a file is not moved to archi\version\ because of an error, all the
1841          * rest of the 'unmoved' driver files are removed from archi\. If one or
1842          * more of the driver's files was already moved to archi\version\, it
1843          * potentially leaves the driver in a partially updated state. Version
1844          * trauma will most likely occur if an client attempts to use any printer
1845          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1846          * done is appropriate... later JRR
1847          */
1848
1849         DEBUG(5,("Moving files now !\n"));
1850
1851         if (driver->driver_path && strlen(driver->driver_path)) {
1852
1853                 *perr = move_driver_file_to_download_area(ctx,
1854                                                           conn,
1855                                                           driver->driver_path,
1856                                                           short_architecture,
1857                                                           driver->version,
1858                                                           ver);
1859                 if (!W_ERROR_IS_OK(*perr)) {
1860                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1861                                 ver = -1;
1862                         }
1863                         goto err_exit;
1864                 }
1865         }
1866
1867         if (driver->data_file && strlen(driver->data_file)) {
1868                 if (!strequal(driver->data_file, driver->driver_path)) {
1869
1870                         *perr = move_driver_file_to_download_area(ctx,
1871                                                                   conn,
1872                                                                   driver->data_file,
1873                                                                   short_architecture,
1874                                                                   driver->version,
1875                                                                   ver);
1876                         if (!W_ERROR_IS_OK(*perr)) {
1877                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1878                                         ver = -1;
1879                                 }
1880                                 goto err_exit;
1881                         }
1882                 }
1883         }
1884
1885         if (driver->config_file && strlen(driver->config_file)) {
1886                 if (!strequal(driver->config_file, driver->driver_path) &&
1887                     !strequal(driver->config_file, driver->data_file)) {
1888
1889                         *perr = move_driver_file_to_download_area(ctx,
1890                                                                   conn,
1891                                                                   driver->config_file,
1892                                                                   short_architecture,
1893                                                                   driver->version,
1894                                                                   ver);
1895                         if (!W_ERROR_IS_OK(*perr)) {
1896                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1897                                         ver = -1;
1898                                 }
1899                                 goto err_exit;
1900                         }
1901                 }
1902         }
1903
1904         if (driver->help_file && strlen(driver->help_file)) {
1905                 if (!strequal(driver->help_file, driver->driver_path) &&
1906                     !strequal(driver->help_file, driver->data_file) &&
1907                     !strequal(driver->help_file, driver->config_file)) {
1908
1909                         *perr = move_driver_file_to_download_area(ctx,
1910                                                                   conn,
1911                                                                   driver->help_file,
1912                                                                   short_architecture,
1913                                                                   driver->version,
1914                                                                   ver);
1915                         if (!W_ERROR_IS_OK(*perr)) {
1916                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1917                                         ver = -1;
1918                                 }
1919                                 goto err_exit;
1920                         }
1921                 }
1922         }
1923
1924         if (driver->dependent_files && driver->dependent_files->string) {
1925                 for (i=0; driver->dependent_files->string[i]; i++) {
1926                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1927                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
1928                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
1929                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
1930                                 int j;
1931                                 for (j=0; j < i; j++) {
1932                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1933                                                 goto NextDriver;
1934                                         }
1935                                 }
1936
1937                                 *perr = move_driver_file_to_download_area(ctx,
1938                                                                           conn,
1939                                                                           driver->dependent_files->string[i],
1940                                                                           short_architecture,
1941                                                                           driver->version,
1942                                                                           ver);
1943                                 if (!W_ERROR_IS_OK(*perr)) {
1944                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1945                                                 ver = -1;
1946                                         }
1947                                         goto err_exit;
1948                                 }
1949                         }
1950                 NextDriver: ;
1951                 }
1952         }
1953
1954   err_exit:
1955         TALLOC_FREE(smb_dname);
1956
1957         if (conn != NULL) {
1958                 vfs_ChDir(conn, oldcwd);
1959                 conn_free(conn);
1960         }
1961
1962         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1963                 return WERR_OK;
1964         }
1965         if (ver == -1) {
1966                 return WERR_UNKNOWN_PRINTER_DRIVER;
1967         }
1968         return (*perr);
1969 }
1970
1971 /****************************************************************************
1972 ****************************************************************************/
1973 int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
1974 {
1975         enum ndr_err_code ndr_err;
1976         DATA_BLOB blob;
1977         int len = 0;
1978
1979         if (devmode) {
1980                 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
1981                                                devmode,
1982                                                (ndr_push_flags_fn_t)
1983                                                ndr_push_spoolss_DeviceMode);
1984                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1985                         DEBUG(10, ("pack_devicemode: "
1986                                    "error encoding spoolss_DeviceMode\n"));
1987                         goto done;
1988                 }
1989         } else {
1990                 ZERO_STRUCT(blob);
1991         }
1992
1993         len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
1994
1995         if (devmode) {
1996                 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
1997         }
1998
1999 done:
2000         return len;
2001 }
2002
2003 /****************************************************************************
2004 ****************************************************************************/
2005 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2006                       const uint8 *buf, int buflen,
2007                       struct spoolss_DeviceMode **devmode)
2008 {
2009         struct spoolss_DeviceMode *dm;
2010         enum ndr_err_code ndr_err;
2011         char *data = NULL;
2012         int data_len = 0;
2013         DATA_BLOB blob;
2014         int len = 0;
2015
2016         *devmode = NULL;
2017
2018         len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2019         if (!data) {
2020                 return len;
2021         }
2022
2023         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2024         if (!dm) {
2025                 goto done;
2026         }
2027
2028         blob = data_blob_const(data, data_len);
2029
2030         ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2031                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2032         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2033                 DEBUG(10, ("unpack_devicemode: "
2034                            "error parsing spoolss_DeviceMode\n"));
2035                 goto done;
2036         }
2037
2038         DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2039                   dm->devicename, dm->formname));
2040         if (dm->driverextra_data.data) {
2041                 DEBUG(8, ("with a private section of %d bytes\n",
2042                           dm->__driverextra_length));
2043         }
2044
2045         *devmode = dm;
2046
2047 done:
2048         SAFE_FREE(data);
2049         return len;
2050 }
2051
2052 /****************************************************************************
2053  Create and allocate a default devicemode.
2054 ****************************************************************************/
2055
2056 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2057                                       const char *devicename,
2058                                       struct spoolss_DeviceMode **devmode)
2059 {
2060         struct spoolss_DeviceMode *dm;
2061         char *dname;
2062
2063         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2064         if (dm == NULL) {
2065                 return WERR_NOMEM;
2066         }
2067
2068         dname = talloc_asprintf(dm, "%s", devicename);
2069         if (dname == NULL) {
2070                 return WERR_NOMEM;
2071         }
2072         if (strlen(dname) > MAXDEVICENAME) {
2073                 dname[MAXDEVICENAME] = '\0';
2074         }
2075         dm->devicename = dname;
2076
2077         dm->formname = talloc_strdup(dm, "Letter");
2078         if (dm->formname == NULL) {
2079                 return WERR_NOMEM;
2080         }
2081
2082         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
2083         dm->driverversion        = 0x0400;
2084         dm->size                 = 0x00DC;
2085         dm->__driverextra_length = 0;
2086         dm->fields               = DEVMODE_FORMNAME |
2087                                    DEVMODE_TTOPTION |
2088                                    DEVMODE_PRINTQUALITY |
2089                                    DEVMODE_DEFAULTSOURCE |
2090                                    DEVMODE_COPIES |
2091                                    DEVMODE_SCALE |
2092                                    DEVMODE_PAPERSIZE |
2093                                    DEVMODE_ORIENTATION;
2094         dm->orientation          = DMORIENT_PORTRAIT;
2095         dm->papersize            = DMPAPER_LETTER;
2096         dm->paperlength          = 0;
2097         dm->paperwidth           = 0;
2098         dm->scale                = 0x64;
2099         dm->copies               = 1;
2100         dm->defaultsource        = DMBIN_FORMSOURCE;
2101         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
2102         dm->color                = DMRES_MONOCHROME;
2103         dm->duplex               = DMDUP_SIMPLEX;
2104         dm->yresolution          = 0;
2105         dm->ttoption             = DMTT_SUBDEV;
2106         dm->collate              = DMCOLLATE_FALSE;
2107         dm->icmmethod            = 0;
2108         dm->icmintent            = 0;
2109         dm->mediatype            = 0;
2110         dm->dithertype           = 0;
2111
2112         dm->logpixels            = 0;
2113         dm->bitsperpel           = 0;
2114         dm->pelswidth            = 0;
2115         dm->pelsheight           = 0;
2116         dm->displayflags         = 0;
2117         dm->displayfrequency     = 0;
2118         dm->reserved1            = 0;
2119         dm->reserved2            = 0;
2120         dm->panningwidth         = 0;
2121         dm->panningheight        = 0;
2122
2123         dm->driverextra_data.data = NULL;
2124         dm->driverextra_data.length = 0;
2125
2126         *devmode = dm;
2127         return WERR_OK;
2128 }
2129
2130 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2131                                       struct spoolss_security_descriptor **secdesc)
2132 {
2133         struct security_ace ace[7];     /* max number of ace entries */
2134         int i = 0;
2135         uint32_t sa;
2136         struct security_acl *psa = NULL;
2137         struct security_descriptor *psd = NULL;
2138         struct dom_sid adm_sid;
2139         size_t sd_size;
2140
2141         /* Create an ACE where Everyone is allowed to print */
2142
2143         sa = PRINTER_ACE_PRINT;
2144         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2145                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2146
2147         /* Add the domain admins group if we are a DC */
2148
2149         if ( IS_DC ) {
2150                 struct dom_sid domadmins_sid;
2151
2152                 sid_compose(&domadmins_sid, get_global_sam_sid(),
2153                             DOMAIN_RID_ADMINS);
2154
2155                 sa = PRINTER_ACE_FULL_CONTROL;
2156                 init_sec_ace(&ace[i++], &domadmins_sid,
2157                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2158                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2159                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2160                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2161         }
2162         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2163                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2164
2165                 sa = PRINTER_ACE_FULL_CONTROL;
2166                 init_sec_ace(&ace[i++], &adm_sid,
2167                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2168                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2169                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2170                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2171         }
2172
2173         /* add BUILTIN\Administrators as FULL CONTROL */
2174
2175         sa = PRINTER_ACE_FULL_CONTROL;
2176         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2177                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2178                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2179         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2180                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2181                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2182
2183         /* add BUILTIN\Print Operators as FULL CONTROL */
2184
2185         sa = PRINTER_ACE_FULL_CONTROL;
2186         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2187                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2188                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2189         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2190                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2191                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2192
2193         /* Make the security descriptor owned by the BUILTIN\Administrators */
2194
2195         /* The ACL revision number in rpc_secdesc.h differs from the one
2196            created by NT when setting ACE entries in printer
2197            descriptors.  NT4 complains about the property being edited by a
2198            NT5 machine. */
2199
2200         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2201                 psd = make_sec_desc(mem_ctx,
2202                                     SD_REVISION,
2203                                     SEC_DESC_SELF_RELATIVE,
2204                                     &global_sid_Builtin_Administrators,
2205                                     &global_sid_Builtin_Administrators,
2206                                     NULL,
2207                                     psa,
2208                                     &sd_size);
2209         }
2210
2211         if (psd == NULL) {
2212                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2213                 return WERR_NOMEM;
2214         }
2215
2216         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2217                  (unsigned int)sd_size));
2218
2219         *secdesc = psd;
2220
2221         return WERR_OK;
2222 }
2223
2224 /****************************************************************************
2225  Allocate and initialize a new slot.
2226 ***************************************************************************/
2227
2228 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2229 {
2230         NT_PRINTER_KEY  *d;
2231         int             key_index;
2232         WERROR werr;
2233
2234         if ( !name || !data )
2235                 return -1;
2236
2237         /* allocate another slot in the NT_PRINTER_KEY array */
2238
2239         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2240                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2241                 return -1;
2242         }
2243
2244         data->keys = d;
2245
2246         key_index = data->num_keys;
2247
2248         /* initialze new key */
2249
2250         data->keys[key_index].name = talloc_strdup( data, name );
2251
2252         werr = regval_ctr_init(data, &(data->keys[key_index].values));
2253         if (!W_ERROR_IS_OK(werr)) {
2254                 return -1;
2255         }
2256
2257         data->num_keys++;
2258
2259         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2260
2261         return key_index;
2262 }
2263
2264 /****************************************************************************
2265  search for a registry key name in the existing printer data
2266  ***************************************************************************/
2267
2268 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2269 {
2270         int i;
2271
2272         for ( i=0; i<data->num_keys; i++ ) {
2273                 if ( strequal( data->keys[i].name, name ) ) {
2274
2275                         /* cleanup memory */
2276
2277                         TALLOC_FREE( data->keys[i].name );
2278                         TALLOC_FREE( data->keys[i].values );
2279
2280                         /* if not the end of the array, move remaining elements down one slot */
2281
2282                         data->num_keys--;
2283                         if ( data->num_keys && (i < data->num_keys) )
2284                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2285
2286                         break;
2287                 }
2288         }
2289
2290
2291         return data->num_keys;
2292 }
2293
2294 /****************************************************************************
2295  search for a registry key name in the existing printer data
2296  ***************************************************************************/
2297
2298 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2299 {
2300         int             key_index = -1;
2301         int             i;
2302
2303         if ( !data || !name )
2304                 return -1;
2305
2306         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2307
2308         /* loop over all existing keys */
2309
2310         for ( i=0; i<data->num_keys; i++ ) {
2311                 if ( strequal(data->keys[i].name, name) ) {
2312                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2313                         key_index = i;
2314                         break;
2315
2316                 }
2317         }
2318
2319         return key_index;
2320 }
2321
2322 /****************************************************************************
2323  ***************************************************************************/
2324
2325 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2326 {
2327         int     i, j;
2328         int     key_len;
2329         int     num_subkeys = 0;
2330         char    *p;
2331         fstring *subkeys_ptr = NULL;
2332         fstring subkeyname;
2333
2334         *subkeys = NULL;
2335
2336         if ( !data )
2337                 return 0;
2338
2339         if ( !key )
2340                 return -1;
2341
2342         /* special case of asking for the top level printer data registry key names */
2343
2344         if ( strlen(key) == 0 ) {
2345                 for ( i=0; i<data->num_keys; i++ ) {
2346
2347                         /* found a match, so allocate space and copy the name */
2348
2349                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2350                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2351                                         num_subkeys+1));
2352                                 return -1;
2353                         }
2354
2355                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2356                         num_subkeys++;
2357                 }
2358
2359                 goto done;
2360         }
2361
2362         /* asking for the subkeys of some key */
2363         /* subkey paths are stored in the key name using '\' as the delimiter */
2364
2365         for ( i=0; i<data->num_keys; i++ ) {
2366                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2367
2368                         /* if we found the exact key, then break */
2369                         key_len = strlen( key );
2370                         if ( strlen(data->keys[i].name) == key_len )
2371                                 break;
2372
2373                         /* get subkey path */
2374
2375                         p = data->keys[i].name + key_len;
2376                         if ( *p == '\\' )
2377                                 p++;
2378                         fstrcpy( subkeyname, p );
2379                         if ( (p = strchr( subkeyname, '\\' )) )
2380                                 *p = '\0';
2381
2382                         /* don't add a key more than once */
2383
2384                         for ( j=0; j<num_subkeys; j++ ) {
2385                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
2386                                         break;
2387                         }
2388
2389                         if ( j != num_subkeys )
2390                                 continue;
2391
2392                         /* found a match, so allocate space and copy the name */
2393
2394                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2395                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2396                                         num_subkeys+1));
2397                                 return 0;
2398                         }
2399
2400                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2401                         num_subkeys++;
2402                 }
2403
2404         }
2405
2406         /* return error if the key was not found */
2407
2408         if ( i == data->num_keys ) {
2409                 SAFE_FREE(subkeys_ptr);
2410                 return -1;
2411         }
2412
2413 done:
2414         /* tag off the end */
2415
2416         if (num_subkeys)
2417                 fstrcpy(subkeys_ptr[num_subkeys], "" );
2418
2419         *subkeys = subkeys_ptr;
2420
2421         return num_subkeys;
2422 }
2423
2424 #ifdef HAVE_ADS
2425 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2426                             const char *sz)
2427 {
2428         regval_ctr_delvalue(ctr, val_name);
2429         regval_ctr_addvalue_sz(ctr, val_name, sz);
2430 }
2431
2432 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2433                                uint32 dword)
2434 {
2435         regval_ctr_delvalue(ctr, val_name);
2436         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2437                             (uint8 *) &dword, sizeof(dword));
2438 }
2439
2440 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2441                               bool b)
2442 {
2443         uint8 bin_bool = (b ? 1 : 0);
2444         regval_ctr_delvalue(ctr, val_name);
2445         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2446                             (uint8 *) &bin_bool, sizeof(bin_bool));
2447 }
2448
2449 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2450                                          const char *multi_sz)
2451 {
2452         const char *a[2];
2453
2454         a[0] = multi_sz;
2455         a[1] = NULL;
2456
2457         regval_ctr_delvalue(ctr, val_name);
2458         regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2459 }
2460
2461 /****************************************************************************
2462  * Map spoolss_PrinterInfo2 data into DsSpooler keys for publishing.
2463  *
2464  * @param mem_ctx  allocation context
2465  * @param info2    spoolss_PrinterInfo2 describing printer
2466  * @param pdata    the talloced printer data
2467  * @return bool    indicating success or failure
2468  ***************************************************************************/
2469
2470 static bool map_nt_printer_info2_to_dsspooler(TALLOC_CTX *mem_ctx,
2471                                               struct spoolss_PrinterInfo2 *info2,
2472                                               NT_PRINTER_DATA **pdata)
2473 {
2474         NT_PRINTER_DATA *data;
2475         struct regval_ctr *ctr = NULL;
2476         fstring longname;
2477         const char *dnssuffix;
2478         char *allocated_string = NULL;
2479         const char *ascii_str;
2480         int i;
2481
2482         data = talloc_zero(mem_ctx, NT_PRINTER_DATA);
2483         if (!data) return false;
2484
2485         /* init data */
2486         i = add_new_printer_key(data, SPOOL_DSSPOOLER_KEY);
2487         ctr = data->keys[i].values;
2488
2489         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2490         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2491
2492         /* we make the assumption that the netbios name is the same
2493            as the DNS name sinc ethe former will be what we used to
2494            join the domain */
2495
2496         dnssuffix = get_mydnsdomname(talloc_tos());
2497         if (dnssuffix && *dnssuffix) {
2498                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2499         } else {
2500                 fstrcpy( longname, global_myname() );
2501         }
2502
2503         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2504
2505         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
2506                 talloc_free(data);
2507                 return false;
2508         }
2509         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2510         SAFE_FREE(allocated_string);
2511
2512         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2513         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2514         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2515         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2516         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2517         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2518         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2519         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2520         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2521
2522         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2523                           (info2->attributes &
2524                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2525
2526         switch (info2->attributes & 0x3) {
2527         case 0:
2528                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2529                 break;
2530         case 1:
2531                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2532                 break;
2533         case 2:
2534                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2535                 break;
2536         default:
2537                 ascii_str = "unknown";
2538         }
2539         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2540
2541         *pdata = data;
2542         return true;
2543 }
2544
2545 /*****************************************************************
2546  ****************************************************************/
2547
2548 static void store_printer_guid(const char *printer, struct GUID guid)
2549 {
2550         TALLOC_CTX *tmp_ctx;
2551         struct auth_serversupplied_info *server_info = NULL;
2552         const char *guid_str;
2553         DATA_BLOB blob;
2554         NTSTATUS status;
2555         WERROR result;
2556
2557         tmp_ctx = talloc_new(NULL);
2558         if (!tmp_ctx) {
2559                 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2560                 return;
2561         }
2562
2563         status = make_server_info_system(tmp_ctx, &server_info);
2564         if (!NT_STATUS_IS_OK(status)) {
2565                 DEBUG(0, ("store_printer_guid: "
2566                           "Could not create system server_info\n"));
2567                 goto done;
2568         }
2569
2570         guid_str = GUID_string(tmp_ctx, &guid);
2571         if (!guid_str) {
2572                 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2573                 goto done;
2574         }
2575
2576         /* We used to store this as a REG_BINARY but that causes
2577            Vista to whine */
2578
2579         if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
2580                 DEBUG(0, ("store_printer_guid: "
2581                           "Could not marshall string %s for objectGUID\n",
2582                           guid_str));
2583                 goto done;
2584         }
2585
2586         result = winreg_set_printer_dataex(tmp_ctx, server_info, printer,
2587                                            SPOOL_DSSPOOLER_KEY, "objectGUID",
2588                                            REG_SZ, blob.data, blob.length);
2589         if (!W_ERROR_IS_OK(result)) {
2590                 DEBUG(0, ("store_printer_guid: "
2591                           "Failed to store GUID for printer %s\n", printer));
2592         }
2593
2594 done:
2595         talloc_free(tmp_ctx);
2596 }
2597
2598 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2599                                      struct spoolss_PrinterInfo2 *pinfo2)
2600 {
2601         ADS_STATUS ads_rc;
2602         LDAPMessage *res;
2603         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
2604         char *srv_dn_utf8, **srv_cn_utf8;
2605         TALLOC_CTX *ctx;
2606         ADS_MODLIST mods;
2607         const char *attrs[] = {"objectGUID", NULL};
2608         struct GUID guid;
2609         WERROR win_rc = WERR_OK;
2610         size_t converted_size;
2611         NT_PRINTER_DATA *pdata;
2612         const char *printer = pinfo2->sharename;
2613
2614         /* build the ads mods */
2615         ctx = talloc_init("nt_printer_publish_ads");
2616         if (ctx == NULL) {
2617                 return WERR_NOMEM;
2618         }
2619
2620         DEBUG(5, ("publishing printer %s\n", printer));
2621
2622         if (!map_nt_printer_info2_to_dsspooler(ctx, pinfo2, &pdata)) {
2623                 TALLOC_FREE(ctx);
2624                 return WERR_SERVER_UNAVAILABLE;
2625         }
2626
2627         /* figure out where to publish */
2628         ads_find_machine_acct(ads, &res, global_myname());
2629
2630         /* We use ldap_get_dn here as we need the answer
2631          * in utf8 to call ldap_explode_dn(). JRA. */
2632
2633         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2634         if (!srv_dn_utf8) {
2635                 TALLOC_FREE(ctx);
2636                 return WERR_SERVER_UNAVAILABLE;
2637         }
2638         ads_msgfree(ads, res);
2639         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2640         if (!srv_cn_utf8) {
2641                 TALLOC_FREE(ctx);
2642                 ldap_memfree(srv_dn_utf8);
2643                 return WERR_SERVER_UNAVAILABLE;
2644         }
2645         /* Now convert to CH_UNIX. */
2646         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
2647                 TALLOC_FREE(ctx);
2648                 ldap_memfree(srv_dn_utf8);
2649                 ldap_memfree(srv_cn_utf8);
2650                 return WERR_SERVER_UNAVAILABLE;
2651         }
2652         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
2653                 TALLOC_FREE(ctx);
2654                 ldap_memfree(srv_dn_utf8);
2655                 ldap_memfree(srv_cn_utf8);
2656                 TALLOC_FREE(srv_dn);
2657                 return WERR_SERVER_UNAVAILABLE;
2658         }
2659
2660         ldap_memfree(srv_dn_utf8);
2661         ldap_memfree(srv_cn_utf8);
2662
2663         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
2664         if (!srv_cn_escaped) {
2665                 TALLOC_FREE(ctx);
2666                 return WERR_SERVER_UNAVAILABLE;
2667         }
2668         sharename_escaped = escape_rdn_val_string_alloc(printer);
2669         if (!sharename_escaped) {
2670                 SAFE_FREE(srv_cn_escaped);
2671                 TALLOC_FREE(ctx);
2672                 return WERR_SERVER_UNAVAILABLE;
2673         }
2674
2675         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
2676
2677         SAFE_FREE(srv_cn_escaped);
2678         SAFE_FREE(sharename_escaped);
2679
2680         mods = ads_init_mods(ctx);
2681
2682         if (mods == NULL) {
2683                 SAFE_FREE(prt_dn);
2684                 TALLOC_FREE(ctx);
2685                 return WERR_NOMEM;
2686         }
2687
2688         get_local_printer_publishing_data(ctx, &mods, pdata);
2689         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
2690
2691         /* publish it */
2692         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2693         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
2694                 int i;
2695                 for (i=0; mods[i] != 0; i++)
2696                         ;
2697                 mods[i] = (LDAPMod *)-1;
2698                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2699         }
2700
2701         if (!ADS_ERR_OK(ads_rc)) {
2702                 DEBUG(3, ("error publishing %s: %s\n",
2703                           printer, ads_errstr(ads_rc)));
2704         }
2705
2706         /* retreive the guid and store it locally */
2707         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2708                 ZERO_STRUCT(guid);
2709                 ads_pull_guid(ads, res, &guid);
2710                 ads_msgfree(ads, res);
2711                 store_printer_guid(printer, guid);
2712         }
2713         TALLOC_FREE(ctx);
2714
2715         return win_rc;
2716 }
2717
2718 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2719                                        const char *printer)
2720 {
2721         ADS_STATUS ads_rc;
2722         LDAPMessage *res = NULL;
2723         char *prt_dn = NULL;
2724
2725         DEBUG(5, ("unpublishing printer %s\n", printer));
2726
2727         /* remove the printer from the directory */
2728         ads_rc = ads_find_printer_on_server(ads, &res,
2729                                             printer, global_myname());
2730
2731         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
2732                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2733                 if (!prt_dn) {
2734                         ads_msgfree(ads, res);
2735                         return WERR_NOMEM;
2736                 }
2737                 ads_rc = ads_del_dn(ads, prt_dn);
2738                 TALLOC_FREE(prt_dn);
2739         }
2740
2741         if (res) {
2742                 ads_msgfree(ads, res);
2743         }
2744         return WERR_OK;
2745 }
2746
2747 /****************************************************************************
2748  * Publish a printer in the directory
2749  *
2750  * @param mem_ctx      memory context
2751  * @param server_info  server_info to access winreg pipe
2752  * @param pinfo2       printer information
2753  * @param action       publish/unpublish action
2754  * @return WERROR indicating status of publishing
2755  ***************************************************************************/
2756
2757 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2758                           struct auth_serversupplied_info *server_info,
2759                           struct spoolss_PrinterInfo2 *pinfo2,
2760                           int action)
2761 {
2762         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
2763         struct spoolss_SetPrinterInfo2 *sinfo2;
2764         ADS_STATUS ads_rc;
2765         ADS_STRUCT *ads = NULL;
2766         WERROR win_rc;
2767
2768         sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
2769         if (!sinfo2) {
2770                 return WERR_NOMEM;
2771         }
2772
2773         switch (action) {
2774         case DSPRINT_PUBLISH:
2775         case DSPRINT_UPDATE:
2776                 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2777                 break;
2778         case DSPRINT_UNPUBLISH:
2779                 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2780                 break;
2781         default:
2782                 win_rc = WERR_NOT_SUPPORTED;
2783                 goto done;
2784         }
2785
2786         sinfo2->attributes = pinfo2->attributes;
2787
2788         win_rc = winreg_update_printer(mem_ctx, server_info,
2789                                         pinfo2->sharename, info2_mask,
2790                                         sinfo2, NULL, NULL);
2791         if (!W_ERROR_IS_OK(win_rc)) {
2792                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2793                 goto done;
2794         }
2795
2796         TALLOC_FREE(sinfo2);
2797
2798         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2799         if (!ads) {
2800                 DEBUG(3, ("ads_init() failed\n"));
2801                 win_rc = WERR_SERVER_UNAVAILABLE;
2802                 goto done;
2803         }
2804         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2805         SAFE_FREE(ads->auth.password);
2806         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2807                 NULL, NULL);
2808
2809         /* ads_connect() will find the DC for us */
2810         ads_rc = ads_connect(ads);
2811         if (!ADS_ERR_OK(ads_rc)) {
2812                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2813                 win_rc = WERR_ACCESS_DENIED;
2814                 goto done;
2815         }
2816
2817         switch (action) {
2818         case DSPRINT_PUBLISH:
2819         case DSPRINT_UPDATE:
2820                 win_rc = nt_printer_publish_ads(ads, pinfo2);
2821                 break;
2822         case DSPRINT_UNPUBLISH:
2823                 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
2824                 break;
2825         }
2826
2827 done:
2828         ads_destroy(&ads);
2829         return win_rc;
2830 }
2831
2832 WERROR check_published_printers(void)
2833 {
2834         ADS_STATUS ads_rc;
2835         ADS_STRUCT *ads = NULL;
2836         int snum;
2837         int n_services = lp_numservices();
2838         TALLOC_CTX *tmp_ctx = NULL;
2839         struct auth_serversupplied_info *server_info = NULL;
2840         struct spoolss_PrinterInfo2 *pinfo2;
2841         NTSTATUS status;
2842         WERROR result;
2843
2844         tmp_ctx = talloc_new(NULL);
2845         if (!tmp_ctx) return WERR_NOMEM;
2846
2847         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2848         if (!ads) {
2849                 DEBUG(3, ("ads_init() failed\n"));
2850                 return WERR_SERVER_UNAVAILABLE;
2851         }
2852         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2853         SAFE_FREE(ads->auth.password);
2854         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2855                 NULL, NULL);
2856
2857         /* ads_connect() will find the DC for us */
2858         ads_rc = ads_connect(ads);
2859         if (!ADS_ERR_OK(ads_rc)) {
2860                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2861                 result = WERR_ACCESS_DENIED;
2862                 goto done;
2863         }
2864
2865         status = make_server_info_system(tmp_ctx, &server_info);
2866         if (!NT_STATUS_IS_OK(status)) {
2867                 DEBUG(0, ("check_published_printers: "
2868                           "Could not create system server_info\n"));
2869                 result = WERR_ACCESS_DENIED;
2870                 goto done;
2871         }
2872
2873         for (snum = 0; snum < n_services; snum++) {
2874                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
2875                         continue;
2876                 }
2877
2878                 result = winreg_get_printer(tmp_ctx, server_info, NULL,
2879                                             lp_servicename(snum), &pinfo2);
2880                 if (!W_ERROR_IS_OK(result)) {
2881                         continue;
2882                 }
2883
2884                 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2885                         nt_printer_publish_ads(ads, pinfo2);
2886                 }
2887
2888                 TALLOC_FREE(pinfo2);
2889         }
2890
2891         result = WERR_OK;
2892 done:
2893         ads_destroy(&ads);
2894         ads_kdestroy("MEMORY:prtpub_cache");
2895         talloc_free(tmp_ctx);
2896         return result;
2897 }
2898
2899 bool is_printer_published(TALLOC_CTX *mem_ctx,
2900                           struct auth_serversupplied_info *server_info,
2901                           char *servername, char *printer, struct GUID *guid,
2902                           struct spoolss_PrinterInfo2 **info2)
2903 {
2904         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2905         enum winreg_Type type;
2906         uint8_t *data;
2907         uint32_t data_size;
2908         WERROR result;
2909         NTSTATUS status;
2910
2911         result = winreg_get_printer(mem_ctx, server_info,
2912                                     servername, printer, &pinfo2);
2913         if (!W_ERROR_IS_OK(result)) {
2914                 return false;
2915         }
2916
2917         if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
2918                 TALLOC_FREE(pinfo2);
2919                 return false;
2920         }
2921
2922         if (!guid) {
2923                 goto done;
2924         }
2925
2926         /* fetching printer guids really ought to be a separate function. */
2927
2928         result = winreg_get_printer_dataex(mem_ctx, server_info, printer,
2929                                            SPOOL_DSSPOOLER_KEY, "objectGUID",
2930                                            &type, &data, &data_size);
2931         if (!W_ERROR_IS_OK(result)) {
2932                 TALLOC_FREE(pinfo2);
2933                 return false;
2934         }
2935
2936         /* We used to store the guid as REG_BINARY, then swapped
2937            to REG_SZ for Vista compatibility so check for both */
2938
2939         switch (type) {
2940         case REG_SZ:
2941                 status = GUID_from_string((char *)data, guid);
2942                 if (!NT_STATUS_IS_OK(status)) {
2943                         TALLOC_FREE(pinfo2);
2944                         return false;
2945                 }
2946                 break;
2947
2948         case REG_BINARY:
2949                 if (data_size != sizeof(struct GUID)) {
2950                         TALLOC_FREE(pinfo2);
2951                         return false;
2952                 }
2953                 memcpy(guid, data, sizeof(struct GUID));
2954                 break;
2955         default:
2956                 DEBUG(0,("is_printer_published: GUID value stored as "
2957                          "invaluid type (%d)\n", type));
2958                 break;
2959         }
2960
2961 done:
2962         if (info2) {
2963                 *info2 = talloc_move(mem_ctx, &pinfo2);
2964         }
2965         talloc_free(pinfo2);
2966         return true;
2967 }
2968 #else
2969 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2970                           struct auth_serversupplied_info *server_info,
2971                           struct spoolss_PrinterInfo2 *pinfo2,
2972                           int action)
2973 {
2974         return WERR_OK;
2975 }
2976
2977 WERROR check_published_printers(void)
2978 {
2979         return WERR_OK;
2980 }
2981
2982 bool is_printer_published(TALLOC_CTX *mem_ctx,
2983                           struct auth_serversupplied_info *server_info,
2984                           char *servername, char *printer, struct GUID *guid,
2985                           struct spoolss_PrinterInfo2 **info2)
2986 {
2987         return False;
2988 }
2989 #endif /* HAVE_ADS */
2990
2991 /****************************************************************************
2992  ***************************************************************************/
2993
2994 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2995 {
2996         NT_PRINTER_DATA *data;
2997         int             i;
2998         int             removed_keys = 0;
2999         int             empty_slot;
3000
3001         data = p2->data;
3002         empty_slot = data->num_keys;
3003
3004         if ( !key )
3005                 return WERR_INVALID_PARAM;
3006
3007         /* remove all keys */
3008
3009         if ( !strlen(key) ) {
3010
3011                 TALLOC_FREE( data );
3012
3013                 p2->data = NULL;
3014
3015                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3016                         p2->printername ));
3017
3018                 return WERR_OK;
3019         }
3020
3021         /* remove a specific key (and all subkeys) */
3022
3023         for ( i=0; i<data->num_keys; i++ ) {
3024                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3025                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3026                                 data->keys[i].name));
3027
3028                         TALLOC_FREE( data->keys[i].name );
3029                         TALLOC_FREE( data->keys[i].values );
3030
3031                         /* mark the slot as empty */
3032
3033                         ZERO_STRUCTP( &data->keys[i] );
3034                 }
3035         }
3036
3037         /* find the first empty slot */
3038
3039         for ( i=0; i<data->num_keys; i++ ) {
3040                 if ( !data->keys[i].name ) {
3041                         empty_slot = i;
3042                         removed_keys++;
3043                         break;
3044                 }
3045         }
3046
3047         if ( i == data->num_keys )
3048                 /* nothing was removed */
3049                 return WERR_INVALID_PARAM;
3050
3051         /* move everything down */
3052
3053         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3054                 if ( data->keys[i].name ) {
3055                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3056                         ZERO_STRUCTP( &data->keys[i] );
3057                         empty_slot++;
3058                         removed_keys++;
3059                 }
3060         }
3061
3062         /* update count */
3063
3064         data->num_keys -= removed_keys;
3065
3066         /* sanity check to see if anything is left */
3067
3068         if ( !data->num_keys ) {
3069                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3070
3071                 SAFE_FREE( data->keys );
3072                 ZERO_STRUCTP( data );
3073         }
3074
3075         return WERR_OK;
3076 }
3077
3078 /****************************************************************************
3079  ***************************************************************************/
3080
3081 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3082 {
3083         WERROR          result = WERR_OK;
3084         int             key_index;
3085
3086         /* we must have names on non-zero length */
3087
3088         if ( !key || !*key|| !value || !*value )
3089                 return WERR_INVALID_NAME;
3090
3091         /* find the printer key first */
3092
3093         key_index = lookup_printerkey( p2->data, key );
3094         if ( key_index == -1 )
3095                 return WERR_OK;
3096
3097         /* make sure the value exists so we can return the correct error code */
3098
3099         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3100                 return WERR_BADFILE;
3101
3102         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3103
3104         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3105                 key, value ));
3106
3107         return result;
3108 }
3109
3110 /****************************************************************************
3111  ***************************************************************************/
3112
3113 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3114                            uint32 type, uint8 *data, int real_len )
3115 {
3116         WERROR          result = WERR_OK;
3117         int             key_index;
3118
3119         /* we must have names on non-zero length */
3120
3121         if ( !key || !*key|| !value || !*value )
3122                 return WERR_INVALID_NAME;
3123
3124         /* find the printer key first */
3125
3126         key_index = lookup_printerkey( p2->data, key );
3127         if ( key_index == -1 )
3128                 key_index = add_new_printer_key( p2->data, key );
3129
3130         if ( key_index == -1 )
3131                 return WERR_NOMEM;
3132
3133         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3134                 type, data, real_len );
3135
3136         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3137                 key, value, type, real_len  ));
3138
3139         return result;
3140 }
3141
3142 /****************************************************************************
3143  ***************************************************************************/
3144
3145 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3146 {
3147         int             key_index;
3148
3149         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3150                 return NULL;
3151
3152         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3153                 key, value ));
3154
3155         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3156 }
3157
3158 /****************************************************************************
3159  ***************************************************************************/
3160
3161 static char *win_driver;
3162 static char *os2_driver;
3163
3164 static const char *get_win_driver(void)
3165 {
3166         if (win_driver == NULL) {
3167                 return "";
3168         }
3169         return win_driver;
3170 }
3171
3172 static const char *get_os2_driver(void)
3173 {
3174         if (os2_driver == NULL) {
3175                 return "";
3176         }
3177         return os2_driver;
3178 }
3179
3180 static bool set_driver_mapping(const char *from, const char *to)
3181 {
3182         SAFE_FREE(win_driver);
3183         SAFE_FREE(os2_driver);
3184
3185         win_driver = SMB_STRDUP(from);
3186         os2_driver = SMB_STRDUP(to);
3187
3188         if (win_driver == NULL || os2_driver == NULL) {
3189                 SAFE_FREE(win_driver);
3190                 SAFE_FREE(os2_driver);
3191                 return false;
3192         }
3193         return true;
3194 }
3195
3196 /**
3197  * @internal
3198  *
3199  * @brief Map a Windows driver to a OS/2 driver.
3200  *
3201  * @param[in]  mem_ctx  The memory context to use.
3202  *
3203  * @param[in,out] pdrivername The drivername of Windows to remap.
3204  *
3205  * @return              WERR_OK on success, a corresponding WERROR on failure.
3206  */
3207 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3208 {
3209         const char *mapfile = lp_os2_driver_map();
3210         char **lines = NULL;
3211         const char *drivername;
3212         int numlines = 0;
3213         int i;
3214
3215         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3216                 return WERR_INVALID_PARAMETER;
3217         }
3218
3219         drivername = *pdrivername;
3220
3221         if (mapfile[0] == '\0') {
3222                 return WERR_BADFILE;
3223         }
3224
3225         if (strequal(drivername, get_win_driver())) {
3226                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3227                         drivername, get_os2_driver()));
3228                 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3229                 if (drivername == NULL) {
3230                         return WERR_NOMEM;
3231                 }
3232                 *pdrivername = drivername;
3233                 return WERR_OK;
3234         }
3235
3236         lines = file_lines_load(mapfile, &numlines, 0, NULL);
3237         if (numlines == 0 || lines == NULL) {
3238                 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3239                 TALLOC_FREE(lines);
3240                 return WERR_EMPTY;
3241         }
3242
3243         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3244
3245         for( i = 0; i < numlines; i++) {
3246                 char *nt_name = lines[i];
3247                 char *os2_name = strchr(nt_name, '=');
3248
3249                 if (os2_name == NULL) {
3250                         continue;
3251                 }
3252
3253                 *os2_name++ = '\0';
3254
3255                 while (isspace(*nt_name)) {
3256                         nt_name++;
3257                 }
3258
3259                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3260                         continue;
3261                 }
3262
3263                 {
3264                         int l = strlen(nt_name);
3265                         while (l && isspace(nt_name[l - 1])) {
3266                                 nt_name[l - 1] = 0;
3267                                 l--;
3268                         }
3269                 }
3270
3271                 while (isspace(*os2_name)) {
3272                         os2_name++;
3273                 }
3274
3275                 {
3276                         int l = strlen(os2_name);
3277                         while (l && isspace(os2_name[l-1])) {
3278                                 os2_name[l-1] = 0;
3279                                 l--;
3280                         }
3281                 }
3282
3283                 if (strequal(nt_name, drivername)) {
3284                         DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3285                         set_driver_mapping(drivername, os2_name);
3286                         drivername = talloc_strdup(mem_ctx, os2_name);
3287                         TALLOC_FREE(lines);
3288                         if (drivername == NULL) {
3289                                 return WERR_NOMEM;
3290                         }
3291                         *pdrivername = drivername;
3292                         return WERR_OK;
3293                 }
3294         }
3295
3296         TALLOC_FREE(lines);
3297         return WERR_OK;
3298 }
3299
3300 /****************************************************************************
3301 ****************************************************************************/
3302
3303 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
3304                               struct spoolss_DriverInfo8 *_info8)
3305 {
3306         struct spoolss_DriverInfo8 info8;
3307
3308         ZERO_STRUCT(info8);
3309
3310         switch (r->level) {
3311         case 3:
3312                 info8.version           = r->info.info3->version;
3313                 info8.driver_name       = r->info.info3->driver_name;
3314                 info8.architecture      = r->info.info3->architecture;
3315                 info8.driver_path       = r->info.info3->driver_path;
3316                 info8.data_file         = r->info.info3->data_file;
3317                 info8.config_file       = r->info.info3->config_file;
3318                 info8.help_file         = r->info.info3->help_file;
3319                 info8.monitor_name      = r->info.info3->monitor_name;
3320                 info8.default_datatype  = r->info.info3->default_datatype;
3321                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
3322                         info8.dependent_files   = r->info.info3->dependent_files->string;
3323                 }
3324                 break;
3325         case 6:
3326                 info8.version           = r->info.info6->version;
3327                 info8.driver_name       = r->info.info6->driver_name;
3328                 info8.architecture      = r->info.info6->architecture;
3329                 info8.driver_path       = r->info.info6->driver_path;
3330                 info8.data_file         = r->info.info6->data_file;
3331                 info8.config_file       = r->info.info6->config_file;
3332                 info8.help_file         = r->info.info6->help_file;
3333                 info8.monitor_name      = r->info.info6->monitor_name;
3334                 info8.default_datatype  = r->info.info6->default_datatype;
3335                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
3336                         info8.dependent_files   = r->info.info6->dependent_files->string;
3337                 }
3338                 info8.driver_date       = r->info.info6->driver_date;
3339                 info8.driver_version    = r->info.info6->driver_version;
3340                 info8.manufacturer_name = r->info.info6->manufacturer_name;
3341                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
3342                 info8.hardware_id       = r->info.info6->hardware_id;
3343                 info8.provider          = r->info.info6->provider;
3344                 break;
3345         case 8:
3346                 info8.version           = r->info.info8->version;
3347                 info8.driver_name       = r->info.info8->driver_name;
3348                 info8.architecture      = r->info.info8->architecture;
3349                 info8.driver_path       = r->info.info8->driver_path;
3350                 info8.data_file         = r->info.info8->data_file;
3351                 info8.config_file       = r->info.info8->config_file;
3352                 info8.help_file         = r->info.info8->help_file;
3353                 info8.monitor_name      = r->info.info8->monitor_name;
3354                 info8.default_datatype  = r->info.info8->default_datatype;
3355                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
3356                         info8.dependent_files   = r->info.info8->dependent_files->string;
3357                 }
3358                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
3359                         info8.previous_names    = r->info.info8->previous_names->string;
3360                 }
3361                 info8.driver_date       = r->info.info8->driver_date;
3362                 info8.driver_version    = r->info.info8->driver_version;
3363                 info8.manufacturer_name = r->info.info8->manufacturer_name;
3364                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
3365                 info8.hardware_id       = r->info.info8->hardware_id;
3366                 info8.provider          = r->info.info8->provider;
3367                 info8.print_processor   = r->info.info8->print_processor;
3368                 info8.vendor_setup      = r->info.info8->vendor_setup;
3369                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
3370                         info8.color_profiles = r->info.info8->color_profiles->string;
3371                 }
3372                 info8.inf_path          = r->info.info8->inf_path;
3373                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
3374                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
3375                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
3376                 }
3377                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
3378                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
3379                 break;
3380         default:
3381                 return false;
3382         }
3383
3384         *_info8 = info8;
3385
3386         return true;
3387 }
3388
3389
3390 /****************************************************************************
3391   Determine whether or not a particular driver is currently assigned
3392   to a printer
3393 ****************************************************************************/
3394
3395 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
3396                            struct auth_serversupplied_info *server_info,
3397                            const struct spoolss_DriverInfo8 *r)
3398 {
3399         int snum;
3400         int n_services = lp_numservices();
3401         bool in_use = False;
3402         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3403         WERROR result;
3404
3405         if (!r) {
3406                 return false;
3407         }
3408
3409         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3410
3411         /* loop through the printers.tdb and check for the drivername */
3412
3413         for (snum=0; snum<n_services && !in_use; snum++) {
3414                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
3415                         continue;
3416                 }
3417
3418                 result = winreg_get_printer(mem_ctx, server_info, NULL,
3419                                             lp_servicename(snum), &pinfo2);
3420                 if (!W_ERROR_IS_OK(result)) {
3421                         continue; /* skip */
3422                 }
3423
3424                 if (strequal(r->driver_name, pinfo2->drivername)) {
3425                         in_use = True;
3426                 }
3427
3428                 TALLOC_FREE(pinfo2);
3429         }
3430
3431         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3432
3433         if ( in_use ) {
3434                 struct spoolss_DriverInfo8 *driver;
3435                 WERROR werr;
3436
3437                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
3438
3439                 /* we can still remove the driver if there is one of
3440                    "Windows NT x86" version 2 or 3 left */
3441
3442                 if (!strequal("Windows NT x86", r->architecture)) {
3443                         werr = winreg_get_driver(mem_ctx, server_info,
3444                                                  "Windows NT x86",
3445                                                  r->driver_name,
3446                                                  DRIVER_ANY_VERSION,
3447                                                  &driver);
3448                 } else if (r->version == 2) {
3449                         werr = winreg_get_driver(mem_ctx, server_info,
3450                                                  "Windows NT x86",
3451                                                  r->driver_name,
3452                                                  3, &driver);
3453                 } else if (r->version == 3) {
3454                         werr = winreg_get_driver(mem_ctx, server_info,
3455                                                  "Windows NT x86",
3456                                                  r->driver_name,
3457                                                  2, &driver);
3458                 } else {
3459                         DEBUG(0, ("printer_driver_in_use: ERROR!"
3460                                   " unknown driver version (%d)\n",
3461                                   r->version));
3462                         werr = WERR_UNKNOWN_PRINTER_DRIVER;
3463                 }
3464
3465                 /* now check the error code */
3466
3467                 if ( W_ERROR_IS_OK(werr) ) {
3468                         /* it's ok to remove the driver, we have other architctures left */
3469                         in_use = False;
3470                         talloc_free(driver);
3471                 }
3472         }
3473
3474         /* report that the driver is not in use by default */
3475
3476         return in_use;
3477 }
3478
3479
3480 /**********************************************************************
3481  Check to see if a ogiven file is in use by *info
3482  *********************************************************************/
3483
3484 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
3485 {
3486         int i = 0;
3487
3488         if ( !info )
3489                 return False;
3490
3491         /* mz: skip files that are in the list but already deleted */
3492         if (!file || !file[0]) {
3493                 return false;
3494         }
3495
3496         if (strequal(file, info->driver_path))
3497                 return True;
3498
3499         if (strequal(file, info->data_file))
3500                 return True;
3501
3502         if (strequal(file, info->config_file))
3503                 return True;
3504
3505         if (strequal(file, info->help_file))
3506                 return True;
3507
3508         /* see of there are any dependent files to examine */
3509
3510         if (!info->dependent_files)
3511                 return False;
3512
3513         while (info->dependent_files[i] && *info->dependent_files[i]) {
3514                 if (strequal(file, info->dependent_files[i]))
3515                         return True;
3516                 i++;
3517         }
3518
3519         return False;
3520
3521 }
3522
3523 /**********************************************************************
3524  Utility function to remove the dependent file pointed to by the
3525  input parameter from the list
3526  *********************************************************************/
3527
3528 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
3529 {
3530
3531         /* bump everything down a slot */
3532
3533         while (files && files[idx+1]) {
3534                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
3535                 idx++;
3536         }
3537
3538         files[idx] = NULL;
3539
3540         return;
3541 }
3542
3543 /**********************************************************************
3544  Check if any of the files used by src are also used by drv
3545  *********************************************************************/
3546
3547 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
3548                                    struct spoolss_DriverInfo8 *src,
3549                                    const struct spoolss_DriverInfo8 *drv)
3550 {
3551         bool    in_use = False;
3552         int     i = 0;
3553
3554         if ( !src || !drv )
3555                 return False;
3556
3557         /* check each file.  Remove it from the src structure if it overlaps */
3558
3559         if (drv_file_in_use(src->driver_path, drv)) {
3560                 in_use = True;
3561                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
3562                 src->driver_path = talloc_strdup(mem_ctx, "");
3563                 if (!src->driver_path) { return false; }
3564         }
3565
3566         if (drv_file_in_use(src->data_file, drv)) {
3567                 in_use = True;
3568                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
3569                 src->data_file = talloc_strdup(mem_ctx, "");
3570                 if (!src->data_file) { return false; }
3571         }
3572
3573         if (drv_file_in_use(src->config_file, drv)) {
3574                 in_use = True;
3575                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
3576                 src->config_file = talloc_strdup(mem_ctx, "");
3577                 if (!src->config_file) { return false; }
3578         }
3579
3580         if (drv_file_in_use(src->help_file, drv)) {
3581                 in_use = True;
3582                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
3583                 src->help_file = talloc_strdup(mem_ctx, "");
3584                 if (!src->help_file) { return false; }
3585         }
3586
3587         /* are there any dependentfiles to examine? */
3588
3589         if (!src->dependent_files)
3590                 return in_use;
3591
3592         while (src->dependent_files[i] && *src->dependent_files[i]) {
3593                 if (drv_file_in_use(src->dependent_files[i], drv)) {
3594                         in_use = True;
3595                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
3596                         trim_dependent_file(mem_ctx, src->dependent_files, i);
3597                 } else
3598                         i++;
3599         }
3600
3601         return in_use;
3602 }
3603
3604 /****************************************************************************
3605   Determine whether or not a particular driver files are currently being
3606   used by any other driver.
3607
3608   Return value is True if any files were in use by other drivers
3609   and False otherwise.
3610
3611   Upon return, *info has been modified to only contain the driver files
3612   which are not in use
3613
3614   Fix from mz:
3615
3616   This needs to check all drivers to ensure that all files in use
3617   have been removed from *info, not just the ones in the first
3618   match.
3619 ****************************************************************************/
3620
3621 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
3622                                  struct auth_serversupplied_info *server_info,
3623                                  struct spoolss_DriverInfo8 *info)
3624 {
3625         int                             i;
3626         uint32                          version;
3627         struct spoolss_DriverInfo8      *driver;
3628         bool in_use = false;
3629         uint32_t num_drivers;
3630         const char **drivers;
3631         WERROR result;
3632
3633         if ( !info )
3634                 return False;
3635
3636         version = info->version;
3637
3638         /* loop over all driver versions */
3639
3640         DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
3641
3642         /* get the list of drivers */
3643
3644         result = winreg_get_driver_list(mem_ctx, server_info,
3645                                         info->architecture, version,
3646                                         &num_drivers, &drivers);
3647         if (!W_ERROR_IS_OK(result)) {
3648                 return true;
3649         }
3650
3651         DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
3652                      num_drivers, info->architecture, version));
3653
3654         /* check each driver for overlap in files */
3655
3656         for (i = 0; i < num_drivers; i++) {
3657                 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
3658
3659                 driver = NULL;
3660
3661                 result = winreg_get_driver(mem_ctx, server_info,
3662                                            info->architecture, drivers[i],
3663                                            version, &driver);
3664                 if (!W_ERROR_IS_OK(result)) {
3665                         talloc_free(drivers);
3666                         return True;
3667                 }
3668
3669                 /* check if d2 uses any files from d1 */
3670                 /* only if this is a different driver than the one being deleted */
3671
3672                 if (!strequal(info->driver_name, driver->driver_name)) {
3673                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
3674                                 /* mz: Do not instantly return -
3675                                  * we need to ensure this file isn't
3676                                  * also in use by other drivers. */
3677                                 in_use = true;
3678                         }
3679                 }
3680
3681                 talloc_free(driver);
3682         }
3683
3684         talloc_free(drivers);
3685
3686         DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
3687
3688         return in_use;
3689 }
3690
3691 static NTSTATUS driver_unlink_internals(connection_struct *conn,
3692                                         const char *name)
3693 {
3694         struct smb_filename *smb_fname = NULL;
3695         NTSTATUS status;
3696
3697         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
3698             &smb_fname);
3699         if (!NT_STATUS_IS_OK(status)) {
3700                 return status;
3701         }
3702
3703         status = unlink_internals(conn, NULL, 0, smb_fname, false);
3704
3705         TALLOC_FREE(smb_fname);
3706         return status;
3707 }
3708
3709 /****************************************************************************
3710   Actually delete the driver files.  Make sure that
3711   printer_driver_files_in_use() return False before calling
3712   this.
3713 ****************************************************************************/
3714
3715 bool delete_driver_files(struct auth_serversupplied_info *server_info,
3716                          const struct spoolss_DriverInfo8 *r)
3717 {
3718         int i = 0;
3719         char *s;
3720         const char *file;
3721         connection_struct *conn;
3722         NTSTATUS nt_status;
3723         char *oldcwd;
3724         fstring printdollar;
3725         int printdollar_snum;
3726         bool ret = false;
3727
3728         if (!r) {
3729                 return false;
3730         }
3731
3732         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
3733                 r->driver_name, r->version));
3734
3735         fstrcpy(printdollar, "print$");
3736
3737         printdollar_snum = find_service(printdollar);
3738         if (printdollar_snum == -1) {
3739                 return false;
3740         }
3741
3742         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
3743                                        lp_pathname(printdollar_snum),
3744                                        server_info, &oldcwd);
3745         if (!NT_STATUS_IS_OK(nt_status)) {
3746                 DEBUG(0,("delete_driver_files: create_conn_struct "
3747                          "returned %s\n", nt_errstr(nt_status)));
3748                 return false;
3749         }
3750
3751         if ( !CAN_WRITE(conn) ) {
3752                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
3753                 goto fail;
3754         }
3755
3756         /* now delete the files; must strip the '\print$' string from
3757            fron of path                                                */
3758
3759         if (r->driver_path && r->driver_path[0]) {
3760                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
3761                         file = s;
3762                         DEBUG(10,("deleting driverfile [%s]\n", s));
3763                         driver_unlink_internals(conn, file);
3764                 }
3765         }
3766
3767         if (r->config_file && r->config_file[0]) {
3768                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
3769                         file = s;
3770                         DEBUG(10,("deleting configfile [%s]\n", s));
3771                         driver_unlink_internals(conn, file);
3772                 }
3773         }
3774
3775         if (r->data_file && r->data_file[0]) {
3776                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
3777                         file = s;
3778                         DEBUG(10,("deleting datafile [%s]\n", s));
3779                         driver_unlink_internals(conn, file);
3780                 }
3781         }
3782
3783         if (r->help_file && r->help_file[0]) {
3784                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
3785                         file = s;
3786                         DEBUG(10,("deleting helpfile [%s]\n", s));
3787                         driver_unlink_internals(conn, file);
3788                 }
3789         }
3790
3791         /* check if we are done removing files */
3792
3793         if (r->dependent_files) {
3794                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
3795                         char *p;
3796
3797                         /* bypass the "\print$" portion of the path */
3798
3799                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
3800                                 file = p;
3801                                 DEBUG(10,("deleting dependent file [%s]\n", file));
3802                                 driver_unlink_internals(conn, file);
3803                         }
3804
3805                         i++;
3806                 }
3807         }
3808
3809         goto done;
3810  fail:
3811         ret = false;
3812  done:
3813         if (conn != NULL) {
3814                 vfs_ChDir(conn, oldcwd);
3815                 conn_free(conn);
3816         }
3817         return ret;
3818 }
3819
3820 /****************************************************************************
3821  Store a security desc for a printer.
3822 ****************************************************************************/
3823
3824 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
3825 {
3826         struct sec_desc_buf *new_secdesc_ctr = NULL;
3827         struct sec_desc_buf *old_secdesc_ctr = NULL;
3828         TALLOC_CTX *mem_ctx = NULL;
3829         TDB_DATA kbuf;
3830         TDB_DATA dbuf;
3831         DATA_BLOB blob;
3832         WERROR status;
3833         NTSTATUS nt_status;
3834
3835         mem_ctx = talloc_init("nt_printing_setsec");
3836         if (mem_ctx == NULL)
3837                 return WERR_NOMEM;
3838
3839         /* The old owner and group sids of the security descriptor are not
3840            present when new ACEs are added or removed by changing printer
3841            permissions through NT.  If they are NULL in the new security
3842            descriptor then copy them over from the old one. */
3843
3844         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
3845                 struct dom_sid *owner_sid, *group_sid;
3846                 struct security_acl *dacl, *sacl;
3847                 struct security_descriptor *psd = NULL;
3848                 size_t size;
3849
3850                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
3851                         status = WERR_NOMEM;
3852                         goto out;
3853                 }
3854
3855                 /* Pick out correct owner and group sids */
3856
3857                 owner_sid = secdesc_ctr->sd->owner_sid ?
3858                         secdesc_ctr->sd->owner_sid :
3859                         old_secdesc_ctr->sd->owner_sid;
3860
3861                 group_sid = secdesc_ctr->sd->group_sid ?
3862                         secdesc_ctr->sd->group_sid :
3863                         old_secdesc_ctr->sd->group_sid;
3864
3865                 dacl = secdesc_ctr->sd->dacl ?
3866                         secdesc_ctr->sd->dacl :
3867                         old_secdesc_ctr->sd->dacl;
3868
3869                 sacl = secdesc_ctr->sd->sacl ?
3870                         secdesc_ctr->sd->sacl :
3871                         old_secdesc_ctr->sd->sacl;
3872
3873                 /* Make a deep copy of the security descriptor */
3874
3875                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
3876                                     owner_sid, group_sid,
3877                                     sacl,
3878                                     dacl,
3879                                     &size);
3880
3881                 if (!psd) {
3882                         status = WERR_NOMEM;
3883                         goto out;
3884                 }
3885
3886                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3887         }
3888
3889         if (!new_secdesc_ctr) {
3890                 new_secdesc_ctr = secdesc_ctr;
3891         }
3892
3893         /* Store the security descriptor in a tdb */
3894
3895         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
3896                                           &blob.data, &blob.length);
3897         if (!NT_STATUS_IS_OK(nt_status)) {
3898                 status = ntstatus_to_werror(nt_status);
3899                 goto out;
3900         }
3901
3902         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
3903
3904         dbuf.dptr = (unsigned char *)blob.data;
3905         dbuf.dsize = blob.length;
3906
3907         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
3908                 status = WERR_OK;
3909         } else {
3910                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
3911                 status = WERR_BADFUNC;
3912         }
3913
3914         /* Free malloc'ed memory */
3915         talloc_free(blob.data);
3916
3917  out:
3918
3919         if (mem_ctx)
3920                 talloc_destroy(mem_ctx);
3921         return status;
3922 }
3923
3924 /****************************************************************************
3925  Construct a default security descriptor buffer for a printer.
3926 ****************************************************************************/
3927
3928 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
3929 {
3930         struct security_ace ace[7];     /* max number of ace entries */
3931         int i = 0;
3932         uint32_t sa;
3933         struct security_acl *psa = NULL;
3934         struct sec_desc_buf *sdb = NULL;
3935         struct security_descriptor *psd = NULL;
3936         struct dom_sid adm_sid;
3937         size_t sd_size;
3938
3939         /* Create an ACE where Everyone is allowed to print */
3940
3941         sa = PRINTER_ACE_PRINT;
3942         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3943                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3944
3945         /* Add the domain admins group if we are a DC */
3946
3947         if ( IS_DC ) {
3948                 struct dom_sid domadmins_sid;
3949
3950                 sid_compose(&domadmins_sid, get_global_sam_sid(),
3951                             DOMAIN_RID_ADMINS);
3952
3953                 sa = PRINTER_ACE_FULL_CONTROL;
3954                 init_sec_ace(&ace[i++], &domadmins_sid,
3955                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3956                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3957                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3958                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3959         }
3960         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
3961                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
3962
3963                 sa = PRINTER_ACE_FULL_CONTROL;
3964                 init_sec_ace(&ace[i++], &adm_sid,
3965                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3966                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3967                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3968                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3969         }
3970
3971         /* add BUILTIN\Administrators as FULL CONTROL */
3972
3973         sa = PRINTER_ACE_FULL_CONTROL;
3974         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
3975                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3976                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3977         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
3978                 SEC_ACE_TYPE_ACCESS_ALLOWED,
3979                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3980
3981         /* add BUILTIN\Print Operators as FULL CONTROL */
3982
3983         sa = PRINTER_ACE_FULL_CONTROL;
3984         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
3985                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3986                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3987         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
3988                 SEC_ACE_TYPE_ACCESS_ALLOWED,
3989                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3990
3991         /* Make the security descriptor owned by the BUILTIN\Administrators */
3992
3993         /* The ACL revision number in rpc_secdesc.h differs from the one
3994            created by NT when setting ACE entries in printer
3995            descriptors.  NT4 complains about the property being edited by a
3996            NT5 machine. */
3997
3998         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
3999                 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
4000                         &global_sid_Builtin_Administrators,
4001                         &global_sid_Builtin_Administrators,
4002                         NULL, psa, &sd_size);
4003         }
4004
4005         if (!psd) {
4006                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4007                 return NULL;
4008         }
4009
4010         sdb = make_sec_desc_buf(ctx, sd_size, psd);
4011
4012         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4013                  (unsigned int)sd_size));
4014
4015         return sdb;
4016 }
4017
4018 /****************************************************************************
4019  Get a security desc for a printer.
4020 ****************************************************************************/
4021
4022 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
4023 {
4024         TDB_DATA kbuf;
4025         TDB_DATA dbuf;
4026         DATA_BLOB blob;
4027         char *temp;
4028         NTSTATUS status;
4029
4030         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
4031                 sharename = temp + 1;
4032         }
4033
4034         /* Fetch security descriptor from tdb */
4035
4036         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
4037
4038         dbuf = tdb_fetch(tdb_printers, kbuf);
4039         if (dbuf.dptr) {
4040
4041                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
4042                                                  secdesc_ctr);
4043                 SAFE_FREE(dbuf.dptr);
4044
4045                 if (NT_STATUS_IS_OK(status)) {
4046                         return true;
4047                 }
4048         }
4049
4050         *secdesc_ctr = construct_default_printer_sdb(ctx);
4051         if (!*secdesc_ctr) {
4052                 return false;
4053         }
4054
4055         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
4056                                        &blob.data, &blob.length);
4057         if (NT_STATUS_IS_OK(status)) {
4058                 dbuf.dptr = (unsigned char *)blob.data;
4059                 dbuf.dsize = blob.length;
4060                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
4061                 talloc_free(blob.data);
4062         }
4063
4064         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4065            this security descriptor has been created when winbindd was
4066            down.  Take ownership of security descriptor. */
4067
4068         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
4069                 struct dom_sid owner_sid;
4070
4071                 /* Change sd owner to workgroup administrator */
4072
4073                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4074                         struct sec_desc_buf *new_secdesc_ctr = NULL;
4075                         struct security_descriptor *psd = NULL;
4076                         size_t size;
4077
4078                         /* Create new sd */
4079
4080                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
4081
4082                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
4083                                             &owner_sid,
4084                                             (*secdesc_ctr)->sd->group_sid,
4085                                             (*secdesc_ctr)->sd->sacl,
4086                                             (*secdesc_ctr)->sd->dacl,
4087                                             &size);
4088
4089                         if (!psd) {
4090                                 return False;
4091                         }
4092
4093                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4094                         if (!new_secdesc_ctr) {
4095                                 return False;
4096                         }
4097
4098                         /* Swap with other one */
4099
4100                         *secdesc_ctr = new_secdesc_ctr;
4101
4102                         /* Set it */
4103
4104                         nt_printing_setsec(sharename, *secdesc_ctr);
4105                 }
4106         }
4107
4108         if (DEBUGLEVEL >= 10) {
4109                 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
4110                 int i;
4111
4112                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4113                            sharename, the_acl->num_aces));
4114
4115                 for (i = 0; i < the_acl->num_aces; i++) {
4116                         DEBUG(10, ("%s %d %d 0x%08x\n",
4117                                    sid_string_dbg(&the_acl->aces[i].trustee),
4118                                    the_acl->aces[i].type, the_acl->aces[i].flags,
4119                                    the_acl->aces[i].access_mask));
4120                 }
4121         }
4122
4123         return True;
4124 }
4125
4126 /* error code:
4127         0: everything OK
4128         1: level not implemented
4129         2: file doesn't exist
4130         3: can't allocate memory
4131         4: can't free memory
4132         5: non existant struct
4133 */
4134
4135 /*
4136         A printer and a printer driver are 2 different things.
4137         NT manages them separatelly, Samba does the same.
4138         Why ? Simply because it's easier and it makes sense !
4139
4140         Now explanation: You have 3 printers behind your samba server,
4141         2 of them are the same make and model (laser A and B). But laser B
4142         has an 3000 sheet feeder and laser A doesn't such an option.
4143         Your third printer is an old dot-matrix model for the accounting :-).
4144
4145         If the /usr/local/samba/lib directory (default dir), you will have
4146         5 files to describe all of this.
4147
4148         3 files for the printers (1 by printer):
4149                 NTprinter_laser A
4150                 NTprinter_laser B
4151                 NTprinter_accounting
4152         2 files for the drivers (1 for the laser and 1 for the dot matrix)
4153                 NTdriver_printer model X
4154                 NTdriver_printer model Y
4155
4156 jfm: I should use this comment for the text file to explain
4157         same thing for the forms BTW.
4158         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4159
4160 */
4161
4162 /* Convert generic access rights to printer object specific access rights.
4163    It turns out that NT4 security descriptors use generic access rights and
4164    NT5 the object specific ones. */
4165
4166 void map_printer_permissions(struct security_descriptor *sd)
4167 {
4168         int i;
4169
4170         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4171                 se_map_generic(&sd->dacl->aces[i].access_mask,
4172                                &printer_generic_mapping);
4173         }
4174 }
4175
4176 void map_job_permissions(struct security_descriptor *sd)
4177 {
4178         int i;
4179
4180         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4181                 se_map_generic(&sd->dacl->aces[i].access_mask,
4182                                &job_generic_mapping);
4183         }
4184 }
4185
4186
4187 /****************************************************************************
4188  Check a user has permissions to perform the given operation.  We use the
4189  permission constants defined in include/rpc_spoolss.h to check the various
4190  actions we perform when checking printer access.
4191
4192    PRINTER_ACCESS_ADMINISTER:
4193        print_queue_pause, print_queue_resume, update_printer_sec,
4194        update_printer, spoolss_addprinterex_level_2,
4195        _spoolss_setprinterdata
4196
4197    PRINTER_ACCESS_USE:
4198        print_job_start
4199
4200    JOB_ACCESS_ADMINISTER:
4201        print_job_delete, print_job_pause, print_job_resume,
4202        print_queue_purge
4203
4204   Try access control in the following order (for performance reasons):
4205     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
4206     2)  check security descriptor (bit comparisons in memory)
4207     3)  "printer admins" (may result in numerous calls to winbind)
4208
4209  ****************************************************************************/
4210 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
4211                         int access_type)
4212 {
4213         struct spoolss_security_descriptor *secdesc = NULL;
4214         uint32 access_granted;
4215         size_t sd_size;
4216         NTSTATUS status;
4217         WERROR result;
4218         const char *pname;
4219         TALLOC_CTX *mem_ctx = NULL;
4220         SE_PRIV se_printop = SE_PRINT_OPERATOR;
4221
4222         /* If user is NULL then use the current_user structure */
4223
4224         /* Always allow root or SE_PRINT_OPERATROR to do anything */
4225
4226         if (server_info->utok.uid == sec_initial_uid()
4227             || user_has_privileges(server_info->ptok, &se_printop ) ) {
4228                 return True;
4229         }
4230
4231         /* Get printer name */
4232
4233         pname = lp_printername(snum);
4234
4235         if (!pname || !*pname) {
4236                 errno = EACCES;
4237                 return False;
4238         }
4239
4240         /* Get printer security descriptor */
4241
4242         if(!(mem_ctx = talloc_init("print_access_check"))) {
4243                 errno = ENOMEM;
4244                 return False;
4245         }
4246
4247         result = winreg_get_printer_secdesc(mem_ctx,
4248                                             server_info,
4249                                             pname,
4250                                             &secdesc);
4251         if (!W_ERROR_IS_OK(result)) {
4252                 talloc_destroy(mem_ctx);
4253                 errno = ENOMEM;
4254                 return False;
4255         }
4256
4257         if (access_type == JOB_ACCESS_ADMINISTER) {
4258                 struct spoolss_security_descriptor *parent_secdesc = secdesc;
4259
4260                 /* Create a child security descriptor to check permissions
4261                    against.  This is because print jobs are child objects
4262                    objects of a printer. */
4263                 status = se_create_child_secdesc(mem_ctx,
4264                                                  &secdesc,
4265                                                  &sd_size,
4266                                                  parent_secdesc,
4267                                                  parent_secdesc->owner_sid,
4268                                                  parent_secdesc->group_sid,
4269                                                  false);
4270                 if (!NT_STATUS_IS_OK(status)) {
4271                         talloc_destroy(mem_ctx);
4272                         errno = map_errno_from_nt_status(status);
4273                         return False;
4274                 }
4275
4276                 map_job_permissions(secdesc);
4277         } else {
4278                 map_printer_permissions(secdesc);
4279         }
4280
4281         /* Check access */
4282         status = se_access_check(secdesc, server_info->ptok, access_type,
4283                                  &access_granted);
4284
4285         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
4286
4287         /* see if we need to try the printer admin list */
4288
4289         if (!NT_STATUS_IS_OK(status) &&
4290             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
4291                                          server_info->info3->base.domain.string,
4292                                          NULL, server_info->ptok,
4293                                          lp_printer_admin(snum)))) {
4294                 talloc_destroy(mem_ctx);
4295                 return True;
4296         }
4297
4298         talloc_destroy(mem_ctx);
4299
4300         if (!NT_STATUS_IS_OK(status)) {
4301                 errno = EACCES;
4302         }
4303
4304         return NT_STATUS_IS_OK(status);
4305 }
4306
4307 /****************************************************************************
4308  Check the time parameters allow a print operation.
4309 *****************************************************************************/
4310
4311 bool print_time_access_check(struct auth_serversupplied_info *server_info,
4312                              const char *servicename)
4313 {
4314         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4315         WERROR result;
4316         bool ok = False;
4317         time_t now = time(NULL);
4318         struct tm *t;
4319         uint32 mins;
4320
4321         result = winreg_get_printer(NULL, server_info,
4322                                     NULL, servicename, &pinfo2);
4323         if (!W_ERROR_IS_OK(result)) {
4324                 return False;
4325         }
4326
4327         if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
4328                 ok = True;
4329         }
4330
4331         t = gmtime(&now);
4332         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4333
4334         if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
4335                 ok = True;
4336         }
4337
4338         TALLOC_FREE(pinfo2);
4339
4340         if (!ok) {
4341                 errno = EACCES;
4342         }
4343
4344         return ok;
4345 }
4346
4347 void nt_printer_remove(TALLOC_CTX *mem_ctx,
4348                         struct auth_serversupplied_info *server_info,
4349                         const char *printer)
4350 {
4351         WERROR result;
4352
4353         result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
4354         if (!W_ERROR_IS_OK(result)) {
4355                 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",
4356                           printer));
4357         }
4358 }