s3-printing: Fix Bug #7541, %D in "printer admin" causing smbd crash.
[abartlet/samba.git/.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
29 static TDB_CONTEXT *tdb_forms; /* used for forms files */
30 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
31 static TDB_CONTEXT *tdb_printers; /* used for printers files */
32
33 #define FORMS_PREFIX "FORMS/"
34 #define DRIVERS_PREFIX "DRIVERS/"
35 #define PRINTERS_PREFIX "PRINTERS/"
36 #define SECDESC_PREFIX "SECDESC/"
37 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38
39 #define NTDRIVERS_DATABASE_VERSION_1 1
40 #define NTDRIVERS_DATABASE_VERSION_2 2
41 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
43 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44
45 /* Map generic permissions to printer object specific permissions */
46
47 const struct generic_mapping printer_generic_mapping = {
48         PRINTER_READ,
49         PRINTER_WRITE,
50         PRINTER_EXECUTE,
51         PRINTER_ALL_ACCESS
52 };
53
54 const struct standard_mapping printer_std_mapping = {
55         PRINTER_READ,
56         PRINTER_WRITE,
57         PRINTER_EXECUTE,
58         PRINTER_ALL_ACCESS
59 };
60
61 /* Map generic permissions to print server object specific permissions */
62
63 const struct generic_mapping printserver_generic_mapping = {
64         SERVER_READ,
65         SERVER_WRITE,
66         SERVER_EXECUTE,
67         SERVER_ALL_ACCESS
68 };
69
70 const struct generic_mapping printserver_std_mapping = {
71         SERVER_READ,
72         SERVER_WRITE,
73         SERVER_EXECUTE,
74         SERVER_ALL_ACCESS
75 };
76
77 /* Map generic permissions to job object specific permissions */
78
79 const struct generic_mapping job_generic_mapping = {
80         JOB_READ,
81         JOB_WRITE,
82         JOB_EXECUTE,
83         JOB_ALL_ACCESS
84 };
85
86 /* We need one default form to support our default printer. Msoft adds the
87 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
88 array index). Letter is always first, so (for the current code) additions
89 always put things in the correct order. */
90 static const nt_forms_struct default_forms[] = {
91         {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
92         {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
93         {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
94         {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
95         {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
96         {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
97         {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
98         {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
99         {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
100         {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
101         {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
102         {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
103         {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
104         {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
105         {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
106         {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
107         {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
108         {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
109         {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
110         {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
111         {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
112         {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
113         {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
114         {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
115         {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
116         {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
117         {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
118         {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
119         {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
120         {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
121         {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
122         {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
123         {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
124         {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
125         {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
126         {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
127         {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
128         {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
129         {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
130         {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
131         {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
132         {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
133         {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
134         {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
135         {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
136         {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
137         {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
138         {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
139         {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
140         {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
141         {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
142         {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
143         {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
144         {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
145         {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
146         {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
147         {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
148         {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
149         {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
150         {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
151         {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
152         {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
153         {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
154         {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
155         {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
156         {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
157         {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
158         {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
159         {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
160         {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
161         {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
162         {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
163         {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
164         {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
165         {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
166         {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
167         {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
168         {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
169         {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
170         {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
171         {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
172         {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
173         {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
174         {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
175         {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
176         {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
177         {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
178         {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
179         {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
180         {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
181         {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
182         {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
183         {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
184         {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
185         {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
186         {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
187         {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
188         {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
189         {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
190         {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
191         {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
192         {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
193         {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
194         {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
195         {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
196         {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
197         {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
198         {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
199         {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
200         {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
201         {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
202         {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
203         {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
204         {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
205         {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
206         {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
207         {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
208         {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
209         {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
210         {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
211 };
212
213 static const struct print_architecture_table_node archi_table[]= {
214
215         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
216         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
217         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
218         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
219         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
220         {"Windows IA64",         SPL_ARCH_IA64,         3 },
221         {"Windows x64",          SPL_ARCH_X64,          3 },
222         {NULL,                   "",            -1 }
223 };
224
225
226 /****************************************************************************
227  generate a new TDB_DATA key for storing a printer
228 ****************************************************************************/
229
230 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
231 {
232         fstring share;
233         char *keystr = NULL;
234         TDB_DATA key;
235
236         fstrcpy(share, sharename);
237         strlower_m(share);
238
239         keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
240         key = string_term_tdb_data(keystr ? keystr : "");
241
242         return key;
243 }
244
245 /****************************************************************************
246  generate a new TDB_DATA key for storing a printer security descriptor
247 ****************************************************************************/
248
249 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
250                                         const char* sharename  )
251 {
252         fstring share;
253         char *keystr = NULL;
254         TDB_DATA key;
255
256         fstrcpy(share, sharename );
257         strlower_m(share);
258
259         keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
260         key = string_term_tdb_data(keystr ? keystr : "");
261
262         return key;
263 }
264
265 /****************************************************************************
266 ****************************************************************************/
267
268 static bool upgrade_to_version_3(void)
269 {
270         TDB_DATA kbuf, newkey, dbuf;
271
272         DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
273
274         for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
275                         newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
276
277                 dbuf = tdb_fetch(tdb_drivers, kbuf);
278
279                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
280                         DEBUG(0,("upgrade_to_version_3:moving form\n"));
281                         if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
282                                 SAFE_FREE(dbuf.dptr);
283                                 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
284                                 return False;
285                         }
286                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
287                                 SAFE_FREE(dbuf.dptr);
288                                 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
289                                 return False;
290                         }
291                 }
292
293                 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
294                         DEBUG(0,("upgrade_to_version_3:moving printer\n"));
295                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
296                                 SAFE_FREE(dbuf.dptr);
297                                 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
298                                 return False;
299                         }
300                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
301                                 SAFE_FREE(dbuf.dptr);
302                                 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
303                                 return False;
304                         }
305                 }
306
307                 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
308                         DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
309                         if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
310                                 SAFE_FREE(dbuf.dptr);
311                                 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
312                                 return False;
313                         }
314                         if (tdb_delete(tdb_drivers, kbuf) != 0) {
315                                 SAFE_FREE(dbuf.dptr);
316                                 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
317                                 return False;
318                         }
319                 }
320
321                 SAFE_FREE(dbuf.dptr);
322         }
323
324         return True;
325 }
326
327 /*******************************************************************
328  Fix an issue with security descriptors.  Printer sec_desc must
329  use more than the generic bits that were previously used
330  in <= 3.0.14a.  They must also have a owner and group SID assigned.
331  Otherwise, any printers than have been migrated to a Windows
332  host using printmig.exe will not be accessible.
333 *******************************************************************/
334
335 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
336                             TDB_DATA data, void *state )
337 {
338         NTSTATUS status;
339         struct sec_desc_buf *sd_orig = NULL;
340         struct sec_desc_buf *sd_new, *sd_store;
341         struct security_descriptor *sec, *new_sec;
342         TALLOC_CTX *ctx = state;
343         int result, i;
344         uint32 sd_size;
345         size_t size_new_sec;
346
347         if (!data.dptr || data.dsize == 0) {
348                 return 0;
349         }
350
351         if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
352                 return 0;
353         }
354
355         /* upgrade the security descriptor */
356
357         status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
358         if (!NT_STATUS_IS_OK(status)) {
359                 /* delete bad entries */
360                 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si.  Deleting....\n",
361                         (const char *)key.dptr ));
362                 tdb_delete( tdb_printers, key );
363                 return 0;
364         }
365
366         if (!sd_orig) {
367                 return 0;
368         }
369         sec = sd_orig->sd;
370
371         /* is this even valid? */
372
373         if ( !sec->dacl ) {
374                 return 0;
375         }
376
377         /* update access masks */
378
379         for ( i=0; i<sec->dacl->num_aces; i++ ) {
380                 switch ( sec->dacl->aces[i].access_mask ) {
381                         case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
382                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
383                                 break;
384
385                         case GENERIC_ALL_ACCESS:
386                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
387                                 break;
388
389                         case READ_CONTROL_ACCESS:
390                                 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
391
392                         default:        /* no change */
393                                 break;
394                 }
395         }
396
397         /* create a new struct security_descriptor with the appropriate owner and group SIDs */
398
399         new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
400                                  &global_sid_Builtin_Administrators,
401                                  &global_sid_Builtin_Administrators,
402                                  NULL, NULL, &size_new_sec );
403         if (!new_sec) {
404                 return 0;
405         }
406         sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
407         if (!sd_new) {
408                 return 0;
409         }
410
411         if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
412                 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
413                 return 0;
414         }
415
416         /* store it back */
417
418         sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
419                 + sizeof(struct sec_desc_buf);
420
421         status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
422         if (!NT_STATUS_IS_OK(status)) {
423                 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
424                 return 0;
425         }
426
427         result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
428
429         /* 0 to continue and non-zero to stop traversal */
430
431         return (result == -1);
432 }
433
434 /*******************************************************************
435 *******************************************************************/
436
437 static bool upgrade_to_version_4(void)
438 {
439         TALLOC_CTX *ctx;
440         int result;
441
442         DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
443
444         if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
445                 return False;
446
447         result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
448
449         talloc_destroy( ctx );
450
451         return ( result != -1 );
452 }
453
454 /*******************************************************************
455  Fix an issue with security descriptors.  Printer sec_desc must
456  use more than the generic bits that were previously used
457  in <= 3.0.14a.  They must also have a owner and group SID assigned.
458  Otherwise, any printers than have been migrated to a Windows
459  host using printmig.exe will not be accessible.
460 *******************************************************************/
461
462 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
463                                   TDB_DATA data, void *state )
464 {
465         TALLOC_CTX *ctx = talloc_tos();
466         TDB_DATA new_key;
467
468         if (!data.dptr || data.dsize == 0)
469                 return 0;
470
471         /* upgrade printer records and security descriptors */
472
473         if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
474                 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
475         }
476         else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
477                 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
478         }
479         else {
480                 /* ignore this record */
481                 return 0;
482         }
483
484         /* delete the original record and store under the normalized key */
485
486         if ( tdb_delete( the_tdb, key ) != 0 ) {
487                 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
488                         key.dptr));
489                 return 1;
490         }
491
492         if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
493                 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
494                         key.dptr));
495                 return 1;
496         }
497
498         return 0;
499 }
500
501 /*******************************************************************
502 *******************************************************************/
503
504 static bool upgrade_to_version_5(void)
505 {
506         TALLOC_CTX *ctx;
507         int result;
508
509         DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
510
511         if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
512                 return False;
513
514         result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
515
516         talloc_destroy( ctx );
517
518         return ( result != -1 );
519 }
520
521 /****************************************************************************
522  Open the NT printing tdbs. Done once before fork().
523 ****************************************************************************/
524
525 bool nt_printing_init(struct messaging_context *msg_ctx)
526 {
527         const char *vstring = "INFO/version";
528         WERROR win_rc;
529         int32 vers_id;
530
531         if ( tdb_drivers && tdb_printers && tdb_forms )
532                 return True;
533
534         if (tdb_drivers)
535                 tdb_close(tdb_drivers);
536         tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
537         if (!tdb_drivers) {
538                 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
539                         state_path("ntdrivers.tdb"), strerror(errno) ));
540                 return False;
541         }
542
543         if (tdb_printers)
544                 tdb_close(tdb_printers);
545         tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
546         if (!tdb_printers) {
547                 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
548                         state_path("ntprinters.tdb"), strerror(errno) ));
549                 return False;
550         }
551
552         if (tdb_forms)
553                 tdb_close(tdb_forms);
554         tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
555         if (!tdb_forms) {
556                 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
557                         state_path("ntforms.tdb"), strerror(errno) ));
558                 return False;
559         }
560
561         /* handle a Samba upgrade */
562
563         vers_id = tdb_fetch_int32(tdb_drivers, vstring);
564         if (vers_id == -1) {
565                 DEBUG(10, ("Fresh database\n"));
566                 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
567                 vers_id = NTDRIVERS_DATABASE_VERSION_5;
568         }
569
570         if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
571
572                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
573                         if (!upgrade_to_version_3())
574                                 return False;
575                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
576                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
577                 }
578
579                 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
580                         /* Written on a bigendian machine with old fetch_int code. Save as le. */
581                         /* The only upgrade between V2 and V3 is to save the version in little-endian. */
582                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
583                         vers_id = NTDRIVERS_DATABASE_VERSION_3;
584                 }
585
586                 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
587                         if ( !upgrade_to_version_4() )
588                                 return False;
589                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
590                         vers_id = NTDRIVERS_DATABASE_VERSION_4;
591                 }
592
593                 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
594                         if ( !upgrade_to_version_5() )
595                                 return False;
596                         tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
597                         vers_id = NTDRIVERS_DATABASE_VERSION_5;
598                 }
599
600
601                 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
602                         DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
603                         return False;
604                 }
605         }
606
607         update_c_setprinter(True);
608
609         /*
610          * register callback to handle updating printers as new
611          * drivers are installed
612          */
613
614         messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
615                            do_drv_upgrade_printer);
616
617         /* of course, none of the message callbacks matter if you don't
618            tell messages.c that you interested in receiving PRINT_GENERAL
619            msgs.  This is done in serverid_register() */
620
621
622         if ( lp_security() == SEC_ADS ) {
623                 win_rc = check_published_printers();
624                 if (!W_ERROR_IS_OK(win_rc))
625                         DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
626         }
627
628         return True;
629 }
630
631 /*******************************************************************
632  Function to allow filename parsing "the old way".
633 ********************************************************************/
634
635 static NTSTATUS driver_unix_convert(connection_struct *conn,
636                                     const char *old_name,
637                                     struct smb_filename **smb_fname)
638 {
639         NTSTATUS status;
640         TALLOC_CTX *ctx = talloc_tos();
641         char *name = talloc_strdup(ctx, old_name);
642
643         if (!name) {
644                 return NT_STATUS_NO_MEMORY;
645         }
646         unix_format(name);
647         name = unix_clean_name(ctx, name);
648         if (!name) {
649                 return NT_STATUS_NO_MEMORY;
650         }
651         trim_string(name,"/","/");
652
653         status = unix_convert(ctx, conn, name, smb_fname, 0);
654         if (!NT_STATUS_IS_OK(status)) {
655                 return NT_STATUS_NO_MEMORY;
656         }
657
658         return NT_STATUS_OK;
659 }
660
661 /*******************************************************************
662  tdb traversal function for counting printers.
663 ********************************************************************/
664
665 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
666                                       TDB_DATA data, void *context)
667 {
668         int *printer_count = (int*)context;
669
670         if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
671                 (*printer_count)++;
672                 DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
673         }
674
675         return 0;
676 }
677
678 /*******************************************************************
679  Update the spooler global c_setprinter. This variable is initialized
680  when the parent smbd starts with the number of existing printers. It
681  is monotonically increased by the current number of printers *after*
682  each add or delete printer RPC. Only Microsoft knows why... JRR020119
683 ********************************************************************/
684
685 uint32 update_c_setprinter(bool initialize)
686 {
687         int32 c_setprinter;
688         int32 printer_count = 0;
689
690         tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
691
692         /* Traverse the tdb, counting the printers */
693         tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
694
695         /* If initializing, set c_setprinter to current printers count
696          * otherwise, bump it by the current printer count
697          */
698         if (!initialize)
699                 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
700         else
701                 c_setprinter = printer_count;
702
703         DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
704         tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
705
706         tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
707
708         return (uint32)c_setprinter;
709 }
710
711 /*******************************************************************
712  Get the spooler global c_setprinter, accounting for initialization.
713 ********************************************************************/
714
715 uint32 get_c_setprinter(void)
716 {
717         int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
718
719         if (c_setprinter == (int32)-1)
720                 c_setprinter = update_c_setprinter(True);
721
722         DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
723
724         return (uint32)c_setprinter;
725 }
726
727 /****************************************************************************
728  Get builtin form struct list.
729 ****************************************************************************/
730
731 int get_builtin_ntforms(nt_forms_struct **list)
732 {
733         *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
734         if (!*list) {
735                 return 0;
736         }
737         return ARRAY_SIZE(default_forms);
738 }
739
740 /****************************************************************************
741  get a builtin form struct
742 ****************************************************************************/
743
744 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
745 {
746         int i;
747         DEBUGADD(6,("Looking for builtin form %s \n", form_name));
748         for (i=0; i<ARRAY_SIZE(default_forms); i++) {
749                 if (strequal(form_name,default_forms[i].name)) {
750                         DEBUGADD(6,("Found builtin form %s \n", form_name));
751                         memcpy(form,&default_forms[i],sizeof(*form));
752                         return true;
753                 }
754         }
755
756         return false;
757 }
758
759 /****************************************************************************
760  get a form struct list.
761 ****************************************************************************/
762
763 int get_ntforms(nt_forms_struct **list)
764 {
765         TDB_DATA kbuf, newkey, dbuf;
766         nt_forms_struct form;
767         int ret;
768         int i;
769         int n = 0;
770
771         *list = NULL;
772
773         for (kbuf = tdb_firstkey(tdb_forms);
774              kbuf.dptr;
775              newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
776         {
777                 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
778                         continue;
779
780                 dbuf = tdb_fetch(tdb_forms, kbuf);
781                 if (!dbuf.dptr)
782                         continue;
783
784                 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
785                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
786                                  &i, &form.flag, &form.width, &form.length, &form.left,
787                                  &form.top, &form.right, &form.bottom);
788                 SAFE_FREE(dbuf.dptr);
789                 if (ret != dbuf.dsize)
790                         continue;
791
792                 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
793                 if (!*list) {
794                         DEBUG(0,("get_ntforms: Realloc fail.\n"));
795                         return 0;
796                 }
797                 (*list)[n] = form;
798                 n++;
799         }
800
801
802         return n;
803 }
804
805 /****************************************************************************
806 write a form struct list
807 ****************************************************************************/
808
809 int write_ntforms(nt_forms_struct **list, int number)
810 {
811         TALLOC_CTX *ctx = talloc_tos();
812         char *buf = NULL;
813         char *key = NULL;
814         int len;
815         TDB_DATA dbuf;
816         int i;
817
818         for (i=0;i<number;i++) {
819                 /* save index, so list is rebuilt in correct order */
820                 len = tdb_pack(NULL, 0, "dddddddd",
821                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
822                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
823                                (*list)[i].bottom);
824                 if (!len) {
825                         continue;
826                 }
827                 buf = TALLOC_ARRAY(ctx, char, len);
828                 if (!buf) {
829                         return 0;
830                 }
831                 len = tdb_pack((uint8 *)buf, len, "dddddddd",
832                                i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
833                                (*list)[i].left, (*list)[i].top, (*list)[i].right,
834                                (*list)[i].bottom);
835                 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
836                 if (!key) {
837                         return 0;
838                 }
839                 dbuf.dsize = len;
840                 dbuf.dptr = (uint8 *)buf;
841                 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
842                         TALLOC_FREE(key);
843                         TALLOC_FREE(buf);
844                         break;
845                 }
846                 TALLOC_FREE(key);
847                 TALLOC_FREE(buf);
848        }
849
850        return i;
851 }
852
853 /****************************************************************************
854 add a form struct at the end of the list
855 ****************************************************************************/
856 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
857 {
858         int n=0;
859         bool update;
860
861         /*
862          * NT tries to add forms even when
863          * they are already in the base
864          * only update the values if already present
865          */
866
867         update=False;
868
869         for (n=0; n<*count; n++) {
870                 if ( strequal((*list)[n].name, form->form_name) ) {
871                         update=True;
872                         break;
873                 }
874         }
875
876         if (update==False) {
877                 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
878                         DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
879                         return False;
880                 }
881                 fstrcpy((*list)[n].name, form->form_name);
882                 (*count)++;
883         }
884
885         (*list)[n].flag         = form->flags;
886         (*list)[n].width        = form->size.width;
887         (*list)[n].length       = form->size.height;
888         (*list)[n].left         = form->area.left;
889         (*list)[n].top          = form->area.top;
890         (*list)[n].right        = form->area.right;
891         (*list)[n].bottom       = form->area.bottom;
892
893         DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
894                 update ? "updated" : "added", form->form_name));
895
896         return True;
897 }
898
899 /****************************************************************************
900  Delete a named form struct.
901 ****************************************************************************/
902
903 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
904 {
905         char *key = NULL;
906         int n=0;
907
908         *ret = WERR_OK;
909
910         for (n=0; n<*count; n++) {
911                 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
912                         DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
913                         break;
914                 }
915         }
916
917         if (n == *count) {
918                 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
919                 *ret = WERR_INVALID_FORM_NAME;
920                 return False;
921         }
922
923         if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
924                 *ret = WERR_NOMEM;
925                 return false;
926         }
927         if (tdb_delete_bystring(tdb_forms, key) != 0) {
928                 SAFE_FREE(key);
929                 *ret = WERR_NOMEM;
930                 return False;
931         }
932         SAFE_FREE(key);
933         return true;
934 }
935
936 /****************************************************************************
937  Update a form struct.
938 ****************************************************************************/
939
940 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
941 {
942         int n=0;
943
944         DEBUG(106, ("[%s]\n", form->form_name));
945         for (n=0; n<count; n++) {
946                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
947                 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
948                         break;
949         }
950
951         if (n==count) return;
952
953         (*list)[n].flag         = form->flags;
954         (*list)[n].width        = form->size.width;
955         (*list)[n].length       = form->size.height;
956         (*list)[n].left         = form->area.left;
957         (*list)[n].top          = form->area.top;
958         (*list)[n].right        = form->area.right;
959         (*list)[n].bottom       = form->area.bottom;
960 }
961
962 /****************************************************************************
963  Get the nt drivers list.
964  Traverse the database and look-up the matching names.
965 ****************************************************************************/
966 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
967 {
968         int total=0;
969         const char *short_archi;
970         char *key = NULL;
971         TDB_DATA kbuf, newkey;
972
973         short_archi = get_short_archi(architecture);
974         if (!short_archi) {
975                 return 0;
976         }
977
978         if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
979                                 short_archi, version) < 0) {
980                 return 0;
981         }
982
983         for (kbuf = tdb_firstkey(tdb_drivers);
984              kbuf.dptr;
985              newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
986
987                 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
988                         continue;
989
990                 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
991                         DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
992                         SAFE_FREE(key);
993                         return -1;
994                 }
995
996                 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
997                 total++;
998         }
999
1000         SAFE_FREE(key);
1001         return(total);
1002 }
1003
1004 /****************************************************************************
1005  Function to do the mapping between the long architecture name and
1006  the short one.
1007 ****************************************************************************/
1008
1009 const char *get_short_archi(const char *long_archi)
1010 {
1011         int i=-1;
1012
1013         DEBUG(107,("Getting architecture dependant directory\n"));
1014         do {
1015                 i++;
1016         } while ( (archi_table[i].long_archi!=NULL ) &&
1017                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
1018
1019         if (archi_table[i].long_archi==NULL) {
1020                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1021                 return NULL;
1022         }
1023
1024         /* this might be client code - but shouldn't this be an fstrcpy etc? */
1025
1026         DEBUGADD(108,("index: [%d]\n", i));
1027         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1028         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1029
1030         return archi_table[i].short_archi;
1031 }
1032
1033 /****************************************************************************
1034  Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1035  There are two case to be covered here: PE (Portable Executable) and NE (New
1036  Executable) files. Both files support the same INFO structure, but PE files
1037  store the signature in unicode, and NE files store it as !unicode.
1038  returns -1 on error, 1 on version info found, and 0 on no version info found.
1039 ****************************************************************************/
1040
1041 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1042 {
1043         int     i;
1044         char    *buf = NULL;
1045         ssize_t byte_count;
1046
1047         if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1048                 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1049                                 fname, DOS_HEADER_SIZE));
1050                 goto error_exit;
1051         }
1052
1053         if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1054                 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1055                          fname, (unsigned long)byte_count));
1056                 goto no_version_info;
1057         }
1058
1059         /* Is this really a DOS header? */
1060         if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1061                 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1062                                 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1063                 goto no_version_info;
1064         }
1065
1066         /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1067         if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1068                 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1069                                 fname, errno));
1070                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1071                 goto no_version_info;
1072         }
1073
1074         /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1075         if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1076                 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1077                          fname, (unsigned long)byte_count));
1078                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1079                 goto no_version_info;
1080         }
1081
1082         /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1083         if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1084                 unsigned int num_sections;
1085                 unsigned int section_table_bytes;
1086
1087                 /* Just skip over optional header to get to section table */
1088                 if (SMB_VFS_LSEEK(fsp,
1089                                 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1090                                 SEEK_CUR) == (SMB_OFF_T)-1) {
1091                         DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1092                                 fname, errno));
1093                         goto error_exit;
1094                 }
1095
1096                 /* get the section table */
1097                 num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1098                 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1099                 if (section_table_bytes == 0)
1100                         goto error_exit;
1101
1102                 SAFE_FREE(buf);
1103                 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1104                         DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1105                                         fname, section_table_bytes));
1106                         goto error_exit;
1107                 }
1108
1109                 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1110                         DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1111                                  fname, (unsigned long)byte_count));
1112                         goto error_exit;
1113                 }
1114
1115                 /* Iterate the section table looking for the resource section ".rsrc" */
1116                 for (i = 0; i < num_sections; i++) {
1117                         int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1118
1119                         if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1120                                 unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1121                                 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1122
1123                                 if (section_bytes == 0)
1124                                         goto error_exit;
1125
1126                                 SAFE_FREE(buf);
1127                                 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1128                                         DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1129                                                         fname, section_bytes));
1130                                         goto error_exit;
1131                                 }
1132
1133                                 /* Seek to the start of the .rsrc section info */
1134                                 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1135                                         DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1136                                                         fname, errno));
1137                                         goto error_exit;
1138                                 }
1139
1140                                 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1141                                         DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1142                                                  fname, (unsigned long)byte_count));
1143                                         goto error_exit;
1144                                 }
1145
1146                                 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1147                                         goto error_exit;
1148
1149                                 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1150                                         /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1151                                         if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1152                                                 /* Align to next long address */
1153                                                 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1154
1155                                                 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1156                                                         *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1157                                                         *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1158
1159                                                         DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1160                                                                           fname, *major, *minor,
1161                                                                           (*major>>16)&0xffff, *major&0xffff,
1162                                                                           (*minor>>16)&0xffff, *minor&0xffff));
1163                                                         SAFE_FREE(buf);
1164                                                         return 1;
1165                                                 }
1166                                         }
1167                                 }
1168                         }
1169                 }
1170
1171                 /* Version info not found, fall back to origin date/time */
1172                 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1173                 SAFE_FREE(buf);
1174                 return 0;
1175
1176         } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1177                 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1178                         DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1179                                         fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1180                         /* At this point, we assume the file is in error. It still could be somthing
1181                          * else besides a NE file, but it unlikely at this point. */
1182                         goto error_exit;
1183                 }
1184
1185                 /* Allocate a bit more space to speed up things */
1186                 SAFE_FREE(buf);
1187                 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1188                         DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
1189                                         fname, PE_HEADER_SIZE));
1190                         goto error_exit;
1191                 }
1192
1193                 /* This is a HACK! I got tired of trying to sort through the messy
1194                  * 'NE' file format. If anyone wants to clean this up please have at
1195                  * it, but this works. 'NE' files will eventually fade away. JRR */
1196                 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1197                         /* Cover case that should not occur in a well formed 'NE' .dll file */
1198                         if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1199
1200                         for(i=0; i<byte_count; i++) {
1201                                 /* Fast skip past data that can't possibly match */
1202                                 if (buf[i] != 'V') continue;
1203
1204                                 /* Potential match data crosses buf boundry, move it to beginning
1205                                  * of buf, and fill the buf with as much as it will hold. */
1206                                 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1207                                         int bc;
1208
1209                                         memcpy(buf, &buf[i], byte_count-i);
1210                                         if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1211                                                                    (byte_count-i))) < 0) {
1212
1213                                                 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1214                                                                  fname, errno));
1215                                                 goto error_exit;
1216                                         }
1217
1218                                         byte_count = bc + (byte_count - i);
1219                                         if (byte_count<VS_VERSION_INFO_SIZE) break;
1220
1221                                         i = 0;
1222                                 }
1223
1224                                 /* Check that the full signature string and the magic number that
1225                                  * follows exist (not a perfect solution, but the chances that this
1226                                  * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1227                                  * twice, as it is simpler to read the code. */
1228                                 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1229                                         /* Compute skip alignment to next long address */
1230                                         int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1231                                                                  sizeof(VS_SIGNATURE)) & 3;
1232                                         if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1233
1234                                         *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1235                                         *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1236                                         DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1237                                                           fname, *major, *minor,
1238                                                           (*major>>16)&0xffff, *major&0xffff,
1239                                                           (*minor>>16)&0xffff, *minor&0xffff));
1240                                         SAFE_FREE(buf);
1241                                         return 1;
1242                                 }
1243                         }
1244                 }
1245
1246                 /* Version info not found, fall back to origin date/time */
1247                 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1248                 SAFE_FREE(buf);
1249                 return 0;
1250
1251         } else
1252                 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1253                 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1254                                 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1255
1256         no_version_info:
1257                 SAFE_FREE(buf);
1258                 return 0;
1259
1260         error_exit:
1261                 SAFE_FREE(buf);
1262                 return -1;
1263 }
1264
1265 /****************************************************************************
1266 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1267 share one or more files. During the MS installation process files are checked
1268 to insure that only a newer version of a shared file is installed over an
1269 older version. There are several possibilities for this comparison. If there
1270 is no previous version, the new one is newer (obviously). If either file is
1271 missing the version info structure, compare the creation date (on Unix use
1272 the modification date). Otherwise chose the numerically larger version number.
1273 ****************************************************************************/
1274
1275 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1276 {
1277         bool use_version = true;
1278
1279         uint32 new_major;
1280         uint32 new_minor;
1281         time_t new_create_time;
1282
1283         uint32 old_major;
1284         uint32 old_minor;
1285         time_t old_create_time;
1286
1287         struct smb_filename *smb_fname = NULL;
1288         files_struct    *fsp = NULL;
1289         SMB_STRUCT_STAT st;
1290
1291         NTSTATUS status;
1292         int ret;
1293
1294         SET_STAT_INVALID(st);
1295         new_create_time = (time_t)0;
1296         old_create_time = (time_t)0;
1297
1298         /* Get file version info (if available) for previous file (if it exists) */
1299         status = driver_unix_convert(conn, old_file, &smb_fname);
1300         if (!NT_STATUS_IS_OK(status)) {
1301                 goto error_exit;
1302         }
1303
1304         status = SMB_VFS_CREATE_FILE(
1305                 conn,                                   /* conn */
1306                 NULL,                                   /* req */
1307                 0,                                      /* root_dir_fid */
1308                 smb_fname,                              /* fname */
1309                 FILE_GENERIC_READ,                      /* access_mask */
1310                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1311                 FILE_OPEN,                              /* create_disposition*/
1312                 0,                                      /* create_options */
1313                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1314                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1315                 0,                                      /* allocation_size */
1316                 0,                                      /* private_flags */
1317                 NULL,                                   /* sd */
1318                 NULL,                                   /* ea_list */
1319                 &fsp,                                   /* result */
1320                 NULL);                                  /* pinfo */
1321
1322         if (!NT_STATUS_IS_OK(status)) {
1323                 /* Old file not found, so by definition new file is in fact newer */
1324                 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1325                           "errno = %d\n", smb_fname_str_dbg(smb_fname),
1326                           errno));
1327                 ret = 1;
1328                 goto done;
1329
1330         } else {
1331                 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1332                 if (ret == -1) {
1333                         goto error_exit;
1334                 }
1335
1336                 if (!ret) {
1337                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1338                                          old_file));
1339                         use_version = false;
1340                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1341                                  goto error_exit;
1342                         }
1343                         old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1344                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1345                                 (long)old_create_time));
1346                 }
1347         }
1348         close_file(NULL, fsp, NORMAL_CLOSE);
1349         fsp = NULL;
1350
1351         /* Get file version info (if available) for new file */
1352         status = driver_unix_convert(conn, new_file, &smb_fname);
1353         if (!NT_STATUS_IS_OK(status)) {
1354                 goto error_exit;
1355         }
1356
1357         status = SMB_VFS_CREATE_FILE(
1358                 conn,                                   /* conn */
1359                 NULL,                                   /* req */
1360                 0,                                      /* root_dir_fid */
1361                 smb_fname,                              /* fname */
1362                 FILE_GENERIC_READ,                      /* access_mask */
1363                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1364                 FILE_OPEN,                              /* create_disposition*/
1365                 0,                                      /* create_options */
1366                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1367                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1368                 0,                                      /* allocation_size */
1369                 0,                                      /* private_flags */
1370                 NULL,                                   /* sd */
1371                 NULL,                                   /* ea_list */
1372                 &fsp,                                   /* result */
1373                 NULL);                                  /* pinfo */
1374
1375         if (!NT_STATUS_IS_OK(status)) {
1376                 /* New file not found, this shouldn't occur if the caller did its job */
1377                 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1378                          "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1379                 goto error_exit;
1380
1381         } else {
1382                 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1383                 if (ret == -1) {
1384                         goto error_exit;
1385                 }
1386
1387                 if (!ret) {
1388                         DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1389                                          new_file));
1390                         use_version = false;
1391                         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1392                                 goto error_exit;
1393                         }
1394                         new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1395                         DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1396                                 (long)new_create_time));
1397                 }
1398         }
1399         close_file(NULL, fsp, NORMAL_CLOSE);
1400         fsp = NULL;
1401
1402         if (use_version && (new_major != old_major || new_minor != old_minor)) {
1403                 /* Compare versions and choose the larger version number */
1404                 if (new_major > old_major ||
1405                         (new_major == old_major && new_minor > old_minor)) {
1406
1407                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1408                         ret = 1;
1409                         goto done;
1410                 }
1411                 else {
1412                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1413                         ret = 0;
1414                         goto done;
1415                 }
1416
1417         } else {
1418                 /* Compare modification time/dates and choose the newest time/date */
1419                 if (new_create_time > old_create_time) {
1420                         DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1421                         ret = 1;
1422                         goto done;
1423                 }
1424                 else {
1425                         DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1426                         ret = 0;
1427                         goto done;
1428                 }
1429         }
1430
1431  error_exit:
1432         if(fsp)
1433                 close_file(NULL, fsp, NORMAL_CLOSE);
1434         ret = -1;
1435  done:
1436         TALLOC_FREE(smb_fname);
1437         return ret;
1438 }
1439
1440 /****************************************************************************
1441 Determine the correct cVersion associated with an architecture and driver
1442 ****************************************************************************/
1443 static uint32 get_correct_cversion(struct pipes_struct *p,
1444                                    const char *architecture,
1445                                    const char *driverpath_in,
1446                                    WERROR *perr)
1447 {
1448         int               cversion;
1449         NTSTATUS          nt_status;
1450         struct smb_filename *smb_fname = NULL;
1451         char *driverpath = NULL;
1452         files_struct      *fsp = NULL;
1453         connection_struct *conn = NULL;
1454         NTSTATUS status;
1455         char *oldcwd;
1456         fstring printdollar;
1457         int printdollar_snum;
1458
1459         *perr = WERR_INVALID_PARAM;
1460
1461         /* If architecture is Windows 95/98/ME, the version is always 0. */
1462         if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1463                 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1464                 *perr = WERR_OK;
1465                 return 0;
1466         }
1467
1468         /* If architecture is Windows x64, the version is always 3. */
1469         if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1470                 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1471                 *perr = WERR_OK;
1472                 return 3;
1473         }
1474
1475         fstrcpy(printdollar, "print$");
1476
1477         printdollar_snum = find_service(printdollar);
1478         if (printdollar_snum == -1) {
1479                 *perr = WERR_NO_SUCH_SHARE;
1480                 return -1;
1481         }
1482
1483         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1484                                        lp_pathname(printdollar_snum),
1485                                        p->server_info, &oldcwd);
1486         if (!NT_STATUS_IS_OK(nt_status)) {
1487                 DEBUG(0,("get_correct_cversion: create_conn_struct "
1488                          "returned %s\n", nt_errstr(nt_status)));
1489                 *perr = ntstatus_to_werror(nt_status);
1490                 return -1;
1491         }
1492
1493         /* Open the driver file (Portable Executable format) and determine the
1494          * deriver the cversion. */
1495         driverpath = talloc_asprintf(talloc_tos(),
1496                                         "%s/%s",
1497                                         architecture,
1498                                         driverpath_in);
1499         if (!driverpath) {
1500                 *perr = WERR_NOMEM;
1501                 goto error_exit;
1502         }
1503
1504         nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1505         if (!NT_STATUS_IS_OK(nt_status)) {
1506                 *perr = ntstatus_to_werror(nt_status);
1507                 goto error_exit;
1508         }
1509
1510         nt_status = vfs_file_exist(conn, smb_fname);
1511         if (!NT_STATUS_IS_OK(nt_status)) {
1512                 *perr = WERR_BADFILE;
1513                 goto error_exit;
1514         }
1515
1516         status = SMB_VFS_CREATE_FILE(
1517                 conn,                                   /* conn */
1518                 NULL,                                   /* req */
1519                 0,                                      /* root_dir_fid */
1520                 smb_fname,                              /* fname */
1521                 FILE_GENERIC_READ,                      /* access_mask */
1522                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
1523                 FILE_OPEN,                              /* create_disposition*/
1524                 0,                                      /* create_options */
1525                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
1526                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
1527                 0,                                      /* private_flags */
1528                 0,                                      /* allocation_size */
1529                 NULL,                                   /* sd */
1530                 NULL,                                   /* ea_list */
1531                 &fsp,                                   /* result */
1532                 NULL);                                  /* pinfo */
1533
1534         if (!NT_STATUS_IS_OK(status)) {
1535                 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1536                          "%d\n", smb_fname_str_dbg(smb_fname), errno));
1537                 *perr = WERR_ACCESS_DENIED;
1538                 goto error_exit;
1539         } else {
1540                 uint32 major;
1541                 uint32 minor;
1542                 int    ret;
1543
1544                 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1545                 if (ret == -1) goto error_exit;
1546
1547                 if (!ret) {
1548                         DEBUG(6,("get_correct_cversion: Version info not "
1549                                  "found [%s]\n",
1550                                  smb_fname_str_dbg(smb_fname)));
1551                         goto error_exit;
1552                 }
1553
1554                 /*
1555                  * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1556                  * for more details. Version in this case is not just the version of the
1557                  * file, but the version in the sense of kernal mode (2) vs. user mode
1558                  * (3) drivers. Other bits of the version fields are the version info.
1559                  * JRR 010716
1560                 */
1561                 cversion = major & 0x0000ffff;
1562                 switch (cversion) {
1563                         case 2: /* WinNT drivers */
1564                         case 3: /* Win2K drivers */
1565                                 break;
1566
1567                         default:
1568                                 DEBUG(6,("get_correct_cversion: cversion "
1569                                          "invalid [%s]  cversion = %d\n",
1570                                          smb_fname_str_dbg(smb_fname),
1571                                          cversion));
1572                                 goto error_exit;
1573                 }
1574
1575                 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1576                           " = 0x%x  minor = 0x%x\n",
1577                           smb_fname_str_dbg(smb_fname), major, minor));
1578         }
1579
1580         DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1581                   smb_fname_str_dbg(smb_fname), cversion));
1582
1583         goto done;
1584
1585  error_exit:
1586         cversion = -1;
1587  done:
1588         TALLOC_FREE(smb_fname);
1589         if (fsp != NULL) {
1590                 close_file(NULL, fsp, NORMAL_CLOSE);
1591         }
1592         if (conn != NULL) {
1593                 vfs_ChDir(conn, oldcwd);
1594                 conn_free(conn);
1595         }
1596         if (cversion != -1) {
1597                 *perr = WERR_OK;
1598         }
1599         return cversion;
1600 }
1601
1602 /****************************************************************************
1603 ****************************************************************************/
1604
1605 #define strip_driver_path(_mem_ctx, _element) do { \
1606         if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1607                 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1608                 W_ERROR_HAVE_NO_MEMORY((_element)); \
1609         } \
1610 } while (0);
1611
1612 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1613                                            struct pipes_struct *rpc_pipe,
1614                                            const char *architecture,
1615                                            const char **driver_path,
1616                                            const char **data_file,
1617                                            const char **config_file,
1618                                            const char **help_file,
1619                                            struct spoolss_StringArray *dependent_files,
1620                                            uint32_t *version)
1621 {
1622         const char *short_architecture;
1623         int i;
1624         WERROR err;
1625         char *_p;
1626
1627         if (!*driver_path || !*data_file || !*config_file) {
1628                 return WERR_INVALID_PARAM;
1629         }
1630
1631         /* clean up the driver name.
1632          * we can get .\driver.dll
1633          * or worse c:\windows\system\driver.dll !
1634          */
1635         /* using an intermediate string to not have overlaping memcpy()'s */
1636
1637         strip_driver_path(mem_ctx, *driver_path);
1638         strip_driver_path(mem_ctx, *data_file);
1639         strip_driver_path(mem_ctx, *config_file);
1640         if (help_file) {
1641                 strip_driver_path(mem_ctx, *help_file);
1642         }
1643
1644         if (dependent_files && dependent_files->string) {
1645                 for (i=0; dependent_files->string[i]; i++) {
1646                         strip_driver_path(mem_ctx, dependent_files->string[i]);
1647                 }
1648         }
1649
1650         short_architecture = get_short_archi(architecture);
1651         if (!short_architecture) {
1652                 return WERR_UNKNOWN_PRINTER_DRIVER;
1653         }
1654
1655         /* jfm:7/16/2000 the client always sends the cversion=0.
1656          * The server should check which version the driver is by reading
1657          * the PE header of driver->driverpath.
1658          *
1659          * For Windows 95/98 the version is 0 (so the value sent is correct)
1660          * For Windows NT (the architecture doesn't matter)
1661          *      NT 3.1: cversion=0
1662          *      NT 3.5/3.51: cversion=1
1663          *      NT 4: cversion=2
1664          *      NT2K: cversion=3
1665          */
1666
1667         *version = get_correct_cversion(rpc_pipe, short_architecture,
1668                                         *driver_path, &err);
1669         if (*version == -1) {
1670                 return err;
1671         }
1672
1673         return WERR_OK;
1674 }
1675
1676 /****************************************************************************
1677 ****************************************************************************/
1678
1679 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1680                               struct pipes_struct *rpc_pipe,
1681                               struct spoolss_AddDriverInfoCtr *r)
1682 {
1683         switch (r->level) {
1684         case 3:
1685                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1686                                                     r->info.info3->architecture,
1687                                                     &r->info.info3->driver_path,
1688                                                     &r->info.info3->data_file,
1689                                                     &r->info.info3->config_file,
1690                                                     &r->info.info3->help_file,
1691                                                     r->info.info3->dependent_files,
1692                                                     &r->info.info3->version);
1693         case 6:
1694                 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1695                                                     r->info.info6->architecture,
1696                                                     &r->info.info6->driver_path,
1697                                                     &r->info.info6->data_file,
1698                                                     &r->info.info6->config_file,
1699                                                     &r->info.info6->help_file,
1700                                                     r->info.info6->dependent_files,
1701                                                     &r->info.info6->version);
1702         default:
1703                 return WERR_NOT_SUPPORTED;
1704         }
1705 }
1706
1707 /****************************************************************************
1708  This function sucks and should be replaced. JRA.
1709 ****************************************************************************/
1710
1711 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1712                                       const struct spoolss_AddDriverInfo6 *src)
1713 {
1714         dst->version            = src->version;
1715
1716         dst->driver_name        = src->driver_name;
1717         dst->architecture       = src->architecture;
1718         dst->driver_path        = src->driver_path;
1719         dst->data_file          = src->data_file;
1720         dst->config_file        = src->config_file;
1721         dst->help_file          = src->help_file;
1722         dst->monitor_name       = src->monitor_name;
1723         dst->default_datatype   = src->default_datatype;
1724         dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1725         dst->dependent_files    = src->dependent_files;
1726 }
1727
1728 /****************************************************************************
1729  This function sucks and should be replaced. JRA.
1730 ****************************************************************************/
1731
1732 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1733                                       struct spoolss_AddDriverInfo3 *dst,
1734                                       const struct spoolss_DriverInfo8 *src)
1735 {
1736         dst->version            = src->version;
1737         dst->driver_name        = src->driver_name;
1738         dst->architecture       = src->architecture;
1739         dst->driver_path        = src->driver_path;
1740         dst->data_file          = src->data_file;
1741         dst->config_file        = src->config_file;
1742         dst->help_file          = src->help_file;
1743         dst->monitor_name       = src->monitor_name;
1744         dst->default_datatype   = src->default_datatype;
1745         if (src->dependent_files) {
1746                 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1747                 if (!dst->dependent_files) return;
1748                 dst->dependent_files->string = src->dependent_files;
1749         } else {
1750                 dst->dependent_files = NULL;
1751         }
1752 }
1753
1754 /****************************************************************************
1755 ****************************************************************************/
1756
1757 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1758                                                 connection_struct *conn,
1759                                                 const char *driver_file,
1760                                                 const char *short_architecture,
1761                                                 uint32_t driver_version,
1762                                                 uint32_t version)
1763 {
1764         struct smb_filename *smb_fname_old = NULL;
1765         struct smb_filename *smb_fname_new = NULL;
1766         char *old_name = NULL;
1767         char *new_name = NULL;
1768         NTSTATUS status;
1769         WERROR ret;
1770
1771         old_name = talloc_asprintf(mem_ctx, "%s/%s",
1772                                    short_architecture, driver_file);
1773         W_ERROR_HAVE_NO_MEMORY(old_name);
1774
1775         new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1776                                    short_architecture, driver_version, driver_file);
1777         if (new_name == NULL) {
1778                 TALLOC_FREE(old_name);
1779                 return WERR_NOMEM;
1780         }
1781
1782         if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1783
1784                 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1785                 if (!NT_STATUS_IS_OK(status)) {
1786                         ret = WERR_NOMEM;
1787                         goto out;
1788                 }
1789
1790                 /* Setup a synthetic smb_filename struct */
1791                 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1792                 if (!smb_fname_new) {
1793                         ret = WERR_NOMEM;
1794                         goto out;
1795                 }
1796
1797                 smb_fname_new->base_name = new_name;
1798
1799                 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1800                           "'%s'\n", smb_fname_old->base_name,
1801                           smb_fname_new->base_name));
1802
1803                 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1804                                    OPENX_FILE_EXISTS_TRUNCATE |
1805                                    OPENX_FILE_CREATE_IF_NOT_EXIST,
1806                                    0, false);
1807
1808                 if (!NT_STATUS_IS_OK(status)) {
1809                         DEBUG(0,("move_driver_file_to_download_area: Unable "
1810                                  "to rename [%s] to [%s]: %s\n",
1811                                  smb_fname_old->base_name, new_name,
1812                                  nt_errstr(status)));
1813                         ret = WERR_ACCESS_DENIED;
1814                         goto out;
1815                 }
1816         }
1817
1818         ret = WERR_OK;
1819  out:
1820         TALLOC_FREE(smb_fname_old);
1821         TALLOC_FREE(smb_fname_new);
1822         return ret;
1823 }
1824
1825 WERROR move_driver_to_download_area(struct pipes_struct *p,
1826                                     struct spoolss_AddDriverInfoCtr *r,
1827                                     WERROR *perr)
1828 {
1829         struct spoolss_AddDriverInfo3 *driver;
1830         struct spoolss_AddDriverInfo3 converted_driver;
1831         const char *short_architecture;
1832         struct smb_filename *smb_dname = NULL;
1833         char *new_dir = NULL;
1834         connection_struct *conn = NULL;
1835         NTSTATUS nt_status;
1836         int i;
1837         TALLOC_CTX *ctx = talloc_tos();
1838         int ver = 0;
1839         char *oldcwd;
1840         fstring printdollar;
1841         int printdollar_snum;
1842
1843         *perr = WERR_OK;
1844
1845         switch (r->level) {
1846         case 3:
1847                 driver = r->info.info3;
1848                 break;
1849         case 6:
1850                 convert_level_6_to_level3(&converted_driver, r->info.info6);
1851                 driver = &converted_driver;
1852                 break;
1853         default:
1854                 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1855                 return WERR_UNKNOWN_LEVEL;
1856         }
1857
1858         short_architecture = get_short_archi(driver->architecture);
1859         if (!short_architecture) {
1860                 return WERR_UNKNOWN_PRINTER_DRIVER;
1861         }
1862
1863         fstrcpy(printdollar, "print$");
1864
1865         printdollar_snum = find_service(printdollar);
1866         if (printdollar_snum == -1) {
1867                 *perr = WERR_NO_SUCH_SHARE;
1868                 return WERR_NO_SUCH_SHARE;
1869         }
1870
1871         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1872                                        lp_pathname(printdollar_snum),
1873                                        p->server_info, &oldcwd);
1874         if (!NT_STATUS_IS_OK(nt_status)) {
1875                 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1876                          "returned %s\n", nt_errstr(nt_status)));
1877                 *perr = ntstatus_to_werror(nt_status);
1878                 return *perr;
1879         }
1880
1881         new_dir = talloc_asprintf(ctx,
1882                                 "%s/%d",
1883                                 short_architecture,
1884                                 driver->version);
1885         if (!new_dir) {
1886                 *perr = WERR_NOMEM;
1887                 goto err_exit;
1888         }
1889         nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1890         if (!NT_STATUS_IS_OK(nt_status)) {
1891                 *perr = WERR_NOMEM;
1892                 goto err_exit;
1893         }
1894
1895         DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1896
1897         create_directory(conn, NULL, smb_dname);
1898
1899         /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1900          * listed for this driver which has already been moved, skip it (note:
1901          * drivers may list the same file name several times. Then check if the
1902          * file already exists in archi\version\, if so, check that the version
1903          * info (or time stamps if version info is unavailable) is newer (or the
1904          * date is later). If it is, move it to archi\version\filexxx.yyy.
1905          * Otherwise, delete the file.
1906          *
1907          * If a file is not moved to archi\version\ because of an error, all the
1908          * rest of the 'unmoved' driver files are removed from archi\. If one or
1909          * more of the driver's files was already moved to archi\version\, it
1910          * potentially leaves the driver in a partially updated state. Version
1911          * trauma will most likely occur if an client attempts to use any printer
1912          * bound to the driver. Perhaps a rewrite to make sure the moves can be
1913          * done is appropriate... later JRR
1914          */
1915
1916         DEBUG(5,("Moving files now !\n"));
1917
1918         if (driver->driver_path && strlen(driver->driver_path)) {
1919
1920                 *perr = move_driver_file_to_download_area(ctx,
1921                                                           conn,
1922                                                           driver->driver_path,
1923                                                           short_architecture,
1924                                                           driver->version,
1925                                                           ver);
1926                 if (!W_ERROR_IS_OK(*perr)) {
1927                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1928                                 ver = -1;
1929                         }
1930                         goto err_exit;
1931                 }
1932         }
1933
1934         if (driver->data_file && strlen(driver->data_file)) {
1935                 if (!strequal(driver->data_file, driver->driver_path)) {
1936
1937                         *perr = move_driver_file_to_download_area(ctx,
1938                                                                   conn,
1939                                                                   driver->data_file,
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         }
1951
1952         if (driver->config_file && strlen(driver->config_file)) {
1953                 if (!strequal(driver->config_file, driver->driver_path) &&
1954                     !strequal(driver->config_file, driver->data_file)) {
1955
1956                         *perr = move_driver_file_to_download_area(ctx,
1957                                                                   conn,
1958                                                                   driver->config_file,
1959                                                                   short_architecture,
1960                                                                   driver->version,
1961                                                                   ver);
1962                         if (!W_ERROR_IS_OK(*perr)) {
1963                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1964                                         ver = -1;
1965                                 }
1966                                 goto err_exit;
1967                         }
1968                 }
1969         }
1970
1971         if (driver->help_file && strlen(driver->help_file)) {
1972                 if (!strequal(driver->help_file, driver->driver_path) &&
1973                     !strequal(driver->help_file, driver->data_file) &&
1974                     !strequal(driver->help_file, driver->config_file)) {
1975
1976                         *perr = move_driver_file_to_download_area(ctx,
1977                                                                   conn,
1978                                                                   driver->help_file,
1979                                                                   short_architecture,
1980                                                                   driver->version,
1981                                                                   ver);
1982                         if (!W_ERROR_IS_OK(*perr)) {
1983                                 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1984                                         ver = -1;
1985                                 }
1986                                 goto err_exit;
1987                         }
1988                 }
1989         }
1990
1991         if (driver->dependent_files && driver->dependent_files->string) {
1992                 for (i=0; driver->dependent_files->string[i]; i++) {
1993                         if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1994                             !strequal(driver->dependent_files->string[i], driver->data_file) &&
1995                             !strequal(driver->dependent_files->string[i], driver->config_file) &&
1996                             !strequal(driver->dependent_files->string[i], driver->help_file)) {
1997                                 int j;
1998                                 for (j=0; j < i; j++) {
1999                                         if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2000                                                 goto NextDriver;
2001                                         }
2002                                 }
2003
2004                                 *perr = move_driver_file_to_download_area(ctx,
2005                                                                           conn,
2006                                                                           driver->dependent_files->string[i],
2007                                                                           short_architecture,
2008                                                                           driver->version,
2009                                                                           ver);
2010                                 if (!W_ERROR_IS_OK(*perr)) {
2011                                         if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2012                                                 ver = -1;
2013                                         }
2014                                         goto err_exit;
2015                                 }
2016                         }
2017                 NextDriver: ;
2018                 }
2019         }
2020
2021   err_exit:
2022         TALLOC_FREE(smb_dname);
2023
2024         if (conn != NULL) {
2025                 vfs_ChDir(conn, oldcwd);
2026                 conn_free(conn);
2027         }
2028
2029         if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2030                 return WERR_OK;
2031         }
2032         if (ver == -1) {
2033                 return WERR_UNKNOWN_PRINTER_DRIVER;
2034         }
2035         return (*perr);
2036 }
2037
2038 /****************************************************************************
2039 ****************************************************************************/
2040
2041 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2042 {
2043         TALLOC_CTX *ctx = talloc_tos();
2044         int len, buflen;
2045         const char *architecture;
2046         char *directory = NULL;
2047         char *key = NULL;
2048         uint8 *buf;
2049         int i, ret;
2050         TDB_DATA dbuf;
2051
2052         architecture = get_short_archi(driver->architecture);
2053         if (!architecture) {
2054                 return (uint32)-1;
2055         }
2056
2057         /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2058          * \\server is added in the rpc server layer.
2059          * It does make sense to NOT store the server's name in the printer TDB.
2060          */
2061
2062         directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2063                         architecture, driver->version);
2064         if (!directory) {
2065                 return (uint32)-1;
2066         }
2067
2068 #define gen_full_driver_unc_path(ctx, directory, file) \
2069         do { \
2070                 if (file && strlen(file)) { \
2071                         file = talloc_asprintf(ctx, "%s%s", directory, file); \
2072                 } else { \
2073                         file = talloc_strdup(ctx, ""); \
2074                 } \
2075                 if (!file) { \
2076                         return (uint32_t)-1; \
2077                 } \
2078         } while (0);
2079
2080         /* .inf files do not always list a file for each of the four standard files.
2081          * Don't prepend a path to a null filename, or client claims:
2082          *   "The server on which the printer resides does not have a suitable
2083          *   <printer driver name> printer driver installed. Click OK if you
2084          *   wish to install the driver on your local machine."
2085          */
2086
2087         gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2088         gen_full_driver_unc_path(ctx, directory, driver->data_file);
2089         gen_full_driver_unc_path(ctx, directory, driver->config_file);
2090         gen_full_driver_unc_path(ctx, directory, driver->help_file);
2091
2092         if (driver->dependent_files && driver->dependent_files->string) {
2093                 for (i=0; driver->dependent_files->string[i]; i++) {
2094                         gen_full_driver_unc_path(ctx, directory,
2095                                 driver->dependent_files->string[i]);
2096                 }
2097         }
2098
2099         key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2100                         architecture, driver->version, driver->driver_name);
2101         if (!key) {
2102                 return (uint32)-1;
2103         }
2104
2105         DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2106
2107         buf = NULL;
2108         len = buflen = 0;
2109
2110  again:
2111         len = 0;
2112         len += tdb_pack(buf+len, buflen-len, "dffffffff",
2113                         driver->version,
2114                         driver->driver_name,
2115                         driver->architecture,
2116                         driver->driver_path,
2117                         driver->data_file,
2118                         driver->config_file,
2119                         driver->help_file,
2120                         driver->monitor_name ? driver->monitor_name : "",
2121                         driver->default_datatype ? driver->default_datatype : "");
2122
2123         if (driver->dependent_files && driver->dependent_files->string) {
2124                 for (i=0; driver->dependent_files->string[i]; i++) {
2125                         len += tdb_pack(buf+len, buflen-len, "f",
2126                                         driver->dependent_files->string[i]);
2127                 }
2128         }
2129
2130         if (len != buflen) {
2131                 buf = (uint8 *)SMB_REALLOC(buf, len);
2132                 if (!buf) {
2133                         DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2134                         ret = -1;
2135                         goto done;
2136                 }
2137                 buflen = len;
2138                 goto again;
2139         }
2140
2141         dbuf.dptr = buf;
2142         dbuf.dsize = len;
2143
2144         ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2145
2146 done:
2147         if (ret)
2148                 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2149
2150         SAFE_FREE(buf);
2151         return ret;
2152 }
2153
2154 /****************************************************************************
2155 ****************************************************************************/
2156
2157 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2158 {
2159         TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2160         struct spoolss_AddDriverInfo3 info3;
2161         uint32_t ret;
2162
2163         convert_level_8_to_level3(mem_ctx, &info3, driver);
2164
2165         ret = add_a_printer_driver_3(&info3);
2166         talloc_free(mem_ctx);
2167
2168         return ret;
2169 }
2170
2171 /****************************************************************************
2172 ****************************************************************************/
2173
2174 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2175                                              struct spoolss_DriverInfo3 *info,
2176                                              const char *driver, const char *arch)
2177 {
2178         info->driver_name = talloc_strdup(mem_ctx, driver);
2179         if (!info->driver_name) {
2180                 return WERR_NOMEM;
2181         }
2182
2183         info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2184         if (!info->default_datatype) {
2185                 return WERR_NOMEM;
2186         }
2187
2188         info->driver_path = talloc_strdup(mem_ctx, "");
2189         info->data_file = talloc_strdup(mem_ctx, "");
2190         info->config_file = talloc_strdup(mem_ctx, "");
2191         info->help_file = talloc_strdup(mem_ctx, "");
2192         if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2193                 return WERR_NOMEM;
2194         }
2195
2196         return WERR_OK;
2197 }
2198
2199 /****************************************************************************
2200 ****************************************************************************/
2201
2202 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2203                                      struct spoolss_DriverInfo3 *driver,
2204                                      const char *drivername, const char *arch,
2205                                      uint32_t version)
2206 {
2207         TDB_DATA dbuf;
2208         const char *architecture;
2209         int len = 0;
2210         int i;
2211         char *key = NULL;
2212         fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2213
2214         architecture = get_short_archi(arch);
2215         if ( !architecture ) {
2216                 return WERR_UNKNOWN_PRINTER_DRIVER;
2217         }
2218
2219         /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2220
2221         if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2222                 version = 0;
2223
2224         DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2225
2226         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2227                                 architecture, version, drivername) < 0) {
2228                 return WERR_NOMEM;
2229         }
2230
2231         dbuf = tdb_fetch_bystring(tdb_drivers, key);
2232         if (!dbuf.dptr) {
2233                 SAFE_FREE(key);
2234                 return WERR_UNKNOWN_PRINTER_DRIVER;
2235         }
2236
2237         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2238                           &driver->version,
2239                           name,
2240                           environment,
2241                           driverpath,
2242                           datafile,
2243                           configfile,
2244                           helpfile,
2245                           monitorname,
2246                           defaultdatatype);
2247
2248         driver->driver_name     = talloc_strdup(mem_ctx, name);
2249         driver->architecture    = talloc_strdup(mem_ctx, environment);
2250         driver->driver_path     = talloc_strdup(mem_ctx, driverpath);
2251         driver->data_file       = talloc_strdup(mem_ctx, datafile);
2252         driver->config_file     = talloc_strdup(mem_ctx, configfile);
2253         driver->help_file       = talloc_strdup(mem_ctx, helpfile);
2254         driver->monitor_name    = talloc_strdup(mem_ctx, monitorname);
2255         driver->default_datatype        = talloc_strdup(mem_ctx, defaultdatatype);
2256
2257         i=0;
2258
2259         while (len < dbuf.dsize) {
2260
2261                 fstring file;
2262
2263                 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2264                 if (!driver->dependent_files ) {
2265                         DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2266                         break;
2267                 }
2268
2269                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2270                                   &file);
2271
2272                 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2273
2274                 i++;
2275         }
2276
2277         if (driver->dependent_files)
2278                 driver->dependent_files[i] = NULL;
2279
2280         SAFE_FREE(dbuf.dptr);
2281         SAFE_FREE(key);
2282
2283         if (len != dbuf.dsize) {
2284                 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2285         }
2286
2287         return WERR_OK;
2288 }
2289
2290 /****************************************************************************
2291 ****************************************************************************/
2292 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2293 {
2294         int len = 0;
2295
2296         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2297
2298         if (!nt_devmode)
2299                 return len;
2300
2301         len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2302                         nt_devmode->devicename,
2303                         nt_devmode->formname,
2304
2305                         nt_devmode->specversion,
2306                         nt_devmode->driverversion,
2307                         nt_devmode->size,
2308                         nt_devmode->driverextra,
2309                         nt_devmode->orientation,
2310                         nt_devmode->papersize,
2311                         nt_devmode->paperlength,
2312                         nt_devmode->paperwidth,
2313                         nt_devmode->scale,
2314                         nt_devmode->copies,
2315                         nt_devmode->defaultsource,
2316                         nt_devmode->printquality,
2317                         nt_devmode->color,
2318                         nt_devmode->duplex,
2319                         nt_devmode->yresolution,
2320                         nt_devmode->ttoption,
2321                         nt_devmode->collate,
2322                         nt_devmode->logpixels,
2323
2324                         nt_devmode->fields,
2325                         nt_devmode->bitsperpel,
2326                         nt_devmode->pelswidth,
2327                         nt_devmode->pelsheight,
2328                         nt_devmode->displayflags,
2329                         nt_devmode->displayfrequency,
2330                         nt_devmode->icmmethod,
2331                         nt_devmode->icmintent,
2332                         nt_devmode->mediatype,
2333                         nt_devmode->dithertype,
2334                         nt_devmode->reserved1,
2335                         nt_devmode->reserved2,
2336                         nt_devmode->panningwidth,
2337                         nt_devmode->panningheight,
2338                         nt_devmode->nt_dev_private);
2339
2340         if (nt_devmode->nt_dev_private) {
2341                 len += tdb_pack(buf+len, buflen-len, "B",
2342                                 nt_devmode->driverextra,
2343                                 nt_devmode->nt_dev_private);
2344         }
2345
2346         DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2347
2348         return len;
2349 }
2350
2351 /****************************************************************************
2352  Pack all values in all printer keys
2353  ***************************************************************************/
2354
2355 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2356 {
2357         int             len = 0;
2358         int             i, j;
2359         struct regval_blob      *val;
2360         struct regval_ctr       *val_ctr;
2361         char *path = NULL;
2362         int             num_values;
2363
2364         if ( !data )
2365                 return 0;
2366
2367         /* loop over all keys */
2368
2369         for ( i=0; i<data->num_keys; i++ ) {
2370                 val_ctr = data->keys[i].values;
2371                 num_values = regval_ctr_numvals( val_ctr );
2372
2373                 /* pack the keyname followed by a empty value */
2374
2375                 len += tdb_pack(buf+len, buflen-len, "pPdB",
2376                                 &data->keys[i].name,
2377                                 data->keys[i].name,
2378                                 REG_NONE,
2379                                 0,
2380                                 NULL);
2381
2382                 /* now loop over all values */
2383
2384                 for ( j=0; j<num_values; j++ ) {
2385                         /* pathname should be stored as <key>\<value> */
2386
2387                         val = regval_ctr_specific_value( val_ctr, j );
2388                         if (asprintf(&path, "%s\\%s",
2389                                         data->keys[i].name,
2390                                         regval_name(val)) < 0) {
2391                                 return -1;
2392                         }
2393
2394                         len += tdb_pack(buf+len, buflen-len, "pPdB",
2395                                         val,
2396                                         path,
2397                                         regval_type(val),
2398                                         regval_size(val),
2399                                         regval_data_p(val) );
2400
2401                         DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2402                         SAFE_FREE(path);
2403                 }
2404
2405         }
2406
2407         /* terminator */
2408
2409         len += tdb_pack(buf+len, buflen-len, "p", NULL);
2410
2411         return len;
2412 }
2413
2414
2415 /****************************************************************************
2416  Delete a printer - this just deletes the printer info file, any open
2417  handles are not affected.
2418 ****************************************************************************/
2419
2420 uint32 del_a_printer(const char *sharename)
2421 {
2422         TDB_DATA kbuf;
2423         char *printdb_path = NULL;
2424         TALLOC_CTX *ctx = talloc_tos();
2425
2426         kbuf = make_printer_tdbkey(ctx, sharename);
2427         tdb_delete(tdb_printers, kbuf);
2428
2429         kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2430         tdb_delete(tdb_printers, kbuf);
2431
2432         close_all_print_db();
2433
2434         if (geteuid() == sec_initial_uid()) {
2435                 if (asprintf(&printdb_path, "%s%s.tdb",
2436                                 cache_path("printing/"),
2437                                 sharename) < 0) {
2438                         return (uint32)-1;
2439                 }
2440                 unlink(printdb_path);
2441                 SAFE_FREE(printdb_path);
2442         }
2443
2444         return 0;
2445 }
2446
2447 /****************************************************************************
2448 ****************************************************************************/
2449 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2450 {
2451         uint8 *buf;
2452         int buflen, len;
2453         int retlen;
2454         WERROR ret;
2455         TDB_DATA kbuf, dbuf;
2456
2457         /*
2458          * in addprinter: no servername and the printer is the name
2459          * in setprinter: servername is \\server
2460          *                and printer is \\server\\printer
2461          *
2462          * Samba manages only local printers.
2463          * we currently don't support things like i
2464          * path=\\other_server\printer
2465          *
2466          * We only store the printername, not \\server\printername
2467          */
2468
2469         if ( info->servername[0] != '\0' ) {
2470                 trim_string(info->printername, info->servername, NULL);
2471                 trim_char(info->printername, '\\', '\0');
2472                 info->servername[0]='\0';
2473         }
2474
2475         /*
2476          * JFM: one day I'll forget.
2477          * below that's info->portname because that's the SAMBA sharename
2478          * and I made NT 'thinks' it's the portname
2479          * the info->sharename is the thing you can name when you add a printer
2480          * that's the short-name when you create shared printer for 95/98
2481          * So I've made a limitation in SAMBA: you can only have 1 printer model
2482          * behind a SAMBA share.
2483          */
2484
2485         buf = NULL;
2486         buflen = 0;
2487
2488  again:
2489         len = 0;
2490         len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2491                         info->attributes,
2492                         info->priority,
2493                         info->default_priority,
2494                         info->starttime,
2495                         info->untiltime,
2496                         info->status,
2497                         info->cjobs,
2498                         info->averageppm,
2499                         info->changeid,
2500                         info->c_setprinter,
2501                         info->setuptime,
2502                         info->servername,
2503                         info->printername,
2504                         info->sharename,
2505                         info->portname,
2506                         info->drivername,
2507                         info->comment,
2508                         info->location,
2509                         info->sepfile,
2510                         info->printprocessor,
2511                         info->datatype,
2512                         info->parameters);
2513
2514         len += pack_devicemode(info->devmode, buf+len, buflen-len);
2515         retlen = pack_values( info->data, buf+len, buflen-len );
2516         if (retlen == -1) {
2517                 ret = WERR_NOMEM;
2518                 goto done;
2519         }
2520         len += retlen;
2521
2522         if (buflen != len) {
2523                 buf = (uint8 *)SMB_REALLOC(buf, len);
2524                 if (!buf) {
2525                         DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2526                         ret = WERR_NOMEM;
2527                         goto done;
2528                 }
2529                 buflen = len;
2530                 goto again;
2531         }
2532
2533         kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2534
2535         dbuf.dptr = buf;
2536         dbuf.dsize = len;
2537
2538         ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2539
2540 done:
2541         if (!W_ERROR_IS_OK(ret))
2542                 DEBUG(8, ("error updating printer to tdb on disk\n"));
2543
2544         SAFE_FREE(buf);
2545
2546         DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2547                  info->sharename, info->drivername, info->portname, len));
2548
2549         return ret;
2550 }
2551
2552 /****************************************************************************
2553  Create and allocate a default devicemode.
2554 ****************************************************************************/
2555
2556 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2557                                       const char *devicename,
2558                                       struct spoolss_DeviceMode **devmode)
2559 {
2560         struct spoolss_DeviceMode *dm;
2561         char *dname;
2562
2563         dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2564         if (dm == NULL) {
2565                 return WERR_NOMEM;
2566         }
2567
2568         dname = talloc_asprintf(dm, "%s", devicename);
2569         if (dname == NULL) {
2570                 return WERR_NOMEM;
2571         }
2572         if (strlen(dname) > MAXDEVICENAME) {
2573                 dname[MAXDEVICENAME] = '\0';
2574         }
2575         dm->devicename = dname;
2576
2577         dm->formname = talloc_strdup(dm, "Letter");
2578         if (dm->formname == NULL) {
2579                 return WERR_NOMEM;
2580         }
2581
2582         dm->specversion          = DMSPEC_NT4_AND_ABOVE;
2583         dm->driverversion        = 0x0400;
2584         dm->size                 = 0x00DC;
2585         dm->__driverextra_length = 0;
2586         dm->fields               = DEVMODE_FORMNAME |
2587                                    DEVMODE_TTOPTION |
2588                                    DEVMODE_PRINTQUALITY |
2589                                    DEVMODE_DEFAULTSOURCE |
2590                                    DEVMODE_COPIES |
2591                                    DEVMODE_SCALE |
2592                                    DEVMODE_PAPERSIZE |
2593                                    DEVMODE_ORIENTATION;
2594         dm->orientation          = DMORIENT_PORTRAIT;
2595         dm->papersize            = DMPAPER_LETTER;
2596         dm->paperlength          = 0;
2597         dm->paperwidth           = 0;
2598         dm->scale                = 0x64;
2599         dm->copies               = 1;
2600         dm->defaultsource        = DMBIN_FORMSOURCE;
2601         dm->printquality         = DMRES_HIGH;           /* 0x0258 */
2602         dm->color                = DMRES_MONOCHROME;
2603         dm->duplex               = DMDUP_SIMPLEX;
2604         dm->yresolution          = 0;
2605         dm->ttoption             = DMTT_SUBDEV;
2606         dm->collate              = DMCOLLATE_FALSE;
2607         dm->icmmethod            = 0;
2608         dm->icmintent            = 0;
2609         dm->mediatype            = 0;
2610         dm->dithertype           = 0;
2611
2612         dm->logpixels            = 0;
2613         dm->bitsperpel           = 0;
2614         dm->pelswidth            = 0;
2615         dm->pelsheight           = 0;
2616         dm->displayflags         = 0;
2617         dm->displayfrequency     = 0;
2618         dm->reserved1            = 0;
2619         dm->reserved2            = 0;
2620         dm->panningwidth         = 0;
2621         dm->panningheight        = 0;
2622
2623         dm->driverextra_data.data = NULL;
2624         dm->driverextra_data.length = 0;
2625
2626         *devmode = dm;
2627         return WERR_OK;
2628 }
2629
2630 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2631                                       struct spoolss_security_descriptor **secdesc)
2632 {
2633         struct security_ace ace[7];     /* max number of ace entries */
2634         int i = 0;
2635         uint32_t sa;
2636         struct security_acl *psa = NULL;
2637         struct security_descriptor *psd = NULL;
2638         struct dom_sid adm_sid;
2639         size_t sd_size;
2640
2641         /* Create an ACE where Everyone is allowed to print */
2642
2643         sa = PRINTER_ACE_PRINT;
2644         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2645                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2646
2647         /* Add the domain admins group if we are a DC */
2648
2649         if ( IS_DC ) {
2650                 struct dom_sid domadmins_sid;
2651
2652                 sid_compose(&domadmins_sid, get_global_sam_sid(),
2653                             DOMAIN_RID_ADMINS);
2654
2655                 sa = PRINTER_ACE_FULL_CONTROL;
2656                 init_sec_ace(&ace[i++], &domadmins_sid,
2657                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2658                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2659                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2660                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2661         }
2662         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2663                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2664
2665                 sa = PRINTER_ACE_FULL_CONTROL;
2666                 init_sec_ace(&ace[i++], &adm_sid,
2667                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2668                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2669                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2670                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2671         }
2672
2673         /* add BUILTIN\Administrators as FULL CONTROL */
2674
2675         sa = PRINTER_ACE_FULL_CONTROL;
2676         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2677                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2678                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2679         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2680                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2681                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2682
2683         /* add BUILTIN\Print Operators as FULL CONTROL */
2684
2685         sa = PRINTER_ACE_FULL_CONTROL;
2686         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2687                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2688                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2689         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2690                 SEC_ACE_TYPE_ACCESS_ALLOWED,
2691                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2692
2693         /* Make the security descriptor owned by the BUILTIN\Administrators */
2694
2695         /* The ACL revision number in rpc_secdesc.h differs from the one
2696            created by NT when setting ACE entries in printer
2697            descriptors.  NT4 complains about the property being edited by a
2698            NT5 machine. */
2699
2700         if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2701                 psd = make_sec_desc(mem_ctx,
2702                                     SD_REVISION,
2703                                     SEC_DESC_SELF_RELATIVE,
2704                                     &global_sid_Builtin_Administrators,
2705                                     &global_sid_Builtin_Administrators,
2706                                     NULL,
2707                                     psa,
2708                                     &sd_size);
2709         }
2710
2711         if (psd == NULL) {
2712                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2713                 return WERR_NOMEM;
2714         }
2715
2716         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2717                  (unsigned int)sd_size));
2718
2719         *secdesc = psd;
2720
2721         return WERR_OK;
2722 }
2723
2724 /****************************************************************************
2725  Malloc and return an NT devicemode.
2726 ****************************************************************************/
2727
2728 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2729 {
2730
2731         char adevice[MAXDEVICENAME];
2732         NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2733
2734         if (nt_devmode == NULL) {
2735                 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2736                 return NULL;
2737         }
2738
2739         ZERO_STRUCTP(nt_devmode);
2740
2741         slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2742         fstrcpy(nt_devmode->devicename, adevice);
2743
2744         fstrcpy(nt_devmode->formname, "Letter");
2745
2746         nt_devmode->specversion      = DMSPEC_NT4_AND_ABOVE;
2747         nt_devmode->driverversion    = 0x0400;
2748         nt_devmode->size             = 0x00DC;
2749         nt_devmode->driverextra      = 0x0000;
2750         nt_devmode->fields           = DEVMODE_FORMNAME |
2751                                        DEVMODE_TTOPTION |
2752                                        DEVMODE_PRINTQUALITY |
2753                                        DEVMODE_DEFAULTSOURCE |
2754                                        DEVMODE_COPIES |
2755                                        DEVMODE_SCALE |
2756                                        DEVMODE_PAPERSIZE |
2757                                        DEVMODE_ORIENTATION;
2758         nt_devmode->orientation      = DMORIENT_PORTRAIT;
2759         nt_devmode->papersize        = DMPAPER_LETTER;
2760         nt_devmode->paperlength      = 0;
2761         nt_devmode->paperwidth       = 0;
2762         nt_devmode->scale            = 0x64;
2763         nt_devmode->copies           = 1;
2764         nt_devmode->defaultsource    = DMBIN_FORMSOURCE;
2765         nt_devmode->printquality     = DMRES_HIGH;           /* 0x0258 */
2766         nt_devmode->color            = DMRES_MONOCHROME;
2767         nt_devmode->duplex           = DMDUP_SIMPLEX;
2768         nt_devmode->yresolution      = 0;
2769         nt_devmode->ttoption         = DMTT_SUBDEV;
2770         nt_devmode->collate          = DMCOLLATE_FALSE;
2771         nt_devmode->icmmethod        = 0;
2772         nt_devmode->icmintent        = 0;
2773         nt_devmode->mediatype        = 0;
2774         nt_devmode->dithertype       = 0;
2775
2776         /* non utilisés par un driver d'imprimante */
2777         nt_devmode->logpixels        = 0;
2778         nt_devmode->bitsperpel       = 0;
2779         nt_devmode->pelswidth        = 0;
2780         nt_devmode->pelsheight       = 0;
2781         nt_devmode->displayflags     = 0;
2782         nt_devmode->displayfrequency = 0;
2783         nt_devmode->reserved1        = 0;
2784         nt_devmode->reserved2        = 0;
2785         nt_devmode->panningwidth     = 0;
2786         nt_devmode->panningheight    = 0;
2787
2788         nt_devmode->nt_dev_private = NULL;
2789         return nt_devmode;
2790 }
2791
2792 /****************************************************************************
2793  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2794 ****************************************************************************/
2795
2796 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2797 {
2798         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2799
2800         if(nt_devmode == NULL)
2801                 return;
2802
2803         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2804
2805         SAFE_FREE(nt_devmode->nt_dev_private);
2806         SAFE_FREE(*devmode_ptr);
2807 }
2808
2809 /****************************************************************************
2810  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2811 ****************************************************************************/
2812
2813 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2814 {
2815         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2816
2817         if ( !info )
2818                 return;
2819
2820         free_nt_devicemode(&info->devmode);
2821
2822         TALLOC_FREE( *info_ptr );
2823 }
2824
2825
2826 /****************************************************************************
2827 ****************************************************************************/
2828 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2829 {
2830         int len = 0;
2831         int extra_len = 0;
2832         NT_DEVICEMODE devmode;
2833
2834         ZERO_STRUCT(devmode);
2835
2836         len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2837
2838         if (!*nt_devmode) return len;
2839
2840         len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2841                           devmode.devicename,
2842                           devmode.formname,
2843
2844                           &devmode.specversion,
2845                           &devmode.driverversion,
2846                           &devmode.size,
2847                           &devmode.driverextra,
2848                           &devmode.orientation,
2849                           &devmode.papersize,
2850                           &devmode.paperlength,
2851                           &devmode.paperwidth,
2852                           &devmode.scale,
2853                           &devmode.copies,
2854                           &devmode.defaultsource,
2855                           &devmode.printquality,
2856                           &devmode.color,
2857                           &devmode.duplex,
2858                           &devmode.yresolution,
2859                           &devmode.ttoption,
2860                           &devmode.collate,
2861                           &devmode.logpixels,
2862
2863                           &devmode.fields,
2864                           &devmode.bitsperpel,
2865                           &devmode.pelswidth,
2866                           &devmode.pelsheight,
2867                           &devmode.displayflags,
2868                           &devmode.displayfrequency,
2869                           &devmode.icmmethod,
2870                           &devmode.icmintent,
2871                           &devmode.mediatype,
2872                           &devmode.dithertype,
2873                           &devmode.reserved1,
2874                           &devmode.reserved2,
2875                           &devmode.panningwidth,
2876                           &devmode.panningheight,
2877                           &devmode.nt_dev_private);
2878
2879         if (devmode.nt_dev_private) {
2880                 /* the len in tdb_unpack is an int value and
2881                  * devmode.driverextra is only a short
2882                  */
2883                 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2884                 devmode.driverextra=(uint16)extra_len;
2885
2886                 /* check to catch an invalid TDB entry so we don't segfault */
2887                 if (devmode.driverextra == 0) {
2888                         devmode.nt_dev_private = NULL;
2889                 }
2890         }
2891
2892         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2893         if (!*nt_devmode) {
2894                 SAFE_FREE(devmode.nt_dev_private);
2895                 return -1;
2896         }
2897
2898         DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2899         if (devmode.nt_dev_private)
2900                 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2901
2902         return len;
2903 }
2904
2905 /****************************************************************************
2906  Allocate and initialize a new slot.
2907 ***************************************************************************/
2908
2909 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2910 {
2911         NT_PRINTER_KEY  *d;
2912         int             key_index;
2913         WERROR werr;
2914
2915         if ( !name || !data )
2916                 return -1;
2917
2918         /* allocate another slot in the NT_PRINTER_KEY array */
2919
2920         if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2921                 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2922                 return -1;
2923         }
2924
2925         data->keys = d;
2926
2927         key_index = data->num_keys;
2928
2929         /* initialze new key */
2930
2931         data->keys[key_index].name = talloc_strdup( data, name );
2932
2933         werr = regval_ctr_init(data, &(data->keys[key_index].values));
2934         if (!W_ERROR_IS_OK(werr)) {
2935                 return -1;
2936         }
2937
2938         data->num_keys++;
2939
2940         DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2941
2942         return key_index;
2943 }
2944
2945 /****************************************************************************
2946  search for a registry key name in the existing printer data
2947  ***************************************************************************/
2948
2949 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2950 {
2951         int i;
2952
2953         for ( i=0; i<data->num_keys; i++ ) {
2954                 if ( strequal( data->keys[i].name, name ) ) {
2955
2956                         /* cleanup memory */
2957
2958                         TALLOC_FREE( data->keys[i].name );
2959                         TALLOC_FREE( data->keys[i].values );
2960
2961                         /* if not the end of the array, move remaining elements down one slot */
2962
2963                         data->num_keys--;
2964                         if ( data->num_keys && (i < data->num_keys) )
2965                                 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2966
2967                         break;
2968                 }
2969         }
2970
2971
2972         return data->num_keys;
2973 }
2974
2975 /****************************************************************************
2976  search for a registry key name in the existing printer data
2977  ***************************************************************************/
2978
2979 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2980 {
2981         int             key_index = -1;
2982         int             i;
2983
2984         if ( !data || !name )
2985                 return -1;
2986
2987         DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2988
2989         /* loop over all existing keys */
2990
2991         for ( i=0; i<data->num_keys; i++ ) {
2992                 if ( strequal(data->keys[i].name, name) ) {
2993                         DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2994                         key_index = i;
2995                         break;
2996
2997                 }
2998         }
2999
3000         return key_index;
3001 }
3002
3003 /****************************************************************************
3004  ***************************************************************************/
3005
3006 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
3007 {
3008         int     i, j;
3009         int     key_len;
3010         int     num_subkeys = 0;
3011         char    *p;
3012         fstring *subkeys_ptr = NULL;
3013         fstring subkeyname;
3014
3015         *subkeys = NULL;
3016
3017         if ( !data )
3018                 return 0;
3019
3020         if ( !key )
3021                 return -1;
3022
3023         /* special case of asking for the top level printer data registry key names */
3024
3025         if ( strlen(key) == 0 ) {
3026                 for ( i=0; i<data->num_keys; i++ ) {
3027
3028                         /* found a match, so allocate space and copy the name */
3029
3030                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3031                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3032                                         num_subkeys+1));
3033                                 return -1;
3034                         }
3035
3036                         fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3037                         num_subkeys++;
3038                 }
3039
3040                 goto done;
3041         }
3042
3043         /* asking for the subkeys of some key */
3044         /* subkey paths are stored in the key name using '\' as the delimiter */
3045
3046         for ( i=0; i<data->num_keys; i++ ) {
3047                 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3048
3049                         /* if we found the exact key, then break */
3050                         key_len = strlen( key );
3051                         if ( strlen(data->keys[i].name) == key_len )
3052                                 break;
3053
3054                         /* get subkey path */
3055
3056                         p = data->keys[i].name + key_len;
3057                         if ( *p == '\\' )
3058                                 p++;
3059                         fstrcpy( subkeyname, p );
3060                         if ( (p = strchr( subkeyname, '\\' )) )
3061                                 *p = '\0';
3062
3063                         /* don't add a key more than once */
3064
3065                         for ( j=0; j<num_subkeys; j++ ) {
3066                                 if ( strequal( subkeys_ptr[j], subkeyname ) )
3067                                         break;
3068                         }
3069
3070                         if ( j != num_subkeys )
3071                                 continue;
3072
3073                         /* found a match, so allocate space and copy the name */
3074
3075                         if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3076                                 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3077                                         num_subkeys+1));
3078                                 return 0;
3079                         }
3080
3081                         fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3082                         num_subkeys++;
3083                 }
3084
3085         }
3086
3087         /* return error if the key was not found */
3088
3089         if ( i == data->num_keys ) {
3090                 SAFE_FREE(subkeys_ptr);
3091                 return -1;
3092         }
3093
3094 done:
3095         /* tag off the end */
3096
3097         if (num_subkeys)
3098                 fstrcpy(subkeys_ptr[num_subkeys], "" );
3099
3100         *subkeys = subkeys_ptr;
3101
3102         return num_subkeys;
3103 }
3104
3105 #ifdef HAVE_ADS
3106 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3107                             const char *sz)
3108 {
3109         regval_ctr_delvalue(ctr, val_name);
3110         regval_ctr_addvalue_sz(ctr, val_name, sz);
3111 }
3112
3113 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3114                                uint32 dword)
3115 {
3116         regval_ctr_delvalue(ctr, val_name);
3117         regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3118                             (uint8 *) &dword, sizeof(dword));
3119 }
3120
3121 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3122                               bool b)
3123 {
3124         uint8 bin_bool = (b ? 1 : 0);
3125         regval_ctr_delvalue(ctr, val_name);
3126         regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3127                             (uint8 *) &bin_bool, sizeof(bin_bool));
3128 }
3129
3130 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3131                                          const char *multi_sz)
3132 {
3133         const char *a[2];
3134
3135         a[0] = multi_sz;
3136         a[1] = NULL;
3137
3138         regval_ctr_delvalue(ctr, val_name);
3139         regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3140 }
3141
3142 /****************************************************************************
3143  * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3144  *
3145  * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3146  * @return bool indicating success or failure
3147  ***************************************************************************/
3148
3149 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3150 {
3151         struct regval_ctr *ctr = NULL;
3152         fstring longname;
3153         const char *dnssuffix;
3154         char *allocated_string = NULL;
3155         const char *ascii_str;
3156         int i;
3157
3158         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3159                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3160         ctr = info2->data->keys[i].values;
3161
3162         map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3163         map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3164
3165         /* we make the assumption that the netbios name is the same
3166            as the DNS name sinc ethe former will be what we used to
3167            join the domain */
3168
3169         dnssuffix = get_mydnsdomname(talloc_tos());
3170         if (dnssuffix && *dnssuffix) {
3171                 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3172         } else {
3173                 fstrcpy( longname, global_myname() );
3174         }
3175
3176         map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3177
3178         if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3179                 return false;
3180         }
3181         map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3182         SAFE_FREE(allocated_string);
3183
3184         map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3185         map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3186         map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3187         map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3188         map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3189         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3190         map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3191         map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3192         map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3193
3194         map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3195                           (info2->attributes &
3196                            PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3197
3198         switch (info2->attributes & 0x3) {
3199         case 0:
3200                 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3201                 break;
3202         case 1:
3203                 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3204                 break;
3205         case 2:
3206                 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3207                 break;
3208         default:
3209                 ascii_str = "unknown";
3210         }
3211         map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3212
3213         return True;
3214 }
3215
3216 /*****************************************************************
3217  ****************************************************************/
3218
3219 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3220                                struct GUID guid)
3221 {
3222         int i;
3223         struct regval_ctr *ctr=NULL;
3224
3225         /* find the DsSpooler key */
3226         if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3227                 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3228         ctr = info2->data->keys[i].values;
3229
3230         regval_ctr_delvalue(ctr, "objectGUID");
3231
3232         /* We used to store this as a REG_BINARY but that causes
3233            Vista to whine */
3234
3235         regval_ctr_addvalue_sz(ctr, "objectGUID",
3236                                GUID_string(talloc_tos(), &guid));
3237 }
3238
3239 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3240                                      NT_PRINTER_INFO_LEVEL *printer)
3241 {
3242         ADS_STATUS ads_rc;
3243         LDAPMessage *res;
3244         char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3245         char *srv_dn_utf8, **srv_cn_utf8;
3246         TALLOC_CTX *ctx;
3247         ADS_MODLIST mods;
3248         const char *attrs[] = {"objectGUID", NULL};
3249         struct GUID guid;
3250         WERROR win_rc = WERR_OK;
3251         size_t converted_size;
3252
3253         /* build the ads mods */
3254         ctx = talloc_init("nt_printer_publish_ads");
3255         if (ctx == NULL) {
3256                 return WERR_NOMEM;
3257         }
3258
3259         DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3260
3261         /* figure out where to publish */
3262         ads_find_machine_acct(ads, &res, global_myname());
3263
3264         /* We use ldap_get_dn here as we need the answer
3265          * in utf8 to call ldap_explode_dn(). JRA. */
3266
3267         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3268         if (!srv_dn_utf8) {
3269                 TALLOC_FREE(ctx);
3270                 return WERR_SERVER_UNAVAILABLE;
3271         }
3272         ads_msgfree(ads, res);
3273         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3274         if (!srv_cn_utf8) {
3275                 TALLOC_FREE(ctx);
3276                 ldap_memfree(srv_dn_utf8);
3277                 return WERR_SERVER_UNAVAILABLE;
3278         }
3279         /* Now convert to CH_UNIX. */
3280         if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3281                 TALLOC_FREE(ctx);
3282                 ldap_memfree(srv_dn_utf8);
3283                 ldap_memfree(srv_cn_utf8);
3284                 return WERR_SERVER_UNAVAILABLE;
3285         }
3286         if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3287                 TALLOC_FREE(ctx);
3288                 ldap_memfree(srv_dn_utf8);
3289                 ldap_memfree(srv_cn_utf8);
3290                 TALLOC_FREE(srv_dn);
3291                 return WERR_SERVER_UNAVAILABLE;
3292         }
3293
3294         ldap_memfree(srv_dn_utf8);
3295         ldap_memfree(srv_cn_utf8);
3296
3297         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3298         if (!srv_cn_escaped) {
3299                 TALLOC_FREE(ctx);
3300                 return WERR_SERVER_UNAVAILABLE;
3301         }
3302         sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3303         if (!sharename_escaped) {
3304                 SAFE_FREE(srv_cn_escaped);
3305                 TALLOC_FREE(ctx);
3306                 return WERR_SERVER_UNAVAILABLE;
3307         }
3308
3309         prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3310
3311         SAFE_FREE(srv_cn_escaped);
3312         SAFE_FREE(sharename_escaped);
3313
3314         mods = ads_init_mods(ctx);
3315
3316         if (mods == NULL) {
3317                 SAFE_FREE(prt_dn);
3318                 TALLOC_FREE(ctx);
3319                 return WERR_NOMEM;
3320         }
3321
3322         get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3323         ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3324                     printer->info_2->sharename);
3325
3326         /* publish it */
3327         ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3328         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3329                 int i;
3330                 for (i=0; mods[i] != 0; i++)
3331                         ;
3332                 mods[i] = (LDAPMod *)-1;
3333                 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3334         }
3335
3336         if (!ADS_ERR_OK(ads_rc))
3337                 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3338
3339         /* retreive the guid and store it locally */
3340         if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3341                 ZERO_STRUCT(guid);
3342                 ads_pull_guid(ads, res, &guid);
3343                 ads_msgfree(ads, res);
3344                 store_printer_guid(printer->info_2, guid);
3345                 win_rc = mod_a_printer(printer, 2);
3346         }
3347         TALLOC_FREE(ctx);
3348
3349         return win_rc;
3350 }
3351
3352 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3353                                        NT_PRINTER_INFO_LEVEL *printer)
3354 {
3355         ADS_STATUS ads_rc;
3356         LDAPMessage *res = NULL;
3357         char *prt_dn = NULL;
3358
3359         DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3360
3361         /* remove the printer from the directory */
3362         ads_rc = ads_find_printer_on_server(ads, &res,
3363                             printer->info_2->sharename, global_myname());
3364
3365         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3366                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3367                 if (!prt_dn) {
3368                         ads_msgfree(ads, res);
3369                         return WERR_NOMEM;
3370                 }
3371                 ads_rc = ads_del_dn(ads, prt_dn);
3372                 TALLOC_FREE(prt_dn);
3373         }
3374
3375         if (res) {
3376                 ads_msgfree(ads, res);
3377         }
3378         return WERR_OK;
3379 }
3380
3381 /****************************************************************************
3382  * Publish a printer in the directory
3383  *
3384  * @param snum describing printer service
3385  * @return WERROR indicating status of publishing
3386  ***************************************************************************/
3387
3388 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3389 {
3390         ADS_STATUS ads_rc;
3391         ADS_STRUCT *ads = NULL;
3392         NT_PRINTER_INFO_LEVEL *printer = NULL;
3393         WERROR win_rc;
3394
3395         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3396         if (!W_ERROR_IS_OK(win_rc))
3397                 goto done;
3398
3399         switch (action) {
3400         case DSPRINT_PUBLISH:
3401         case DSPRINT_UPDATE:
3402                 /* set the DsSpooler info and attributes */
3403                 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3404                         win_rc = WERR_NOMEM;
3405                         goto done;
3406                 }
3407
3408                 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3409                 break;
3410         case DSPRINT_UNPUBLISH:
3411                 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3412                 break;
3413         default:
3414                 win_rc = WERR_NOT_SUPPORTED;
3415                 goto done;
3416         }
3417
3418         win_rc = mod_a_printer(printer, 2);
3419         if (!W_ERROR_IS_OK(win_rc)) {
3420                 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3421                 goto done;
3422         }
3423
3424         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3425         if (!ads) {
3426                 DEBUG(3, ("ads_init() failed\n"));
3427                 win_rc = WERR_SERVER_UNAVAILABLE;
3428                 goto done;
3429         }
3430         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3431         SAFE_FREE(ads->auth.password);
3432         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3433                 NULL, NULL);
3434
3435         /* ads_connect() will find the DC for us */
3436         ads_rc = ads_connect(ads);
3437         if (!ADS_ERR_OK(ads_rc)) {
3438                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3439                 win_rc = WERR_ACCESS_DENIED;
3440                 goto done;
3441         }
3442
3443         switch (action) {
3444         case DSPRINT_PUBLISH:
3445         case DSPRINT_UPDATE:
3446                 win_rc = nt_printer_publish_ads(ads, printer);
3447                 break;
3448         case DSPRINT_UNPUBLISH:
3449                 win_rc = nt_printer_unpublish_ads(ads, printer);
3450                 break;
3451         }
3452
3453 done:
3454         free_a_printer(&printer, 2);
3455         ads_destroy(&ads);
3456         return win_rc;
3457 }
3458
3459 WERROR check_published_printers(void)
3460 {
3461         ADS_STATUS ads_rc;
3462         ADS_STRUCT *ads = NULL;
3463         int snum;
3464         int n_services = lp_numservices();
3465         NT_PRINTER_INFO_LEVEL *printer = NULL;
3466
3467         ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3468         if (!ads) {
3469                 DEBUG(3, ("ads_init() failed\n"));
3470                 return WERR_SERVER_UNAVAILABLE;
3471         }
3472         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3473         SAFE_FREE(ads->auth.password);
3474         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3475                 NULL, NULL);
3476
3477         /* ads_connect() will find the DC for us */
3478         ads_rc = ads_connect(ads);
3479         if (!ADS_ERR_OK(ads_rc)) {
3480                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3481                 ads_destroy(&ads);
3482                 ads_kdestroy("MEMORY:prtpub_cache");
3483                 return WERR_ACCESS_DENIED;
3484         }
3485
3486         for (snum = 0; snum < n_services; snum++) {
3487                 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3488                         continue;
3489
3490                 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3491                                                 lp_servicename(snum))) &&
3492                     (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3493                         nt_printer_publish_ads(ads, printer);
3494
3495                 free_a_printer(&printer, 2);
3496         }
3497
3498         ads_destroy(&ads);
3499         ads_kdestroy("MEMORY:prtpub_cache");
3500         return WERR_OK;
3501 }
3502
3503 bool is_printer_published(Printer_entry *print_hnd, int snum,
3504                           struct GUID *guid)
3505 {
3506         NT_PRINTER_INFO_LEVEL *printer = NULL;
3507         struct regval_ctr *ctr;
3508         struct regval_blob *guid_val;
3509         WERROR win_rc;
3510         int i;
3511         bool ret = False;
3512         DATA_BLOB blob;
3513
3514         win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3515
3516         if (!W_ERROR_IS_OK(win_rc) ||
3517             !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3518             ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3519             !(ctr = printer->info_2->data->keys[i].values) ||
3520             !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3521         {
3522                 free_a_printer(&printer, 2);
3523                 return False;
3524         }
3525
3526         /* fetching printer guids really ought to be a separate function. */
3527
3528         if ( guid ) {
3529                 char *guid_str;
3530
3531                 /* We used to store the guid as REG_BINARY, then swapped
3532                    to REG_SZ for Vista compatibility so check for both */
3533
3534                 switch ( regval_type(guid_val) ){
3535                 case REG_SZ:
3536                         blob = data_blob_const(regval_data_p(guid_val),
3537                                                regval_size(guid_val));
3538                         pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3539                         ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3540                         talloc_free(guid_str);
3541                         break;
3542                 case REG_BINARY:
3543                         if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3544                                 ret = False;
3545                                 break;
3546                         }
3547                         memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3548                         break;
3549                 default:
3550                         DEBUG(0,("is_printer_published: GUID value stored as "
3551                                  "invaluid type (%d)\n", regval_type(guid_val) ));
3552                         break;
3553                 }
3554         }
3555
3556         free_a_printer(&printer, 2);
3557         return ret;
3558 }
3559 #else
3560 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3561 {
3562         return WERR_OK;
3563 }
3564
3565 WERROR check_published_printers(void)
3566 {
3567         return WERR_OK;
3568 }
3569
3570 bool is_printer_published(Printer_entry *print_hnd, int snum,
3571                           struct GUID *guid)
3572 {
3573         return False;
3574 }
3575 #endif /* HAVE_ADS */
3576
3577 /****************************************************************************
3578  ***************************************************************************/
3579
3580 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3581 {
3582         NT_PRINTER_DATA *data;
3583         int             i;
3584         int             removed_keys = 0;
3585         int             empty_slot;
3586
3587         data = p2->data;
3588         empty_slot = data->num_keys;
3589
3590         if ( !key )
3591                 return WERR_INVALID_PARAM;
3592
3593         /* remove all keys */
3594
3595         if ( !strlen(key) ) {
3596
3597                 TALLOC_FREE( data );
3598
3599                 p2->data = NULL;
3600
3601                 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3602                         p2->printername ));
3603
3604                 return WERR_OK;
3605         }
3606
3607         /* remove a specific key (and all subkeys) */
3608
3609         for ( i=0; i<data->num_keys; i++ ) {
3610                 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3611                         DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3612                                 data->keys[i].name));
3613
3614                         TALLOC_FREE( data->keys[i].name );
3615                         TALLOC_FREE( data->keys[i].values );
3616
3617                         /* mark the slot as empty */
3618
3619                         ZERO_STRUCTP( &data->keys[i] );
3620                 }
3621         }
3622
3623         /* find the first empty slot */
3624
3625         for ( i=0; i<data->num_keys; i++ ) {
3626                 if ( !data->keys[i].name ) {
3627                         empty_slot = i;
3628                         removed_keys++;
3629                         break;
3630                 }
3631         }
3632
3633         if ( i == data->num_keys )
3634                 /* nothing was removed */
3635                 return WERR_INVALID_PARAM;
3636
3637         /* move everything down */
3638
3639         for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3640                 if ( data->keys[i].name ) {
3641                         memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3642                         ZERO_STRUCTP( &data->keys[i] );
3643                         empty_slot++;
3644                         removed_keys++;
3645                 }
3646         }
3647
3648         /* update count */
3649
3650         data->num_keys -= removed_keys;
3651
3652         /* sanity check to see if anything is left */
3653
3654         if ( !data->num_keys ) {
3655                 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3656
3657                 SAFE_FREE( data->keys );
3658                 ZERO_STRUCTP( data );
3659         }
3660
3661         return WERR_OK;
3662 }
3663
3664 /****************************************************************************
3665  ***************************************************************************/
3666
3667 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3668 {
3669         WERROR          result = WERR_OK;
3670         int             key_index;
3671
3672         /* we must have names on non-zero length */
3673
3674         if ( !key || !*key|| !value || !*value )
3675                 return WERR_INVALID_NAME;
3676
3677         /* find the printer key first */
3678
3679         key_index = lookup_printerkey( p2->data, key );
3680         if ( key_index == -1 )
3681                 return WERR_OK;
3682
3683         /* make sure the value exists so we can return the correct error code */
3684
3685         if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3686                 return WERR_BADFILE;
3687
3688         regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3689
3690         DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3691                 key, value ));
3692
3693         return result;
3694 }
3695
3696 /****************************************************************************
3697  ***************************************************************************/
3698
3699 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3700                            uint32 type, uint8 *data, int real_len )
3701 {
3702         WERROR          result = WERR_OK;
3703         int             key_index;
3704
3705         /* we must have names on non-zero length */
3706
3707         if ( !key || !*key|| !value || !*value )
3708                 return WERR_INVALID_NAME;
3709
3710         /* find the printer key first */
3711
3712         key_index = lookup_printerkey( p2->data, key );
3713         if ( key_index == -1 )
3714                 key_index = add_new_printer_key( p2->data, key );
3715
3716         if ( key_index == -1 )
3717                 return WERR_NOMEM;
3718
3719         regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3720                 type, data, real_len );
3721
3722         DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3723                 key, value, type, real_len  ));
3724
3725         return result;
3726 }
3727
3728 /****************************************************************************
3729  ***************************************************************************/
3730
3731 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3732 {
3733         int             key_index;
3734
3735         if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3736                 return NULL;
3737
3738         DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3739                 key, value ));
3740
3741         return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3742 }
3743
3744 /****************************************************************************
3745  Unpack a list of registry values frem the TDB
3746  ***************************************************************************/
3747
3748 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3749 {
3750         int             len = 0;
3751         uint32          type;
3752         fstring string;
3753         const char *valuename = NULL;
3754         const char *keyname = NULL;
3755         char            *str;
3756         int             size;
3757         uint8           *data_p;
3758         struct regval_blob      *regval_p;
3759         int             key_index;
3760
3761         /* add the "PrinterDriverData" key first for performance reasons */
3762
3763         add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3764
3765         /* loop and unpack the rest of the registry values */
3766
3767         while ( True ) {
3768
3769                 /* check to see if there are any more registry values */
3770
3771                 regval_p = NULL;
3772                 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3773                 if ( !regval_p )
3774                         break;
3775
3776                 /* unpack the next regval */
3777
3778                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3779                                   string,
3780                                   &type,
3781                                   &size,
3782                                   &data_p);
3783
3784                 /* lookup for subkey names which have a type of REG_NONE */
3785                 /* there's no data with this entry */
3786
3787                 if ( type == REG_NONE ) {
3788                         if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3789                                 add_new_printer_key( printer_data, string );
3790                         continue;
3791                 }
3792
3793                 /*
3794                  * break of the keyname from the value name.
3795                  * Valuenames can have embedded '\'s so be careful.
3796                  * only support one level of keys.  See the
3797                  * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3798                  * -- jerry
3799                  */
3800
3801                 str = strchr_m( string, '\\');
3802
3803                 /* Put in "PrinterDriverData" is no key specified */
3804
3805                 if ( !str ) {
3806                         keyname = SPOOL_PRINTERDATA_KEY;
3807                         valuename = string;
3808                 }
3809                 else {
3810                         *str = '\0';
3811                         keyname = string;
3812                         valuename = str+1;
3813                 }
3814
3815                 /* see if we need a new key */
3816
3817                 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3818                         key_index = add_new_printer_key( printer_data, keyname );
3819
3820                 if ( key_index == -1 ) {
3821                         DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3822                                 keyname));
3823                         break;
3824                 }
3825
3826                 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3827
3828                 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3829                    Thanks to Martin Zielinski for the hint. */
3830
3831                 if ( type == REG_BINARY &&
3832                      strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3833                      strequal( valuename, "objectGUID" ) )
3834                 {
3835                         struct GUID guid;
3836
3837                         /* convert the GUID to a UNICODE string */
3838
3839                         memcpy( &guid, data_p, sizeof(struct GUID) );
3840
3841                         regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3842                                                valuename,
3843                                                GUID_string(talloc_tos(), &guid));
3844
3845                 } else {
3846                         /* add the value */
3847
3848                         regval_ctr_addvalue( printer_data->keys[key_index].values,
3849                                              valuename, type, data_p,
3850                                              size );
3851                 }
3852
3853                 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3854
3855         }
3856
3857         return len;
3858 }
3859
3860 /****************************************************************************
3861  ***************************************************************************/
3862
3863 static char *win_driver;
3864 static char *os2_driver;
3865
3866 static const char *get_win_driver(void)
3867 {
3868         if (win_driver == NULL) {
3869                 return "";
3870         }
3871         return win_driver;
3872 }
3873
3874 static const char *get_os2_driver(void)
3875 {
3876         if (os2_driver == NULL) {
3877                 return "";
3878         }
3879         return os2_driver;
3880 }
3881
3882 static bool set_driver_mapping(const char *from, const char *to)
3883 {
3884         SAFE_FREE(win_driver);
3885         SAFE_FREE(os2_driver);
3886
3887         win_driver = SMB_STRDUP(from);
3888         os2_driver = SMB_STRDUP(to);
3889
3890         if (win_driver == NULL || os2_driver == NULL) {
3891                 SAFE_FREE(win_driver);
3892                 SAFE_FREE(os2_driver);
3893                 return false;
3894         }
3895         return true;
3896 }
3897
3898 static void map_to_os2_driver(fstring drivername)
3899 {
3900         char *mapfile = lp_os2_driver_map();
3901         char **lines = NULL;
3902         int numlines = 0;
3903         int i;
3904
3905         if (!strlen(drivername))
3906                 return;
3907
3908         if (!*mapfile)
3909                 return;
3910
3911         if (strequal(drivername, get_win_driver())) {
3912                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3913                         drivername, get_os2_driver()));
3914                 fstrcpy(drivername, get_os2_driver());
3915                 return;
3916         }
3917
3918         lines = file_lines_load(mapfile, &numlines,0,NULL);
3919         if (numlines == 0 || lines == NULL) {
3920                 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3921                 TALLOC_FREE(lines);
3922                 return;
3923         }
3924
3925         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3926
3927         for( i = 0; i < numlines; i++) {
3928                 char *nt_name = lines[i];
3929                 char *os2_name = strchr(nt_name,'=');
3930
3931                 if (!os2_name)
3932                         continue;
3933
3934                 *os2_name++ = 0;
3935
3936                 while (isspace(*nt_name))
3937                         nt_name++;
3938
3939                 if (!*nt_name || strchr("#;",*nt_name))
3940                         continue;
3941
3942                 {
3943                         int l = strlen(nt_name);
3944                         while (l && isspace(nt_name[l-1])) {
3945                                 nt_name[l-1] = 0;
3946                                 l--;
3947                         }
3948                 }
3949
3950                 while (isspace(*os2_name))
3951                         os2_name++;
3952
3953                 {
3954                         int l = strlen(os2_name);
3955                         while (l && isspace(os2_name[l-1])) {
3956                                 os2_name[l-1] = 0;
3957                                 l--;
3958                         }
3959                 }
3960
3961                 if (strequal(nt_name,drivername)) {
3962                         DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3963                         set_driver_mapping(drivername,os2_name);
3964                         fstrcpy(drivername,os2_name);
3965                         TALLOC_FREE(lines);
3966                         return;
3967                 }
3968         }
3969
3970         TALLOC_FREE(lines);
3971 }
3972
3973 /**
3974  * @internal
3975  *
3976  * @brief Map a Windows driver to a OS/2 driver.
3977  *
3978  * @param[in]  mem_ctx  The memory context to use.
3979  *
3980  * @param[in,out] pdrivername The drivername of Windows to remap.
3981  *
3982  * @return              WERR_OK on success, a corresponding WERROR on failure.
3983  */
3984 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3985 {
3986         const char *mapfile = lp_os2_driver_map();
3987         char **lines = NULL;
3988         const char *drivername;
3989         int numlines = 0;
3990         int i;
3991
3992         if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3993                 return WERR_INVALID_PARAMETER;
3994         }
3995
3996         drivername = *pdrivername;
3997
3998         if (mapfile[0] == '\0') {
3999                 return WERR_BADFILE;
4000         }
4001
4002         if (strequal(drivername, get_win_driver())) {
4003                 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
4004                         drivername, get_os2_driver()));
4005                 drivername = talloc_strdup(mem_ctx, get_os2_driver());
4006                 if (drivername == NULL) {
4007                         return WERR_NOMEM;
4008                 }
4009                 *pdrivername = drivername;
4010                 return WERR_OK;
4011         }
4012
4013         lines = file_lines_load(mapfile, &numlines, 0, NULL);
4014         if (numlines == 0 || lines == NULL) {
4015                 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
4016                 TALLOC_FREE(lines);
4017                 return WERR_EMPTY;
4018         }
4019
4020         DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
4021
4022         for( i = 0; i < numlines; i++) {
4023                 char *nt_name = lines[i];
4024                 char *os2_name = strchr(nt_name, '=');
4025
4026                 if (os2_name == NULL) {
4027                         continue;
4028                 }
4029
4030                 *os2_name++ = '\0';
4031
4032                 while (isspace(*nt_name)) {
4033                         nt_name++;
4034                 }
4035
4036                 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
4037                         continue;
4038                 }
4039
4040                 {
4041                         int l = strlen(nt_name);
4042                         while (l && isspace(nt_name[l - 1])) {
4043                                 nt_name[l - 1] = 0;
4044                                 l--;
4045                         }
4046                 }
4047
4048                 while (isspace(*os2_name)) {
4049                         os2_name++;
4050                 }
4051
4052                 {
4053                         int l = strlen(os2_name);
4054                         while (l && isspace(os2_name[l-1])) {
4055                                 os2_name[l-1] = 0;
4056                                 l--;
4057                         }
4058                 }
4059
4060                 if (strequal(nt_name, drivername)) {
4061                         DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
4062                         set_driver_mapping(drivername, os2_name);
4063                         drivername = talloc_strdup(mem_ctx, os2_name);
4064                         TALLOC_FREE(lines);
4065                         if (drivername == NULL) {
4066                                 return WERR_NOMEM;
4067                         }
4068                         *pdrivername = drivername;
4069                         return WERR_OK;
4070                 }
4071         }
4072
4073         TALLOC_FREE(lines);
4074         return WERR_OK;
4075 }
4076
4077 /****************************************************************************
4078  Get a default printer info 2 struct.
4079 ****************************************************************************/
4080
4081 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
4082                                 const char *servername,
4083                                 const char* sharename,
4084                                 bool get_loc_com)
4085 {
4086         int snum = lp_servicenumber(sharename);
4087
4088         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4089         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4090                 servername, sharename);
4091         fstrcpy(info->sharename, sharename);
4092         fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
4093
4094         /* by setting the driver name to an empty string, a local NT admin
4095            can now run the **local** APW to install a local printer driver
4096            for a Samba shared printer in 2.2.  Without this, drivers **must** be
4097            installed on the Samba server for NT clients --jerry */
4098 #if 0   /* JERRY --do not uncomment-- */
4099         if (!*info->drivername)
4100                 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4101 #endif
4102
4103
4104         DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
4105
4106         strlcpy(info->comment, "", sizeof(info->comment));
4107         fstrcpy(info->printprocessor, "winprint");
4108         fstrcpy(info->datatype, "RAW");
4109
4110 #ifdef HAVE_CUPS
4111         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4112                 /* Pull the location and comment strings from cups if we don't
4113                    already have one */
4114                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4115                         char *comment = NULL;
4116                         char *location = NULL;
4117                         if (cups_pull_comment_location(info, info->sharename,
4118                                                        &comment, &location)) {
4119                                 strlcpy(info->comment, comment, sizeof(info->comment));
4120                                 fstrcpy(info->location, location);
4121                                 TALLOC_FREE(comment);
4122                                 TALLOC_FREE(location);
4123                         }
4124                 }
4125         }
4126 #endif
4127
4128         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4129
4130         info->starttime = 0; /* Minutes since 12:00am GMT */
4131         info->untiltime = 0; /* Minutes since 12:00am GMT */
4132         info->priority = 1;
4133         info->default_priority = 1;
4134         info->setuptime = (uint32)time(NULL);
4135
4136         /*
4137          * I changed this as I think it is better to have a generic
4138          * DEVMODE than to crash Win2k explorer.exe   --jerry
4139          * See the HP Deskjet 990c Win2k drivers for an example.
4140          *
4141          * However the default devmode appears to cause problems
4142          * with the HP CLJ 8500 PCL driver.  Hence the addition of
4143          * the "default devmode" parameter   --jerry 22/01/2002
4144          */
4145
4146         if (lp_default_devmode(snum)) {
4147                 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4148                         goto fail;
4149                 }
4150         } else {
4151                 info->devmode = NULL;
4152         }
4153
4154         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4155                 goto fail;
4156         }
4157
4158         info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4159         if (!info->data) {
4160                 goto fail;
4161         }
4162
4163         add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4164
4165         return WERR_OK;
4166
4167 fail:
4168         if (info->devmode)
4169                 free_nt_devicemode(&info->devmode);
4170
4171         return WERR_ACCESS_DENIED;
4172 }
4173
4174 /****************************************************************************
4175 ****************************************************************************/
4176
4177 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4178                                 const char *servername,
4179                                 const char *sharename,
4180                                 bool get_loc_com)
4181 {
4182         int len = 0;
4183         int snum = lp_servicenumber(sharename);
4184         TDB_DATA kbuf, dbuf;
4185         fstring printername;
4186         char adevice[MAXDEVICENAME];
4187         char *comment = NULL;
4188
4189         kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4190
4191         dbuf = tdb_fetch(tdb_printers, kbuf);
4192         if (!dbuf.dptr) {
4193                 return get_a_printer_2_default(info, servername,
4194                                         sharename, get_loc_com);
4195         }
4196
4197         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4198                         &info->attributes,
4199                         &info->priority,
4200                         &info->default_priority,
4201                         &info->starttime,
4202                         &info->untiltime,
4203                         &info->status,
4204                         &info->cjobs,
4205                         &info->averageppm,
4206                         &info->changeid,
4207                         &info->c_setprinter,
4208                         &info->setuptime,
4209                         info->servername,
4210                         info->printername,
4211                         info->sharename,
4212                         info->portname,
4213                         info->drivername,
4214                         &comment,
4215                         info->location,
4216                         info->sepfile,
4217                         info->printprocessor,
4218                         info->datatype,
4219                         info->parameters);
4220
4221         if (comment) {
4222                 strlcpy(info->comment, comment, sizeof(info->comment));
4223                 SAFE_FREE(comment);
4224         }
4225
4226         /* Samba has to have shared raw drivers. */
4227         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4228         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4229
4230         /* Restore the stripped strings. */
4231         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4232
4233         if ( lp_force_printername(snum) ) {
4234                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4235         } else {
4236                 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4237         }
4238
4239         fstrcpy(info->printername, printername);
4240
4241 #ifdef HAVE_CUPS
4242         if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4243                 /* Pull the location and comment strings from cups if we don't
4244                    already have one */
4245                 if ( !strlen(info->location) || !strlen(info->comment) ) {
4246                         char *location = NULL;
4247                         comment = NULL;
4248                         if (cups_pull_comment_location(info, info->sharename,
4249                                                        &comment, &location)) {
4250                                 strlcpy(info->comment, comment, sizeof(info->comment));
4251                                 fstrcpy(info->location, location);
4252                                 TALLOC_FREE(comment);
4253                                 TALLOC_FREE(location);
4254                         }
4255                 }
4256         }
4257 #endif
4258
4259         len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4260
4261         /*
4262          * Some client drivers freak out if there is a NULL devmode
4263          * (probably the driver is not checking before accessing
4264          * the devmode pointer)   --jerry
4265          *
4266          * See comments in get_a_printer_2_default()
4267          */
4268
4269         if (lp_default_devmode(snum) && !info->devmode) {
4270                 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4271                         printername));
4272                 info->devmode = construct_nt_devicemode(printername);
4273         }
4274
4275         slprintf( adevice, sizeof(adevice), "%s", info->printername );
4276         if (info->devmode) {
4277                 fstrcpy(info->devmode->devicename, adevice);
4278         }
4279
4280         if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4281                 DEBUG(0,("unpack_values: talloc() failed!\n"));
4282                 SAFE_FREE(dbuf.dptr);
4283                 return WERR_NOMEM;
4284         }
4285         len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4286
4287         /* This will get the current RPC talloc context, but we should be
4288            passing this as a parameter... fixme... JRA ! */
4289
4290         if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4291                 SAFE_FREE(dbuf.dptr);
4292                 return WERR_NOMEM;
4293         }
4294
4295         /* Fix for OS/2 drivers. */
4296
4297         if (get_remote_arch() == RA_OS2) {
4298                 map_to_os2_driver(info->drivername);
4299         }
4300
4301         SAFE_FREE(dbuf.dptr);
4302
4303         DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4304                  sharename, info->printername, info->drivername));
4305
4306         return WERR_OK;
4307 }
4308
4309 /****************************************************************************
4310  Debugging function, dump at level 6 the struct in the logs.
4311 ****************************************************************************/
4312 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4313 {
4314         uint32 result;
4315         NT_PRINTER_INFO_LEVEL_2 *info2;
4316
4317         DEBUG(106,("Dumping printer at level [%d]\n", level));
4318
4319         switch (level) {
4320                 case 2:
4321                 {
4322                         if (printer->info_2 == NULL)
4323                                 result=5;
4324                         else
4325                         {
4326                                 info2=printer->info_2;
4327
4328                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4329                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4330                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4331                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4332                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4333                                 DEBUGADD(106,("status:[%d]\n", info2->status));
4334                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4335                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4336                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4337                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4338                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4339
4340                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4341                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4342                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4343                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4344                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4345                                 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4346                                 DEBUGADD(106,("location:[%s]\n", info2->location));
4347                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4348                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4349                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4350                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4351                                 result=0;
4352                         }
4353                         break;
4354                 }
4355                 default:
4356                         DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4357                         result=1;
4358                         break;
4359         }
4360
4361         return result;
4362 }
4363
4364 /****************************************************************************
4365  Update the changeid time.
4366  This is SO NASTY as some drivers need this to change, others need it
4367  static. This value will change every second, and I must hope that this
4368  is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4369  UTAH ! JRA.
4370 ****************************************************************************/
4371
4372 static uint32 rev_changeid(void)
4373 {
4374         struct timeval tv;
4375
4376         get_process_uptime(&tv);
4377
4378 #if 1   /* JERRY */
4379         /* Return changeid as msec since spooler restart */
4380         return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4381 #else
4382         /*
4383          * This setting seems to work well but is too untested
4384          * to replace the above calculation.  Left in for experiementation
4385          * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
4386          */
4387         return tv.tv_sec * 10 + tv.tv_usec / 100000;
4388 #endif
4389 }
4390
4391
4392 /*
4393  * The function below are the high level ones.
4394  * only those ones must be called from the spoolss code.
4395  * JFM.
4396  */
4397
4398 /****************************************************************************
4399  Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4400 ****************************************************************************/
4401
4402 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4403 {
4404         WERROR result;
4405
4406         dump_a_printer(printer, level);
4407
4408         switch (level) {
4409                 case 2:
4410                 {
4411                         /*
4412                          * Update the changestamp.  Emperical tests show that the
4413                          * ChangeID is always updated,but c_setprinter is
4414                          *  global spooler variable (not per printer).
4415                          */
4416
4417                         /* ChangeID **must** be increasing over the lifetime
4418                            of client's spoolss service in order for the
4419                            client's cache to show updates */
4420
4421                         printer->info_2->changeid = rev_changeid();
4422
4423                         /*
4424                          * Because one day someone will ask:
4425                          * NT->NT       An admin connection to a remote
4426                          *              printer show changes imeediately in
4427                          *              the properities dialog
4428                          *
4429                          *              A non-admin connection will only show the
4430                          *              changes after viewing the properites page
4431                          *              2 times.  Seems to be related to a
4432                          *              race condition in the client between the spooler
4433                          *              updating the local cache and the Explorer.exe GUI
4434                          *              actually displaying the properties.
4435                          *
4436                          *              This is fixed in Win2k.  admin/non-admin
4437                          *              connections both display changes immediately.
4438                          *
4439                          * 14/12/01     --jerry
4440                          */
4441
4442                         result=update_a_printer_2(printer->info_2);
4443                         break;
4444                 }
4445                 default:
4446                         result=WERR_UNKNOWN_LEVEL;
4447                         break;
4448         }
4449
4450         return result;
4451 }
4452
4453 /****************************************************************************
4454  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4455
4456  Previously the code had a memory allocation problem because it always
4457  used the TALLOC_CTX from the Printer_entry*.   This context lasts
4458  as a long as the original handle is open.  So if the client made a lot
4459  of getprinter[data]() calls, the memory usage would climb.  Now we use
4460  a short lived TALLOC_CTX for printer_info_2 objects returned.  We
4461  still use the Printer_entry->ctx for maintaining the cache copy though
4462  since that object must live as long as the handle by definition.
4463                                                     --jerry
4464
4465 ****************************************************************************/
4466
4467 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4468                         const char *sharename, bool get_loc_com)
4469 {
4470         WERROR result;
4471         fstring servername;
4472
4473         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4474
4475         if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4476                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4477                 return WERR_NOMEM;
4478         }
4479
4480         switch (level) {
4481                 case 2:
4482                         if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4483                                 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4484                                 TALLOC_FREE( *pp_printer );
4485                                 return WERR_NOMEM;
4486                         }
4487
4488                         if ( print_hnd )
4489                                 fstrcpy( servername, print_hnd->servername );
4490                         else {
4491                                 fstrcpy( servername, "%L" );
4492                                 standard_sub_basic( "", "", servername,
4493                                                     sizeof(servername)-1 );
4494                         }
4495
4496                         result = get_a_printer_2( (*pp_printer)->info_2,
4497                                         servername, sharename, get_loc_com);
4498
4499                         /* we have a new printer now.  Save it with this handle */
4500
4501                         if ( !W_ERROR_IS_OK(result) ) {
4502                                 TALLOC_FREE( *pp_printer );
4503                                 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4504                                         sharename, (unsigned int)level, win_errstr(result)));
4505                                 return result;
4506                         }
4507
4508                         dump_a_printer( *pp_printer, level);
4509
4510                         break;
4511
4512                 default:
4513                         TALLOC_FREE( *pp_printer );
4514                         return WERR_UNKNOWN_LEVEL;
4515         }
4516
4517         return WERR_OK;
4518 }
4519
4520 WERROR get_a_printer( Printer_entry *print_hnd,
4521                         NT_PRINTER_INFO_LEVEL **pp_printer,
4522                         uint32 level,
4523                         const char *sharename)
4524 {
4525         return get_a_printer_internal(print_hnd, pp_printer, level,
4526                                         sharename, true);
4527 }
4528
4529 WERROR get_a_printer_search( Printer_entry *print_hnd,
4530                         NT_PRINTER_INFO_LEVEL **pp_printer,
4531                         uint32 level,
4532                         const char *sharename)
4533 {
4534         return get_a_printer_internal(print_hnd, pp_printer, level,
4535                                         sharename, false);
4536 }
4537
4538 /****************************************************************************
4539  Deletes a NT_PRINTER_INFO_LEVEL struct.
4540 ****************************************************************************/
4541
4542 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4543 {
4544         NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4545
4546         if ( !printer )
4547                 return 0;
4548
4549         switch (level) {
4550                 case 2:
4551                         if ( printer->info_2 )
4552                                 free_nt_printer_info_level_2(&printer->info_2);
4553                         break;
4554
4555                 default:
4556                         DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4557                         return 1;
4558         }
4559
4560         TALLOC_FREE(*pp_printer);
4561
4562         return 0;
4563 }
4564
4565 /****************************************************************************
4566 ****************************************************************************/
4567
4568 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4569                               struct spoolss_DriverInfo8 *_info8)
4570 {
4571         struct spoolss_DriverInfo8 info8;
4572
4573         ZERO_STRUCT(info8);
4574
4575         switch (r->level) {
4576         case 3:
4577                 info8.version           = r->info.info3->version;
4578                 info8.driver_name       = r->info.info3->driver_name;
4579                 info8.architecture      = r->info.info3->architecture;
4580                 info8.driver_path       = r->info.info3->driver_path;
4581                 info8.data_file         = r->info.info3->data_file;
4582                 info8.config_file       = r->info.info3->config_file;
4583                 info8.help_file         = r->info.info3->help_file;
4584                 info8.monitor_name      = r->info.info3->monitor_name;
4585                 info8.default_datatype  = r->info.info3->default_datatype;
4586                 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4587                         info8.dependent_files   = r->info.info3->dependent_files->string;
4588                 }
4589                 break;
4590         case 6:
4591                 info8.version           = r->info.info6->version;
4592                 info8.driver_name       = r->info.info6->driver_name;
4593                 info8.architecture      = r->info.info6->architecture;
4594                 info8.driver_path       = r->info.info6->driver_path;
4595                 info8.data_file         = r->info.info6->data_file;
4596                 info8.config_file       = r->info.info6->config_file;
4597                 info8.help_file         = r->info.info6->help_file;
4598                 info8.monitor_name      = r->info.info6->monitor_name;
4599                 info8.default_datatype  = r->info.info6->default_datatype;
4600                 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4601                         info8.dependent_files   = r->info.info6->dependent_files->string;
4602                 }
4603                 info8.driver_date       = r->info.info6->driver_date;
4604                 info8.driver_version    = r->info.info6->driver_version;
4605                 info8.manufacturer_name = r->info.info6->manufacturer_name;
4606                 info8.manufacturer_url  = r->info.info6->manufacturer_url;
4607                 info8.hardware_id       = r->info.info6->hardware_id;
4608                 info8.provider          = r->info.info6->provider;
4609                 break;
4610         case 8:
4611                 info8.version           = r->info.info8->version;
4612                 info8.driver_name       = r->info.info8->driver_name;
4613                 info8.architecture      = r->info.info8->architecture;
4614                 info8.driver_path       = r->info.info8->driver_path;
4615                 info8.data_file         = r->info.info8->data_file;
4616                 info8.config_file       = r->info.info8->config_file;
4617                 info8.help_file         = r->info.info8->help_file;
4618                 info8.monitor_name      = r->info.info8->monitor_name;
4619                 info8.default_datatype  = r->info.info8->default_datatype;
4620                 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4621                         info8.dependent_files   = r->info.info8->dependent_files->string;
4622                 }
4623                 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4624                         info8.previous_names    = r->info.info8->previous_names->string;
4625                 }
4626                 info8.driver_date       = r->info.info8->driver_date;
4627                 info8.driver_version    = r->info.info8->driver_version;
4628                 info8.manufacturer_name = r->info.info8->manufacturer_name;
4629                 info8.manufacturer_url  = r->info.info8->manufacturer_url;
4630                 info8.hardware_id       = r->info.info8->hardware_id;
4631                 info8.provider          = r->info.info8->provider;
4632                 info8.print_processor   = r->info.info8->print_processor;
4633                 info8.vendor_setup      = r->info.info8->vendor_setup;
4634                 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4635                         info8.color_profiles = r->info.info8->color_profiles->string;
4636                 }
4637                 info8.inf_path          = r->info.info8->inf_path;
4638                 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4639                 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4640                         info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4641                 }
4642                 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4643                 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4644                 break;
4645         default:
4646                 return false;
4647         }
4648
4649         *_info8 = info8;
4650
4651         return true;
4652 }
4653
4654
4655 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4656                               struct spoolss_AddDriverInfoCtr *r,
4657                               char **driver_name,
4658                               uint32_t *version)
4659 {
4660         struct spoolss_DriverInfo8 info8;
4661
4662         ZERO_STRUCT(info8);
4663
4664         DEBUG(10,("adding a printer at level [%d]\n", r->level));
4665
4666         if (!driver_info_ctr_to_info8(r, &info8)) {
4667                 return -1;
4668         }
4669
4670         *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4671         if (!*driver_name) {
4672                 return -1;
4673         }
4674         *version = info8.version;
4675
4676         return add_a_printer_driver_8(&info8);
4677 }
4678
4679 /****************************************************************************
4680 ****************************************************************************/
4681
4682 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4683                             struct spoolss_DriverInfo8 **driver,
4684                             const char *drivername, const char *architecture,
4685                             uint32_t version)
4686 {
4687         WERROR result;
4688         struct spoolss_DriverInfo3 info3;
4689         struct spoolss_DriverInfo8 *info8;
4690
4691         ZERO_STRUCT(info3);
4692
4693         /* Sometime we just want any version of the driver */
4694
4695         if (version == DRIVER_ANY_VERSION) {
4696                 /* look for Win2k first and then for NT4 */
4697                 result = get_a_printer_driver_3(mem_ctx,
4698                                                 &info3,
4699                                                 drivername,
4700                                                 architecture, 3);
4701                 if (!W_ERROR_IS_OK(result)) {
4702                         result = get_a_printer_driver_3(mem_ctx,
4703                                                         &info3,
4704                                                         drivername,
4705                                                         architecture, 2);
4706                 }
4707         } else {
4708                 result = get_a_printer_driver_3(mem_ctx,
4709                                                 &info3,
4710                                                 drivername,
4711                                                 architecture,
4712                                                 version);
4713         }
4714
4715         if (!W_ERROR_IS_OK(result)) {
4716                 return result;
4717         }
4718
4719         info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4720         if (!info8) {
4721                 return WERR_NOMEM;
4722         }
4723
4724         info8->version          = info3.version;
4725         info8->driver_name      = info3.driver_name;
4726         info8->architecture     = info3.architecture;
4727         info8->driver_path      = info3.driver_path;
4728         info8->data_file        = info3.data_file;
4729         info8->config_file      = info3.config_file;
4730         info8->help_file        = info3.help_file;
4731         info8->dependent_files  = info3.dependent_files;
4732         info8->monitor_name     = info3.monitor_name;
4733         info8->default_datatype = info3.default_datatype;
4734
4735         *driver = info8;
4736
4737         return WERR_OK;
4738 }
4739
4740 /****************************************************************************
4741 ****************************************************************************/
4742
4743 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4744 {
4745         talloc_free(driver);
4746         return 0;
4747 }
4748
4749
4750 /****************************************************************************
4751   Determine whether or not a particular driver is currently assigned
4752   to a printer
4753 ****************************************************************************/
4754
4755 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4756 {
4757         int snum;
4758         int n_services = lp_numservices();
4759         NT_PRINTER_INFO_LEVEL *printer = NULL;
4760         bool in_use = False;
4761
4762         if (!r) {
4763                 return false;
4764         }
4765
4766         DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4767
4768         /* loop through the printers.tdb and check for the drivername */
4769
4770         for (snum=0; snum<n_services && !in_use; snum++) {
4771                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4772                         continue;
4773
4774                 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4775                         continue;
4776
4777                 if (strequal(r->driver_name, printer->info_2->drivername))
4778                         in_use = True;
4779
4780                 free_a_printer( &printer, 2 );
4781         }
4782
4783         DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4784
4785         if ( in_use ) {
4786                 struct spoolss_DriverInfo8 *d;
4787                 WERROR werr;
4788
4789                 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4790
4791                 /* we can still remove the driver if there is one of
4792                    "Windows NT x86" version 2 or 3 left */
4793
4794                 if (!strequal("Windows NT x86", r->architecture)) {
4795                         werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4796                 }
4797                 else {
4798                         switch (r->version) {
4799                         case 2:
4800                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4801                                 break;
4802                         case 3:
4803                                 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4804                                 break;
4805                         default:
4806                                 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4807                                         r->version));
4808                                 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4809                                 break;
4810                         }
4811                 }
4812
4813                 /* now check the error code */
4814
4815                 if ( W_ERROR_IS_OK(werr) ) {
4816                         /* it's ok to remove the driver, we have other architctures left */
4817                         in_use = False;
4818                         free_a_printer_driver(d);
4819                 }
4820         }
4821
4822         /* report that the driver is not in use by default */
4823
4824         return in_use;
4825 }
4826
4827
4828 /**********************************************************************
4829  Check to see if a ogiven file is in use by *info
4830  *********************************************************************/
4831
4832 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4833 {
4834         int i = 0;
4835
4836         if ( !info )
4837                 return False;
4838
4839         /* mz: skip files that are in the list but already deleted */
4840         if (!file || !file[0]) {
4841                 return false;
4842         }
4843
4844         if (strequal(file, info->driver_path))
4845                 return True;
4846
4847         if (strequal(file, info->data_file))
4848                 return True;
4849
4850         if (strequal(file, info->config_file))
4851                 return True;
4852
4853         if (strequal(file, info->help_file))
4854                 return True;
4855
4856         /* see of there are any dependent files to examine */
4857
4858         if (!info->dependent_files)
4859                 return False;
4860
4861         while (info->dependent_files[i] && *info->dependent_files[i]) {
4862                 if (strequal(file, info->dependent_files[i]))
4863                         return True;
4864                 i++;
4865         }
4866
4867         return False;
4868
4869 }
4870
4871 /**********************************************************************
4872  Utility function to remove the dependent file pointed to by the
4873  input parameter from the list
4874  *********************************************************************/
4875
4876 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4877 {
4878
4879         /* bump everything down a slot */
4880
4881         while (files && files[idx+1]) {
4882                 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4883                 idx++;
4884         }
4885
4886         files[idx] = NULL;
4887
4888         return;
4889 }
4890
4891 /**********************************************************************
4892  Check if any of the files used by src are also used by drv
4893  *********************************************************************/
4894
4895 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4896                                    struct spoolss_DriverInfo8 *src,
4897                                    const struct spoolss_DriverInfo8 *drv)
4898 {
4899         bool    in_use = False;
4900         int     i = 0;
4901
4902         if ( !src || !drv )
4903                 return False;
4904
4905         /* check each file.  Remove it from the src structure if it overlaps */
4906
4907         if (drv_file_in_use(src->driver_path, drv)) {
4908                 in_use = True;
4909                 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4910                 src->driver_path = talloc_strdup(mem_ctx, "");
4911                 if (!src->driver_path) { return false; }
4912         }
4913
4914         if (drv_file_in_use(src->data_file, drv)) {
4915                 in_use = True;
4916                 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4917                 src->data_file = talloc_strdup(mem_ctx, "");
4918                 if (!src->data_file) { return false; }
4919         }
4920
4921         if (drv_file_in_use(src->config_file, drv)) {
4922                 in_use = True;
4923                 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4924                 src->config_file = talloc_strdup(mem_ctx, "");
4925                 if (!src->config_file) { return false; }
4926         }
4927
4928         if (drv_file_in_use(src->help_file, drv)) {
4929                 in_use = True;
4930                 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4931                 src->help_file = talloc_strdup(mem_ctx, "");
4932                 if (!src->help_file) { return false; }
4933         }
4934
4935         /* are there any dependentfiles to examine? */
4936
4937         if (!src->dependent_files)
4938                 return in_use;
4939
4940         while (src->dependent_files[i] && *src->dependent_files[i]) {
4941                 if (drv_file_in_use(src->dependent_files[i], drv)) {
4942                         in_use = True;
4943                         DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4944                         trim_dependent_file(mem_ctx, src->dependent_files, i);
4945                 } else
4946                         i++;
4947         }
4948
4949         return in_use;
4950 }
4951
4952 /****************************************************************************
4953   Determine whether or not a particular driver files are currently being
4954   used by any other driver.
4955
4956   Return value is True if any files were in use by other drivers
4957   and False otherwise.
4958
4959   Upon return, *info has been modified to only contain the driver files
4960   which are not in use
4961
4962   Fix from mz:
4963
4964   This needs to check all drivers to ensure that all files in use
4965   have been removed from *info, not just the ones in the first
4966   match.
4967 ****************************************************************************/
4968
4969 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4970                                  struct spoolss_DriverInfo8 *info)
4971 {
4972         int                             i;
4973         int                             ndrivers;
4974         uint32                          version;
4975         fstring                         *list = NULL;
4976         struct spoolss_DriverInfo8      *driver;
4977         bool in_use = false;
4978
4979         if ( !info )
4980                 return False;
4981
4982         version = info->version;
4983
4984         /* loop over all driver versions */
4985
4986         DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4987
4988         /* get the list of drivers */
4989
4990         list = NULL;
4991         ndrivers = get_ntdrivers(&list, info->architecture, version);
4992
4993         DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4994                 ndrivers, info->architecture, version));
4995
4996         /* check each driver for overlap in files */
4997
4998         for (i=0; i<ndrivers; i++) {
4999                 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5000
5001                 driver = NULL;
5002
5003                 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
5004                         SAFE_FREE(list);
5005                         return True;
5006                 }
5007
5008                 /* check if d2 uses any files from d1 */
5009                 /* only if this is a different driver than the one being deleted */
5010
5011                 if (!strequal(info->driver_name, driver->driver_name)) {
5012                         if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5013                                 /* mz: Do not instantly return -
5014                                  * we need to ensure this file isn't
5015                                  * also in use by other drivers. */
5016                                 in_use = true;
5017                         }
5018                 }
5019
5020                 free_a_printer_driver(driver);
5021         }
5022
5023         SAFE_FREE(list);
5024
5025         DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5026
5027         return in_use;
5028 }
5029
5030 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5031                                         const char *name)
5032 {
5033         struct smb_filename *smb_fname = NULL;
5034         NTSTATUS status;
5035
5036         status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5037             &smb_fname);
5038         if (!NT_STATUS_IS_OK(status)) {
5039                 return status;
5040         }
5041
5042         status = unlink_internals(conn, NULL, 0, smb_fname, false);
5043
5044         TALLOC_FREE(smb_fname);
5045         return status;
5046 }
5047
5048 /****************************************************************************
5049   Actually delete the driver files.  Make sure that
5050   printer_driver_files_in_use() return False before calling
5051   this.
5052 ****************************************************************************/
5053
5054 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5055                                 const struct spoolss_DriverInfo8 *r)
5056 {
5057         int i = 0;
5058         char *s;
5059         const char *file;
5060         connection_struct *conn;
5061         NTSTATUS nt_status;
5062         char *oldcwd;
5063         fstring printdollar;
5064         int printdollar_snum;
5065         bool ret = false;
5066
5067         if (!r) {
5068                 return false;
5069         }
5070
5071         DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5072                 r->driver_name, r->version));
5073
5074         fstrcpy(printdollar, "print$");
5075
5076         printdollar_snum = find_service(printdollar);
5077         if (printdollar_snum == -1) {
5078                 return false;
5079         }
5080
5081         nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5082                                        lp_pathname(printdollar_snum),
5083                                        rpc_pipe->server_info, &oldcwd);
5084         if (!NT_STATUS_IS_OK(nt_status)) {
5085                 DEBUG(0,("delete_driver_files: create_conn_struct "
5086                          "returned %s\n", nt_errstr(nt_status)));
5087                 return false;
5088         }
5089
5090         if ( !CAN_WRITE(conn) ) {
5091                 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5092                 goto fail;
5093         }
5094
5095         /* now delete the files; must strip the '\print$' string from
5096            fron of path                                                */
5097
5098         if (r->driver_path && r->driver_path[0]) {
5099                 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5100                         file = s;
5101                         DEBUG(10,("deleting driverfile [%s]\n", s));
5102                         driver_unlink_internals(conn, file);
5103                 }
5104         }
5105
5106         if (r->config_file && r->config_file[0]) {
5107                 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5108                         file = s;
5109                         DEBUG(10,("deleting configfile [%s]\n", s));
5110                         driver_unlink_internals(conn, file);
5111                 }
5112         }
5113
5114         if (r->data_file && r->data_file[0]) {
5115                 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5116                         file = s;
5117                         DEBUG(10,("deleting datafile [%s]\n", s));
5118                         driver_unlink_internals(conn, file);
5119                 }
5120         }
5121
5122         if (r->help_file && r->help_file[0]) {
5123                 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5124                         file = s;
5125                         DEBUG(10,("deleting helpfile [%s]\n", s));
5126                         driver_unlink_internals(conn, file);
5127                 }
5128         }
5129
5130         /* check if we are done removing files */
5131
5132         if (r->dependent_files) {
5133                 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5134                         char *p;
5135
5136                         /* bypass the "\print$" portion of the path */
5137
5138                         if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5139                                 file = p;
5140                                 DEBUG(10,("deleting dependent file [%s]\n", file));
5141                                 driver_unlink_internals(conn, file);
5142                         }
5143
5144                         i++;
5145                 }
5146         }
5147
5148         goto done;
5149  fail:
5150         ret = false;
5151  done:
5152         if (conn != NULL) {
5153                 vfs_ChDir(conn, oldcwd);
5154                 conn_free(conn);
5155         }
5156         return ret;
5157 }
5158
5159 /****************************************************************************
5160  Remove a printer driver from the TDB.  This assumes that the the driver was
5161  previously looked up.
5162  ***************************************************************************/
5163
5164 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5165                              const struct spoolss_DriverInfo8 *r,
5166                              uint32 version, bool delete_files )
5167 {
5168         char *key = NULL;
5169         const char     *arch;
5170         TDB_DATA        dbuf;
5171
5172         /* delete the tdb data first */
5173
5174         arch = get_short_archi(r->architecture);
5175         if (!arch) {
5176                 return WERR_UNKNOWN_PRINTER_DRIVER;
5177         }
5178         if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5179                         arch, version, r->driver_name) < 0) {
5180                 return WERR_NOMEM;
5181         }
5182
5183         DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5184                 key, delete_files ? "TRUE" : "FALSE" ));
5185
5186         /* check if the driver actually exists for this environment */
5187
5188         dbuf = tdb_fetch_bystring( tdb_drivers, key );
5189         if ( !dbuf.dptr ) {
5190                 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5191                 SAFE_FREE(key);
5192                 return WERR_UNKNOWN_PRINTER_DRIVER;
5193         }
5194
5195         SAFE_FREE( dbuf.dptr );
5196
5197         /* ok... the driver exists so the delete should return success */
5198
5199         if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5200                 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5201                 SAFE_FREE(key);
5202                 return WERR_ACCESS_DENIED;
5203         }
5204
5205         /*
5206          * now delete any associated files if delete_files == True
5207          * even if this part failes, we return succes because the
5208          * driver doesn not exist any more
5209          */
5210
5211         if ( delete_files )
5212                 delete_driver_files(rpc_pipe, r);
5213
5214         DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5215         SAFE_FREE(key);
5216
5217         return WERR_OK;
5218 }
5219
5220 /****************************************************************************
5221  Store a security desc for a printer.
5222 ****************************************************************************/
5223
5224 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
5225 {
5226         struct sec_desc_buf *new_secdesc_ctr = NULL;
5227         struct sec_desc_buf *old_secdesc_ctr = NULL;
5228         TALLOC_CTX *mem_ctx = NULL;
5229         TDB_DATA kbuf;
5230         TDB_DATA dbuf;
5231         DATA_BLOB blob;
5232         WERROR status;
5233         NTSTATUS nt_status;
5234
5235         mem_ctx = talloc_init("nt_printing_setsec");
5236         if (mem_ctx == NULL)
5237                 return WERR_NOMEM;
5238
5239         /* The old owner and group sids of the security descriptor are not
5240            present when new ACEs are added or removed by changing printer
5241            permissions through NT.  If they are NULL in the new security
5242            descriptor then copy them over from the old one. */
5243
5244         if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5245                 struct dom_sid *owner_sid, *group_sid;
5246                 struct security_acl *dacl, *sacl;
5247                 struct security_descriptor *psd = NULL;
5248                 size_t size;
5249
5250                 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5251                         status = WERR_NOMEM;
5252                         goto out;
5253                 }
5254
5255                 /* Pick out correct owner and group sids */
5256
5257                 owner_sid = secdesc_ctr->sd->owner_sid ?
5258                         secdesc_ctr->sd->owner_sid :
5259                         old_secdesc_ctr->sd->owner_sid;
5260
5261                 group_sid = secdesc_ctr->sd->group_sid ?
5262                         secdesc_ctr->sd->group_sid :
5263                         old_secdesc_ctr->sd->group_sid;
5264
5265                 dacl = secdesc_ctr->sd->dacl ?
5266                         secdesc_ctr->sd->dacl :
5267                         old_secdesc_ctr->sd->dacl;
5268
5269                 sacl = secdesc_ctr->sd->sacl ?
5270                         secdesc_ctr->sd->sacl :
5271                         old_secdesc_ctr->sd->sacl;
5272
5273                 /* Make a deep copy of the security descriptor */
5274
5275                 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5276                                     owner_sid, group_sid,
5277                                     sacl,
5278                                     dacl,
5279                                     &size);
5280
5281                 if (!psd) {
5282                         status = WERR_NOMEM;
5283                         goto out;
5284                 }
5285
5286                 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5287         }
5288
5289         if (!new_secdesc_ctr) {
5290                 new_secdesc_ctr = secdesc_ctr;
5291         }
5292
5293         /* Store the security descriptor in a tdb */
5294
5295         nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5296                                           &blob.data, &blob.length);
5297         if (!NT_STATUS_IS_OK(nt_status)) {
5298                 status = ntstatus_to_werror(nt_status);
5299                 goto out;
5300         }
5301
5302         kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5303
5304         dbuf.dptr = (unsigned char *)blob.data;
5305         dbuf.dsize = blob.length;
5306
5307         if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5308                 status = WERR_OK;
5309         } else {
5310                 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5311                 status = WERR_BADFUNC;
5312         }
5313
5314         /* Free malloc'ed memory */
5315         talloc_free(blob.data);
5316
5317  out:
5318
5319         if (mem_ctx)
5320                 talloc_destroy(mem_ctx);
5321         return status;
5322 }
5323
5324 /****************************************************************************
5325  Construct a default security descriptor buffer for a printer.
5326 ****************************************************************************/
5327
5328 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
5329 {
5330         struct security_ace ace[7];     /* max number of ace entries */
5331         int i = 0;
5332         uint32_t sa;
5333         struct security_acl *psa = NULL;
5334         struct sec_desc_buf *sdb = NULL;
5335         struct security_descriptor *psd = NULL;
5336         struct dom_sid adm_sid;
5337         size_t sd_size;
5338
5339         /* Create an ACE where Everyone is allowed to print */
5340
5341         sa = PRINTER_ACE_PRINT;
5342         init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5343                      sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5344
5345         /* Add the domain admins group if we are a DC */
5346
5347         if ( IS_DC ) {
5348                 struct dom_sid domadmins_sid;
5349
5350                 sid_compose(&domadmins_sid, get_global_sam_sid(),
5351                             DOMAIN_RID_ADMINS);
5352
5353                 sa = PRINTER_ACE_FULL_CONTROL;
5354                 init_sec_ace(&ace[i++], &domadmins_sid,
5355                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5356                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5357                 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5358                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5359         }
5360         else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5361                 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
5362
5363                 sa = PRINTER_ACE_FULL_CONTROL;
5364                 init_sec_ace(&ace[i++], &adm_sid,
5365                         SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5366                         SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5367                 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5368                         sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5369         }
5370
5371         /* add BUILTIN\Administrators as FULL CONTROL */
5372
5373         sa = PRINTER_ACE_FULL_CONTROL;
5374         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5375                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5376                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5377         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5378                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5379                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5380
5381         /* add BUILTIN\Print Operators as FULL CONTROL */
5382
5383         sa = PRINTER_ACE_FULL_CONTROL;
5384         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5385                 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5386                 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5387         init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
5388                 SEC_ACE_TYPE_ACCESS_ALLOWED,
5389                 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5390
5391         /* Make the security descriptor owned by the BUILTIN\Administrators */
5392
5393         /* The ACL revision number in rpc_secdesc.h differs from the one
5394            created by NT when setting ACE entries in printer
5395            descriptors.  NT4 complains about the property being edited by a
5396            NT5 machine. */
5397
5398         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5399                 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
5400                         &global_sid_Builtin_Administrators,
5401                         &global_sid_Builtin_Administrators,
5402                         NULL, psa, &sd_size);
5403         }
5404
5405         if (!psd) {
5406                 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5407                 return NULL;
5408         }
5409
5410         sdb = make_sec_desc_buf(ctx, sd_size, psd);
5411
5412         DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5413                  (unsigned int)sd_size));
5414
5415         return sdb;
5416 }
5417
5418 /****************************************************************************
5419  Get a security desc for a printer.
5420 ****************************************************************************/
5421
5422 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
5423 {
5424         TDB_DATA kbuf;
5425         TDB_DATA dbuf;
5426         DATA_BLOB blob;
5427         char *temp;
5428         NTSTATUS status;
5429
5430         if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5431                 sharename = temp + 1;
5432         }
5433
5434         /* Fetch security descriptor from tdb */
5435
5436         kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5437
5438         dbuf = tdb_fetch(tdb_printers, kbuf);
5439         if (dbuf.dptr) {
5440
5441                 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5442                                                  secdesc_ctr);
5443                 SAFE_FREE(dbuf.dptr);
5444
5445                 if (NT_STATUS_IS_OK(status)) {
5446                         return true;
5447                 }
5448         }
5449
5450         *secdesc_ctr = construct_default_printer_sdb(ctx);
5451         if (!*secdesc_ctr) {
5452                 return false;
5453         }
5454
5455         status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5456                                        &blob.data, &blob.length);
5457         if (NT_STATUS_IS_OK(status)) {
5458                 dbuf.dptr = (unsigned char *)blob.data;
5459                 dbuf.dsize = blob.length;
5460                 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5461                 talloc_free(blob.data);
5462         }
5463
5464         /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5465            this security descriptor has been created when winbindd was
5466            down.  Take ownership of security descriptor. */
5467
5468         if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5469                 struct dom_sid owner_sid;
5470
5471                 /* Change sd owner to workgroup administrator */
5472
5473                 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5474                         struct sec_desc_buf *new_secdesc_ctr = NULL;
5475                         struct security_descriptor *psd = NULL;
5476                         size_t size;
5477
5478                         /* Create new sd */
5479
5480                         sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
5481
5482                         psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5483                                             &owner_sid,
5484                                             (*secdesc_ctr)->sd->group_sid,
5485                                             (*secdesc_ctr)->sd->sacl,
5486                                             (*secdesc_ctr)->sd->dacl,
5487                                             &size);
5488
5489                         if (!psd) {
5490                                 return False;
5491                         }
5492
5493                         new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5494                         if (!new_secdesc_ctr) {
5495                                 return False;
5496                         }
5497
5498                         /* Swap with other one */
5499
5500                         *secdesc_ctr = new_secdesc_ctr;
5501
5502                         /* Set it */
5503
5504                         nt_printing_setsec(sharename, *secdesc_ctr);
5505                 }
5506         }
5507
5508         if (DEBUGLEVEL >= 10) {
5509                 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5510                 int i;
5511
5512                 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5513                            sharename, the_acl->num_aces));
5514
5515                 for (i = 0; i < the_acl->num_aces; i++) {
5516                         DEBUG(10, ("%s %d %d 0x%08x\n",
5517                                    sid_string_dbg(&the_acl->aces[i].trustee),
5518                                    the_acl->aces[i].type, the_acl->aces[i].flags,
5519                                    the_acl->aces[i].access_mask));
5520                 }
5521         }
5522
5523         return True;
5524 }
5525
5526 /* error code:
5527         0: everything OK
5528         1: level not implemented
5529         2: file doesn't exist
5530         3: can't allocate memory
5531         4: can't free memory
5532         5: non existant struct
5533 */
5534
5535 /*
5536         A printer and a printer driver are 2 different things.
5537         NT manages them separatelly, Samba does the same.
5538         Why ? Simply because it's easier and it makes sense !
5539
5540         Now explanation: You have 3 printers behind your samba server,
5541         2 of them are the same make and model (laser A and B). But laser B
5542         has an 3000 sheet feeder and laser A doesn't such an option.
5543         Your third printer is an old dot-matrix model for the accounting :-).
5544
5545         If the /usr/local/samba/lib directory (default dir), you will have
5546         5 files to describe all of this.
5547
5548         3 files for the printers (1 by printer):
5549                 NTprinter_laser A
5550                 NTprinter_laser B
5551                 NTprinter_accounting
5552         2 files for the drivers (1 for the laser and 1 for the dot matrix)
5553                 NTdriver_printer model X
5554                 NTdriver_printer model Y
5555
5556 jfm: I should use this comment for the text file to explain
5557         same thing for the forms BTW.
5558         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5559
5560 */
5561
5562 /* Convert generic access rights to printer object specific access rights.
5563    It turns out that NT4 security descriptors use generic access rights and
5564    NT5 the object specific ones. */
5565
5566 void map_printer_permissions(struct security_descriptor *sd)
5567 {
5568         int i;
5569
5570         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5571                 se_map_generic(&sd->dacl->aces[i].access_mask,
5572                                &printer_generic_mapping);
5573         }
5574 }
5575
5576 void map_job_permissions(struct security_descriptor *sd)
5577 {
5578         int i;
5579
5580         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5581                 se_map_generic(&sd->dacl->aces[i].access_mask,
5582                                &job_generic_mapping);
5583         }
5584 }
5585
5586
5587 /****************************************************************************
5588  Check a user has permissions to perform the given operation.  We use the
5589  permission constants defined in include/rpc_spoolss.h to check the various
5590  actions we perform when checking printer access.
5591
5592    PRINTER_ACCESS_ADMINISTER:
5593        print_queue_pause, print_queue_resume, update_printer_sec,
5594        update_printer, spoolss_addprinterex_level_2,
5595        _spoolss_setprinterdata
5596
5597    PRINTER_ACCESS_USE:
5598        print_job_start
5599
5600    JOB_ACCESS_ADMINISTER:
5601        print_job_delete, print_job_pause, print_job_resume,
5602        print_queue_purge
5603
5604   Try access control in the following order (for performance reasons):
5605     1)  root and SE_PRINT_OPERATOR can do anything (easy check)
5606     2)  check security descriptor (bit comparisons in memory)
5607     3)  "printer admins" (may result in numerous calls to winbind)
5608
5609  ****************************************************************************/
5610 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5611                         int access_type)
5612 {
5613         struct sec_desc_buf *secdesc = NULL;
5614         uint32 access_granted;
5615         NTSTATUS status;
5616         const char *pname;
5617         TALLOC_CTX *mem_ctx = NULL;
5618         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5619
5620         /* If user is NULL then use the current_user structure */
5621
5622         /* Always allow root or SE_PRINT_OPERATROR to do anything */
5623
5624         if (server_info->utok.uid == sec_initial_uid()
5625             || user_has_privileges(server_info->ptok, &se_printop ) ) {
5626                 return True;
5627         }
5628
5629         /* Get printer name */
5630
5631         pname = lp_printername(snum);
5632
5633         if (!pname || !*pname) {
5634                 errno = EACCES;
5635                 return False;
5636         }
5637
5638         /* Get printer security descriptor */
5639
5640         if(!(mem_ctx = talloc_init("print_access_check"))) {
5641                 errno = ENOMEM;
5642                 return False;
5643         }
5644
5645         if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5646                 talloc_destroy(mem_ctx);
5647                 errno = ENOMEM;
5648                 return False;
5649         }
5650
5651         if (access_type == JOB_ACCESS_ADMINISTER) {
5652                 struct sec_desc_buf *parent_secdesc = secdesc;
5653
5654                 /* Create a child security descriptor to check permissions
5655                    against.  This is because print jobs are child objects
5656                    objects of a printer. */
5657
5658                 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5659
5660                 if (!NT_STATUS_IS_OK(status)) {
5661                         talloc_destroy(mem_ctx);
5662                         errno = map_errno_from_nt_status(status);
5663                         return False;
5664                 }
5665
5666                 map_job_permissions(secdesc->sd);
5667         } else {
5668                 map_printer_permissions(secdesc->sd);
5669         }
5670
5671         /* Check access */
5672         status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5673                                  &access_granted);
5674
5675         DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5676
5677         /* see if we need to try the printer admin list */
5678
5679         if (!NT_STATUS_IS_OK(status) &&
5680             (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5681                                          server_info->info3->base.domain.string,
5682                                          NULL, server_info->ptok,
5683                                          lp_printer_admin(snum)))) {
5684                 talloc_destroy(mem_ctx);
5685                 return True;
5686         }
5687
5688         talloc_destroy(mem_ctx);
5689
5690         if (!NT_STATUS_IS_OK(status)) {
5691                 errno = EACCES;
5692         }
5693
5694         return NT_STATUS_IS_OK(status);
5695 }
5696
5697 /****************************************************************************
5698  Check the time parameters allow a print operation.
5699 *****************************************************************************/
5700
5701 bool print_time_access_check(const char *servicename)
5702 {
5703         NT_PRINTER_INFO_LEVEL *printer = NULL;
5704         bool ok = False;
5705         time_t now = time(NULL);
5706         struct tm *t;
5707         uint32 mins;
5708
5709         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5710                 return False;
5711
5712         if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5713                 ok = True;
5714
5715         t = gmtime(&now);
5716         mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5717
5718         if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5719                 ok = True;
5720
5721         free_a_printer(&printer, 2);
5722
5723         if (!ok)
5724                 errno = EACCES;
5725
5726         return ok;
5727 }
5728
5729 /****************************************************************************
5730  Fill in the servername sent in the _spoolss_open_printer_ex() call
5731 ****************************************************************************/
5732
5733 char* get_server_name( Printer_entry *printer )
5734 {
5735         return printer->servername;
5736 }
5737
5738