source: branches/samba-3.0/source/printing/nt_printing.c

Last change on this file was 134, checked in by Paul Smedley, 17 years ago

Update source to 3.0.29

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