s3-printing: Removed unused mod_a_printer functions.
[Samba/gbeck.git] / source3 / printing / nt_printing.c
blob927022619512b4c53055b9818cd242962bffaed1
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.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
25 #include "registry.h"
26 #include "registry/reg_objects.h"
27 #include "../librpc/gen_ndr/ndr_security.h"
28 #include "rpc_server/srv_spoolss_util.h"
30 #include "../rpc_server/srv_spoolss_util.h"
32 static TDB_CONTEXT *tdb_forms; /* used for forms files */
33 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
34 static TDB_CONTEXT *tdb_printers; /* used for printers files */
36 #define FORMS_PREFIX "FORMS/"
37 #define DRIVERS_PREFIX "DRIVERS/"
38 #define PRINTERS_PREFIX "PRINTERS/"
39 #define SECDESC_PREFIX "SECDESC/"
40 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
42 #define NTDRIVERS_DATABASE_VERSION_1 1
43 #define NTDRIVERS_DATABASE_VERSION_2 2
44 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
45 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
46 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
48 /* Map generic permissions to printer object specific permissions */
50 const struct generic_mapping printer_generic_mapping = {
51 PRINTER_READ,
52 PRINTER_WRITE,
53 PRINTER_EXECUTE,
54 PRINTER_ALL_ACCESS
57 const struct standard_mapping printer_std_mapping = {
58 PRINTER_READ,
59 PRINTER_WRITE,
60 PRINTER_EXECUTE,
61 PRINTER_ALL_ACCESS
64 /* Map generic permissions to print server object specific permissions */
66 const struct generic_mapping printserver_generic_mapping = {
67 SERVER_READ,
68 SERVER_WRITE,
69 SERVER_EXECUTE,
70 SERVER_ALL_ACCESS
73 const struct generic_mapping printserver_std_mapping = {
74 SERVER_READ,
75 SERVER_WRITE,
76 SERVER_EXECUTE,
77 SERVER_ALL_ACCESS
80 /* Map generic permissions to job object specific permissions */
82 const struct generic_mapping job_generic_mapping = {
83 JOB_READ,
84 JOB_WRITE,
85 JOB_EXECUTE,
86 JOB_ALL_ACCESS
89 /* We need one default form to support our default printer. Msoft adds the
90 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
91 array index). Letter is always first, so (for the current code) additions
92 always put things in the correct order. */
93 static const nt_forms_struct default_forms[] = {
94 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
95 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
96 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
98 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
99 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
100 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
101 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
102 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
103 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
104 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
105 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
106 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
107 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
108 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
109 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
110 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
111 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
112 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
113 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
114 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
115 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
116 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
117 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
118 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
119 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
120 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
121 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
122 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
123 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
124 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
125 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
126 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
127 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
128 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
129 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
130 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
131 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
132 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
133 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
134 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
135 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
136 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
137 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
138 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
139 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
140 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
141 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
142 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
143 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
144 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
145 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
146 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
147 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
148 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
149 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
150 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
151 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
152 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
153 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
154 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
155 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
156 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
157 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
158 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
159 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
160 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
161 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
162 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
163 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
164 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
165 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
166 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
167 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
168 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
169 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
170 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
171 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
172 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
173 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
174 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
175 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
176 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
177 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
178 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
179 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
180 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
181 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
182 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
183 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
184 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
185 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
186 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
187 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
188 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
189 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
190 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
191 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
192 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
193 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
194 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
195 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
196 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
197 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
198 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
199 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
200 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
201 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
202 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
203 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
204 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
205 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
206 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
207 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
208 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
209 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
210 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
211 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
212 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
213 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
216 static const struct print_architecture_table_node archi_table[]= {
218 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
219 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
220 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
221 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
222 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
223 {"Windows IA64", SPL_ARCH_IA64, 3 },
224 {"Windows x64", SPL_ARCH_X64, 3 },
225 {NULL, "", -1 }
229 /****************************************************************************
230 generate a new TDB_DATA key for storing a printer
231 ****************************************************************************/
233 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
235 fstring share;
236 char *keystr = NULL;
237 TDB_DATA key;
239 fstrcpy(share, sharename);
240 strlower_m(share);
242 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
243 key = string_term_tdb_data(keystr ? keystr : "");
245 return key;
248 /****************************************************************************
249 generate a new TDB_DATA key for storing a printer security descriptor
250 ****************************************************************************/
252 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
253 const char* sharename )
255 fstring share;
256 char *keystr = NULL;
257 TDB_DATA key;
259 fstrcpy(share, sharename );
260 strlower_m(share);
262 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
263 key = string_term_tdb_data(keystr ? keystr : "");
265 return key;
268 /****************************************************************************
269 ****************************************************************************/
271 static bool upgrade_to_version_3(void)
273 TDB_DATA kbuf, newkey, dbuf;
275 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
277 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
278 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
280 dbuf = tdb_fetch(tdb_drivers, kbuf);
282 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
283 DEBUG(0,("upgrade_to_version_3:moving form\n"));
284 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
285 SAFE_FREE(dbuf.dptr);
286 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
287 return False;
289 if (tdb_delete(tdb_drivers, kbuf) != 0) {
290 SAFE_FREE(dbuf.dptr);
291 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
292 return False;
296 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
297 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
298 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
299 SAFE_FREE(dbuf.dptr);
300 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
301 return False;
303 if (tdb_delete(tdb_drivers, kbuf) != 0) {
304 SAFE_FREE(dbuf.dptr);
305 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
306 return False;
310 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
311 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
312 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
313 SAFE_FREE(dbuf.dptr);
314 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
315 return False;
317 if (tdb_delete(tdb_drivers, kbuf) != 0) {
318 SAFE_FREE(dbuf.dptr);
319 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
320 return False;
324 SAFE_FREE(dbuf.dptr);
327 return True;
330 /*******************************************************************
331 Fix an issue with security descriptors. Printer sec_desc must
332 use more than the generic bits that were previously used
333 in <= 3.0.14a. They must also have a owner and group SID assigned.
334 Otherwise, any printers than have been migrated to a Windows
335 host using printmig.exe will not be accessible.
336 *******************************************************************/
338 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
339 TDB_DATA data, void *state )
341 NTSTATUS status;
342 struct sec_desc_buf *sd_orig = NULL;
343 struct sec_desc_buf *sd_new, *sd_store;
344 struct security_descriptor *sec, *new_sec;
345 TALLOC_CTX *ctx = state;
346 int result, i;
347 uint32 sd_size;
348 size_t size_new_sec;
350 if (!data.dptr || data.dsize == 0) {
351 return 0;
354 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
355 return 0;
358 /* upgrade the security descriptor */
360 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
361 if (!NT_STATUS_IS_OK(status)) {
362 /* delete bad entries */
363 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
364 (const char *)key.dptr ));
365 tdb_delete( tdb_printers, key );
366 return 0;
369 if (!sd_orig) {
370 return 0;
372 sec = sd_orig->sd;
374 /* is this even valid? */
376 if ( !sec->dacl ) {
377 return 0;
380 /* update access masks */
382 for ( i=0; i<sec->dacl->num_aces; i++ ) {
383 switch ( sec->dacl->aces[i].access_mask ) {
384 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
385 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
386 break;
388 case GENERIC_ALL_ACCESS:
389 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
390 break;
392 case READ_CONTROL_ACCESS:
393 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
395 default: /* no change */
396 break;
400 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
402 new_sec = make_sec_desc( ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
403 &global_sid_Builtin_Administrators,
404 &global_sid_Builtin_Administrators,
405 NULL, NULL, &size_new_sec );
406 if (!new_sec) {
407 return 0;
409 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
410 if (!sd_new) {
411 return 0;
414 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
415 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
416 return 0;
419 /* store it back */
421 sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
422 + sizeof(struct sec_desc_buf);
424 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
425 if (!NT_STATUS_IS_OK(status)) {
426 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
427 return 0;
430 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
432 /* 0 to continue and non-zero to stop traversal */
434 return (result == -1);
437 /*******************************************************************
438 *******************************************************************/
440 static bool upgrade_to_version_4(void)
442 TALLOC_CTX *ctx;
443 int result;
445 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
447 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
448 return False;
450 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
452 talloc_destroy( ctx );
454 return ( result != -1 );
457 /*******************************************************************
458 Fix an issue with security descriptors. Printer sec_desc must
459 use more than the generic bits that were previously used
460 in <= 3.0.14a. They must also have a owner and group SID assigned.
461 Otherwise, any printers than have been migrated to a Windows
462 host using printmig.exe will not be accessible.
463 *******************************************************************/
465 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
466 TDB_DATA data, void *state )
468 TALLOC_CTX *ctx = talloc_tos();
469 TDB_DATA new_key;
471 if (!data.dptr || data.dsize == 0)
472 return 0;
474 /* upgrade printer records and security descriptors */
476 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
477 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
479 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
480 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
482 else {
483 /* ignore this record */
484 return 0;
487 /* delete the original record and store under the normalized key */
489 if ( tdb_delete( the_tdb, key ) != 0 ) {
490 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
491 key.dptr));
492 return 1;
495 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
496 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
497 key.dptr));
498 return 1;
501 return 0;
504 /*******************************************************************
505 *******************************************************************/
507 static bool upgrade_to_version_5(void)
509 TALLOC_CTX *ctx;
510 int result;
512 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
514 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
515 return False;
517 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
519 talloc_destroy( ctx );
521 return ( result != -1 );
524 /****************************************************************************
525 Open the NT printing tdbs. Done once before fork().
526 ****************************************************************************/
528 bool nt_printing_init(struct messaging_context *msg_ctx)
530 const char *vstring = "INFO/version";
531 WERROR win_rc;
532 int32 vers_id;
534 if ( tdb_drivers && tdb_printers && tdb_forms )
535 return True;
537 if (tdb_drivers)
538 tdb_close(tdb_drivers);
539 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
540 if (!tdb_drivers) {
541 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
542 state_path("ntdrivers.tdb"), strerror(errno) ));
543 return False;
546 if (tdb_printers)
547 tdb_close(tdb_printers);
548 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
549 if (!tdb_printers) {
550 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
551 state_path("ntprinters.tdb"), strerror(errno) ));
552 return False;
555 if (tdb_forms)
556 tdb_close(tdb_forms);
557 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
558 if (!tdb_forms) {
559 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
560 state_path("ntforms.tdb"), strerror(errno) ));
561 return False;
564 /* handle a Samba upgrade */
566 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
567 if (vers_id == -1) {
568 DEBUG(10, ("Fresh database\n"));
569 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
570 vers_id = NTDRIVERS_DATABASE_VERSION_5;
573 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
575 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
576 if (!upgrade_to_version_3())
577 return False;
578 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579 vers_id = NTDRIVERS_DATABASE_VERSION_3;
582 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
583 /* Written on a bigendian machine with old fetch_int code. Save as le. */
584 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
585 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
586 vers_id = NTDRIVERS_DATABASE_VERSION_3;
589 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
590 if ( !upgrade_to_version_4() )
591 return False;
592 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
593 vers_id = NTDRIVERS_DATABASE_VERSION_4;
596 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
597 if ( !upgrade_to_version_5() )
598 return False;
599 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
600 vers_id = NTDRIVERS_DATABASE_VERSION_5;
604 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
605 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
606 return False;
611 * register callback to handle updating printers as new
612 * drivers are installed
615 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
616 do_drv_upgrade_printer);
618 /* of course, none of the message callbacks matter if you don't
619 tell messages.c that you interested in receiving PRINT_GENERAL
620 msgs. This is done in serverid_register() */
623 if ( lp_security() == SEC_ADS ) {
624 win_rc = check_published_printers();
625 if (!W_ERROR_IS_OK(win_rc))
626 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
629 return True;
632 /*******************************************************************
633 Function to allow filename parsing "the old way".
634 ********************************************************************/
636 static NTSTATUS driver_unix_convert(connection_struct *conn,
637 const char *old_name,
638 struct smb_filename **smb_fname)
640 NTSTATUS status;
641 TALLOC_CTX *ctx = talloc_tos();
642 char *name = talloc_strdup(ctx, old_name);
644 if (!name) {
645 return NT_STATUS_NO_MEMORY;
647 unix_format(name);
648 name = unix_clean_name(ctx, name);
649 if (!name) {
650 return NT_STATUS_NO_MEMORY;
652 trim_string(name,"/","/");
654 status = unix_convert(ctx, conn, name, smb_fname, 0);
655 if (!NT_STATUS_IS_OK(status)) {
656 return NT_STATUS_NO_MEMORY;
659 return NT_STATUS_OK;
662 /*******************************************************************
663 tdb traversal function for counting printers.
664 ********************************************************************/
666 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
667 TDB_DATA data, void *context)
669 int *printer_count = (int*)context;
671 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
672 (*printer_count)++;
673 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
676 return 0;
679 /*******************************************************************
680 Update the spooler global c_setprinter. This variable is initialized
681 when the parent smbd starts with the number of existing printers. It
682 is monotonically increased by the current number of printers *after*
683 each add or delete printer RPC. Only Microsoft knows why... JRR020119
684 ********************************************************************/
686 uint32 update_c_setprinter(bool initialize)
688 int32 c_setprinter;
689 int32 printer_count = 0;
691 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
693 /* Traverse the tdb, counting the printers */
694 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
696 /* If initializing, set c_setprinter to current printers count
697 * otherwise, bump it by the current printer count
699 if (!initialize)
700 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
701 else
702 c_setprinter = printer_count;
704 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
705 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
707 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
709 return (uint32)c_setprinter;
712 /*******************************************************************
713 Get the spooler global c_setprinter, accounting for initialization.
714 ********************************************************************/
716 uint32 get_c_setprinter(void)
718 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
720 if (c_setprinter == (int32)-1)
721 c_setprinter = update_c_setprinter(True);
723 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
725 return (uint32)c_setprinter;
728 /****************************************************************************
729 Get builtin form struct list.
730 ****************************************************************************/
732 int get_builtin_ntforms(nt_forms_struct **list)
734 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
735 if (!*list) {
736 return 0;
738 return ARRAY_SIZE(default_forms);
741 /****************************************************************************
742 get a builtin form struct
743 ****************************************************************************/
745 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
747 int i;
748 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
749 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
750 if (strequal(form_name,default_forms[i].name)) {
751 DEBUGADD(6,("Found builtin form %s \n", form_name));
752 memcpy(form,&default_forms[i],sizeof(*form));
753 return true;
757 return false;
760 /****************************************************************************
761 get a form struct list.
762 ****************************************************************************/
764 int get_ntforms(nt_forms_struct **list)
766 TDB_DATA kbuf, newkey, dbuf;
767 nt_forms_struct form;
768 int ret;
769 int i;
770 int n = 0;
772 *list = NULL;
774 for (kbuf = tdb_firstkey(tdb_forms);
775 kbuf.dptr;
776 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
778 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
779 continue;
781 dbuf = tdb_fetch(tdb_forms, kbuf);
782 if (!dbuf.dptr)
783 continue;
785 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
786 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
787 &i, &form.flag, &form.width, &form.length, &form.left,
788 &form.top, &form.right, &form.bottom);
789 SAFE_FREE(dbuf.dptr);
790 if (ret != dbuf.dsize)
791 continue;
793 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
794 if (!*list) {
795 DEBUG(0,("get_ntforms: Realloc fail.\n"));
796 return 0;
798 (*list)[n] = form;
799 n++;
803 return n;
806 /****************************************************************************
807 write a form struct list
808 ****************************************************************************/
810 int write_ntforms(nt_forms_struct **list, int number)
812 TALLOC_CTX *ctx = talloc_tos();
813 char *buf = NULL;
814 char *key = NULL;
815 int len;
816 TDB_DATA dbuf;
817 int i;
819 for (i=0;i<number;i++) {
820 /* save index, so list is rebuilt in correct order */
821 len = tdb_pack(NULL, 0, "dddddddd",
822 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
823 (*list)[i].left, (*list)[i].top, (*list)[i].right,
824 (*list)[i].bottom);
825 if (!len) {
826 continue;
828 buf = TALLOC_ARRAY(ctx, char, len);
829 if (!buf) {
830 return 0;
832 len = tdb_pack((uint8 *)buf, len, "dddddddd",
833 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
834 (*list)[i].left, (*list)[i].top, (*list)[i].right,
835 (*list)[i].bottom);
836 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
837 if (!key) {
838 return 0;
840 dbuf.dsize = len;
841 dbuf.dptr = (uint8 *)buf;
842 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
843 TALLOC_FREE(key);
844 TALLOC_FREE(buf);
845 break;
847 TALLOC_FREE(key);
848 TALLOC_FREE(buf);
851 return i;
854 /****************************************************************************
855 add a form struct at the end of the list
856 ****************************************************************************/
857 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
859 int n=0;
860 bool update;
863 * NT tries to add forms even when
864 * they are already in the base
865 * only update the values if already present
868 update=False;
870 for (n=0; n<*count; n++) {
871 if ( strequal((*list)[n].name, form->form_name) ) {
872 update=True;
873 break;
877 if (update==False) {
878 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
879 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
880 return False;
882 fstrcpy((*list)[n].name, form->form_name);
883 (*count)++;
886 (*list)[n].flag = form->flags;
887 (*list)[n].width = form->size.width;
888 (*list)[n].length = form->size.height;
889 (*list)[n].left = form->area.left;
890 (*list)[n].top = form->area.top;
891 (*list)[n].right = form->area.right;
892 (*list)[n].bottom = form->area.bottom;
894 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
895 update ? "updated" : "added", form->form_name));
897 return True;
900 /****************************************************************************
901 Delete a named form struct.
902 ****************************************************************************/
904 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
906 char *key = NULL;
907 int n=0;
909 *ret = WERR_OK;
911 for (n=0; n<*count; n++) {
912 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
913 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
914 break;
918 if (n == *count) {
919 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
920 *ret = WERR_INVALID_FORM_NAME;
921 return False;
924 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
925 *ret = WERR_NOMEM;
926 return false;
928 if (tdb_delete_bystring(tdb_forms, key) != 0) {
929 SAFE_FREE(key);
930 *ret = WERR_NOMEM;
931 return False;
933 SAFE_FREE(key);
934 return true;
937 /****************************************************************************
938 Update a form struct.
939 ****************************************************************************/
941 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
943 int n=0;
945 DEBUG(106, ("[%s]\n", form->form_name));
946 for (n=0; n<count; n++) {
947 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
948 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
949 break;
952 if (n==count) return;
954 (*list)[n].flag = form->flags;
955 (*list)[n].width = form->size.width;
956 (*list)[n].length = form->size.height;
957 (*list)[n].left = form->area.left;
958 (*list)[n].top = form->area.top;
959 (*list)[n].right = form->area.right;
960 (*list)[n].bottom = form->area.bottom;
963 /****************************************************************************
964 Function to do the mapping between the long architecture name and
965 the short one.
966 ****************************************************************************/
968 const char *get_short_archi(const char *long_archi)
970 int i=-1;
972 DEBUG(107,("Getting architecture dependant directory\n"));
973 do {
974 i++;
975 } while ( (archi_table[i].long_archi!=NULL ) &&
976 StrCaseCmp(long_archi, archi_table[i].long_archi) );
978 if (archi_table[i].long_archi==NULL) {
979 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
980 return NULL;
983 /* this might be client code - but shouldn't this be an fstrcpy etc? */
985 DEBUGADD(108,("index: [%d]\n", i));
986 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
987 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
989 return archi_table[i].short_archi;
992 /****************************************************************************
993 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
994 There are two case to be covered here: PE (Portable Executable) and NE (New
995 Executable) files. Both files support the same INFO structure, but PE files
996 store the signature in unicode, and NE files store it as !unicode.
997 returns -1 on error, 1 on version info found, and 0 on no version info found.
998 ****************************************************************************/
1000 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1002 int i;
1003 char *buf = NULL;
1004 ssize_t byte_count;
1006 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1007 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1008 fname, DOS_HEADER_SIZE));
1009 goto error_exit;
1012 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1013 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1014 fname, (unsigned long)byte_count));
1015 goto no_version_info;
1018 /* Is this really a DOS header? */
1019 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1020 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1021 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1022 goto no_version_info;
1025 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1026 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1027 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1028 fname, errno));
1029 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1030 goto no_version_info;
1033 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1034 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1035 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1036 fname, (unsigned long)byte_count));
1037 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1038 goto no_version_info;
1041 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1042 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1043 unsigned int num_sections;
1044 unsigned int section_table_bytes;
1046 /* Just skip over optional header to get to section table */
1047 if (SMB_VFS_LSEEK(fsp,
1048 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1049 SEEK_CUR) == (SMB_OFF_T)-1) {
1050 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1051 fname, errno));
1052 goto error_exit;
1055 /* get the section table */
1056 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1057 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1058 if (section_table_bytes == 0)
1059 goto error_exit;
1061 SAFE_FREE(buf);
1062 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1063 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1064 fname, section_table_bytes));
1065 goto error_exit;
1068 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1069 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1070 fname, (unsigned long)byte_count));
1071 goto error_exit;
1074 /* Iterate the section table looking for the resource section ".rsrc" */
1075 for (i = 0; i < num_sections; i++) {
1076 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1078 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1079 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1080 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1082 if (section_bytes == 0)
1083 goto error_exit;
1085 SAFE_FREE(buf);
1086 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1087 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1088 fname, section_bytes));
1089 goto error_exit;
1092 /* Seek to the start of the .rsrc section info */
1093 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1094 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1095 fname, errno));
1096 goto error_exit;
1099 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1100 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1101 fname, (unsigned long)byte_count));
1102 goto error_exit;
1105 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1106 goto error_exit;
1108 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1109 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1110 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1111 /* Align to next long address */
1112 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1114 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1115 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1116 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1118 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1119 fname, *major, *minor,
1120 (*major>>16)&0xffff, *major&0xffff,
1121 (*minor>>16)&0xffff, *minor&0xffff));
1122 SAFE_FREE(buf);
1123 return 1;
1130 /* Version info not found, fall back to origin date/time */
1131 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1132 SAFE_FREE(buf);
1133 return 0;
1135 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1136 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1137 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1138 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1139 /* At this point, we assume the file is in error. It still could be somthing
1140 * else besides a NE file, but it unlikely at this point. */
1141 goto error_exit;
1144 /* Allocate a bit more space to speed up things */
1145 SAFE_FREE(buf);
1146 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1147 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1148 fname, PE_HEADER_SIZE));
1149 goto error_exit;
1152 /* This is a HACK! I got tired of trying to sort through the messy
1153 * 'NE' file format. If anyone wants to clean this up please have at
1154 * it, but this works. 'NE' files will eventually fade away. JRR */
1155 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1156 /* Cover case that should not occur in a well formed 'NE' .dll file */
1157 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1159 for(i=0; i<byte_count; i++) {
1160 /* Fast skip past data that can't possibly match */
1161 if (buf[i] != 'V') continue;
1163 /* Potential match data crosses buf boundry, move it to beginning
1164 * of buf, and fill the buf with as much as it will hold. */
1165 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1166 int bc;
1168 memcpy(buf, &buf[i], byte_count-i);
1169 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1170 (byte_count-i))) < 0) {
1172 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1173 fname, errno));
1174 goto error_exit;
1177 byte_count = bc + (byte_count - i);
1178 if (byte_count<VS_VERSION_INFO_SIZE) break;
1180 i = 0;
1183 /* Check that the full signature string and the magic number that
1184 * follows exist (not a perfect solution, but the chances that this
1185 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1186 * twice, as it is simpler to read the code. */
1187 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1188 /* Compute skip alignment to next long address */
1189 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1190 sizeof(VS_SIGNATURE)) & 3;
1191 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1193 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1194 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1195 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1196 fname, *major, *minor,
1197 (*major>>16)&0xffff, *major&0xffff,
1198 (*minor>>16)&0xffff, *minor&0xffff));
1199 SAFE_FREE(buf);
1200 return 1;
1205 /* Version info not found, fall back to origin date/time */
1206 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1207 SAFE_FREE(buf);
1208 return 0;
1210 } else
1211 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1212 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1213 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1215 no_version_info:
1216 SAFE_FREE(buf);
1217 return 0;
1219 error_exit:
1220 SAFE_FREE(buf);
1221 return -1;
1224 /****************************************************************************
1225 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1226 share one or more files. During the MS installation process files are checked
1227 to insure that only a newer version of a shared file is installed over an
1228 older version. There are several possibilities for this comparison. If there
1229 is no previous version, the new one is newer (obviously). If either file is
1230 missing the version info structure, compare the creation date (on Unix use
1231 the modification date). Otherwise chose the numerically larger version number.
1232 ****************************************************************************/
1234 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1236 bool use_version = true;
1238 uint32 new_major;
1239 uint32 new_minor;
1240 time_t new_create_time;
1242 uint32 old_major;
1243 uint32 old_minor;
1244 time_t old_create_time;
1246 struct smb_filename *smb_fname = NULL;
1247 files_struct *fsp = NULL;
1248 SMB_STRUCT_STAT st;
1250 NTSTATUS status;
1251 int ret;
1253 SET_STAT_INVALID(st);
1254 new_create_time = (time_t)0;
1255 old_create_time = (time_t)0;
1257 /* Get file version info (if available) for previous file (if it exists) */
1258 status = driver_unix_convert(conn, old_file, &smb_fname);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 goto error_exit;
1263 status = SMB_VFS_CREATE_FILE(
1264 conn, /* conn */
1265 NULL, /* req */
1266 0, /* root_dir_fid */
1267 smb_fname, /* fname */
1268 FILE_GENERIC_READ, /* access_mask */
1269 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1270 FILE_OPEN, /* create_disposition*/
1271 0, /* create_options */
1272 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1273 INTERNAL_OPEN_ONLY, /* oplock_request */
1274 0, /* allocation_size */
1275 0, /* private_flags */
1276 NULL, /* sd */
1277 NULL, /* ea_list */
1278 &fsp, /* result */
1279 NULL); /* pinfo */
1281 if (!NT_STATUS_IS_OK(status)) {
1282 /* Old file not found, so by definition new file is in fact newer */
1283 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1284 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1285 errno));
1286 ret = 1;
1287 goto done;
1289 } else {
1290 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1291 if (ret == -1) {
1292 goto error_exit;
1295 if (!ret) {
1296 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1297 old_file));
1298 use_version = false;
1299 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1300 goto error_exit;
1302 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1303 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1304 (long)old_create_time));
1307 close_file(NULL, fsp, NORMAL_CLOSE);
1308 fsp = NULL;
1310 /* Get file version info (if available) for new file */
1311 status = driver_unix_convert(conn, new_file, &smb_fname);
1312 if (!NT_STATUS_IS_OK(status)) {
1313 goto error_exit;
1316 status = SMB_VFS_CREATE_FILE(
1317 conn, /* conn */
1318 NULL, /* req */
1319 0, /* root_dir_fid */
1320 smb_fname, /* fname */
1321 FILE_GENERIC_READ, /* access_mask */
1322 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1323 FILE_OPEN, /* create_disposition*/
1324 0, /* create_options */
1325 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1326 INTERNAL_OPEN_ONLY, /* oplock_request */
1327 0, /* allocation_size */
1328 0, /* private_flags */
1329 NULL, /* sd */
1330 NULL, /* ea_list */
1331 &fsp, /* result */
1332 NULL); /* pinfo */
1334 if (!NT_STATUS_IS_OK(status)) {
1335 /* New file not found, this shouldn't occur if the caller did its job */
1336 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1337 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1338 goto error_exit;
1340 } else {
1341 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1342 if (ret == -1) {
1343 goto error_exit;
1346 if (!ret) {
1347 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1348 new_file));
1349 use_version = false;
1350 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1351 goto error_exit;
1353 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1354 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1355 (long)new_create_time));
1358 close_file(NULL, fsp, NORMAL_CLOSE);
1359 fsp = NULL;
1361 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1362 /* Compare versions and choose the larger version number */
1363 if (new_major > old_major ||
1364 (new_major == old_major && new_minor > old_minor)) {
1366 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1367 ret = 1;
1368 goto done;
1370 else {
1371 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1372 ret = 0;
1373 goto done;
1376 } else {
1377 /* Compare modification time/dates and choose the newest time/date */
1378 if (new_create_time > old_create_time) {
1379 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1380 ret = 1;
1381 goto done;
1383 else {
1384 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1385 ret = 0;
1386 goto done;
1390 error_exit:
1391 if(fsp)
1392 close_file(NULL, fsp, NORMAL_CLOSE);
1393 ret = -1;
1394 done:
1395 TALLOC_FREE(smb_fname);
1396 return ret;
1399 /****************************************************************************
1400 Determine the correct cVersion associated with an architecture and driver
1401 ****************************************************************************/
1402 static uint32 get_correct_cversion(struct pipes_struct *p,
1403 const char *architecture,
1404 const char *driverpath_in,
1405 WERROR *perr)
1407 int cversion;
1408 NTSTATUS nt_status;
1409 struct smb_filename *smb_fname = NULL;
1410 char *driverpath = NULL;
1411 files_struct *fsp = NULL;
1412 connection_struct *conn = NULL;
1413 NTSTATUS status;
1414 char *oldcwd;
1415 fstring printdollar;
1416 int printdollar_snum;
1418 *perr = WERR_INVALID_PARAM;
1420 /* If architecture is Windows 95/98/ME, the version is always 0. */
1421 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1422 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1423 *perr = WERR_OK;
1424 return 0;
1427 /* If architecture is Windows x64, the version is always 3. */
1428 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1429 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1430 *perr = WERR_OK;
1431 return 3;
1434 fstrcpy(printdollar, "print$");
1436 printdollar_snum = find_service(printdollar);
1437 if (printdollar_snum == -1) {
1438 *perr = WERR_NO_SUCH_SHARE;
1439 return -1;
1442 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1443 lp_pathname(printdollar_snum),
1444 p->server_info, &oldcwd);
1445 if (!NT_STATUS_IS_OK(nt_status)) {
1446 DEBUG(0,("get_correct_cversion: create_conn_struct "
1447 "returned %s\n", nt_errstr(nt_status)));
1448 *perr = ntstatus_to_werror(nt_status);
1449 return -1;
1452 /* Open the driver file (Portable Executable format) and determine the
1453 * deriver the cversion. */
1454 driverpath = talloc_asprintf(talloc_tos(),
1455 "%s/%s",
1456 architecture,
1457 driverpath_in);
1458 if (!driverpath) {
1459 *perr = WERR_NOMEM;
1460 goto error_exit;
1463 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1464 if (!NT_STATUS_IS_OK(nt_status)) {
1465 *perr = ntstatus_to_werror(nt_status);
1466 goto error_exit;
1469 nt_status = vfs_file_exist(conn, smb_fname);
1470 if (!NT_STATUS_IS_OK(nt_status)) {
1471 *perr = WERR_BADFILE;
1472 goto error_exit;
1475 status = SMB_VFS_CREATE_FILE(
1476 conn, /* conn */
1477 NULL, /* req */
1478 0, /* root_dir_fid */
1479 smb_fname, /* fname */
1480 FILE_GENERIC_READ, /* access_mask */
1481 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1482 FILE_OPEN, /* create_disposition*/
1483 0, /* create_options */
1484 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1485 INTERNAL_OPEN_ONLY, /* oplock_request */
1486 0, /* private_flags */
1487 0, /* allocation_size */
1488 NULL, /* sd */
1489 NULL, /* ea_list */
1490 &fsp, /* result */
1491 NULL); /* pinfo */
1493 if (!NT_STATUS_IS_OK(status)) {
1494 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1495 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1496 *perr = WERR_ACCESS_DENIED;
1497 goto error_exit;
1498 } else {
1499 uint32 major;
1500 uint32 minor;
1501 int ret;
1503 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1504 if (ret == -1) goto error_exit;
1506 if (!ret) {
1507 DEBUG(6,("get_correct_cversion: Version info not "
1508 "found [%s]\n",
1509 smb_fname_str_dbg(smb_fname)));
1510 goto error_exit;
1514 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1515 * for more details. Version in this case is not just the version of the
1516 * file, but the version in the sense of kernal mode (2) vs. user mode
1517 * (3) drivers. Other bits of the version fields are the version info.
1518 * JRR 010716
1520 cversion = major & 0x0000ffff;
1521 switch (cversion) {
1522 case 2: /* WinNT drivers */
1523 case 3: /* Win2K drivers */
1524 break;
1526 default:
1527 DEBUG(6,("get_correct_cversion: cversion "
1528 "invalid [%s] cversion = %d\n",
1529 smb_fname_str_dbg(smb_fname),
1530 cversion));
1531 goto error_exit;
1534 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1535 " = 0x%x minor = 0x%x\n",
1536 smb_fname_str_dbg(smb_fname), major, minor));
1539 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1540 smb_fname_str_dbg(smb_fname), cversion));
1542 goto done;
1544 error_exit:
1545 cversion = -1;
1546 done:
1547 TALLOC_FREE(smb_fname);
1548 if (fsp != NULL) {
1549 close_file(NULL, fsp, NORMAL_CLOSE);
1551 if (conn != NULL) {
1552 vfs_ChDir(conn, oldcwd);
1553 conn_free(conn);
1555 if (cversion != -1) {
1556 *perr = WERR_OK;
1558 return cversion;
1561 /****************************************************************************
1562 ****************************************************************************/
1564 #define strip_driver_path(_mem_ctx, _element) do { \
1565 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1566 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1567 W_ERROR_HAVE_NO_MEMORY((_element)); \
1569 } while (0);
1571 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1572 struct pipes_struct *rpc_pipe,
1573 const char *architecture,
1574 const char **driver_path,
1575 const char **data_file,
1576 const char **config_file,
1577 const char **help_file,
1578 struct spoolss_StringArray *dependent_files,
1579 uint32_t *version)
1581 const char *short_architecture;
1582 int i;
1583 WERROR err;
1584 char *_p;
1586 if (!*driver_path || !*data_file || !*config_file) {
1587 return WERR_INVALID_PARAM;
1590 /* clean up the driver name.
1591 * we can get .\driver.dll
1592 * or worse c:\windows\system\driver.dll !
1594 /* using an intermediate string to not have overlaping memcpy()'s */
1596 strip_driver_path(mem_ctx, *driver_path);
1597 strip_driver_path(mem_ctx, *data_file);
1598 strip_driver_path(mem_ctx, *config_file);
1599 if (help_file) {
1600 strip_driver_path(mem_ctx, *help_file);
1603 if (dependent_files && dependent_files->string) {
1604 for (i=0; dependent_files->string[i]; i++) {
1605 strip_driver_path(mem_ctx, dependent_files->string[i]);
1609 short_architecture = get_short_archi(architecture);
1610 if (!short_architecture) {
1611 return WERR_UNKNOWN_PRINTER_DRIVER;
1614 /* jfm:7/16/2000 the client always sends the cversion=0.
1615 * The server should check which version the driver is by reading
1616 * the PE header of driver->driverpath.
1618 * For Windows 95/98 the version is 0 (so the value sent is correct)
1619 * For Windows NT (the architecture doesn't matter)
1620 * NT 3.1: cversion=0
1621 * NT 3.5/3.51: cversion=1
1622 * NT 4: cversion=2
1623 * NT2K: cversion=3
1626 *version = get_correct_cversion(rpc_pipe, short_architecture,
1627 *driver_path, &err);
1628 if (*version == -1) {
1629 return err;
1632 return WERR_OK;
1635 /****************************************************************************
1636 ****************************************************************************/
1638 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1639 struct pipes_struct *rpc_pipe,
1640 struct spoolss_AddDriverInfoCtr *r)
1642 switch (r->level) {
1643 case 3:
1644 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1645 r->info.info3->architecture,
1646 &r->info.info3->driver_path,
1647 &r->info.info3->data_file,
1648 &r->info.info3->config_file,
1649 &r->info.info3->help_file,
1650 r->info.info3->dependent_files,
1651 &r->info.info3->version);
1652 case 6:
1653 return clean_up_driver_struct_level(mem_ctx, rpc_pipe,
1654 r->info.info6->architecture,
1655 &r->info.info6->driver_path,
1656 &r->info.info6->data_file,
1657 &r->info.info6->config_file,
1658 &r->info.info6->help_file,
1659 r->info.info6->dependent_files,
1660 &r->info.info6->version);
1661 default:
1662 return WERR_NOT_SUPPORTED;
1666 /****************************************************************************
1667 This function sucks and should be replaced. JRA.
1668 ****************************************************************************/
1670 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1671 const struct spoolss_AddDriverInfo6 *src)
1673 dst->version = src->version;
1675 dst->driver_name = src->driver_name;
1676 dst->architecture = src->architecture;
1677 dst->driver_path = src->driver_path;
1678 dst->data_file = src->data_file;
1679 dst->config_file = src->config_file;
1680 dst->help_file = src->help_file;
1681 dst->monitor_name = src->monitor_name;
1682 dst->default_datatype = src->default_datatype;
1683 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1684 dst->dependent_files = src->dependent_files;
1687 /****************************************************************************
1688 ****************************************************************************/
1690 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1691 connection_struct *conn,
1692 const char *driver_file,
1693 const char *short_architecture,
1694 uint32_t driver_version,
1695 uint32_t version)
1697 struct smb_filename *smb_fname_old = NULL;
1698 struct smb_filename *smb_fname_new = NULL;
1699 char *old_name = NULL;
1700 char *new_name = NULL;
1701 NTSTATUS status;
1702 WERROR ret;
1704 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1705 short_architecture, driver_file);
1706 W_ERROR_HAVE_NO_MEMORY(old_name);
1708 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1709 short_architecture, driver_version, driver_file);
1710 if (new_name == NULL) {
1711 TALLOC_FREE(old_name);
1712 return WERR_NOMEM;
1715 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1717 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 ret = WERR_NOMEM;
1720 goto out;
1723 /* Setup a synthetic smb_filename struct */
1724 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1725 if (!smb_fname_new) {
1726 ret = WERR_NOMEM;
1727 goto out;
1730 smb_fname_new->base_name = new_name;
1732 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1733 "'%s'\n", smb_fname_old->base_name,
1734 smb_fname_new->base_name));
1736 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1737 OPENX_FILE_EXISTS_TRUNCATE |
1738 OPENX_FILE_CREATE_IF_NOT_EXIST,
1739 0, false);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 DEBUG(0,("move_driver_file_to_download_area: Unable "
1743 "to rename [%s] to [%s]: %s\n",
1744 smb_fname_old->base_name, new_name,
1745 nt_errstr(status)));
1746 ret = WERR_ACCESS_DENIED;
1747 goto out;
1751 ret = WERR_OK;
1752 out:
1753 TALLOC_FREE(smb_fname_old);
1754 TALLOC_FREE(smb_fname_new);
1755 return ret;
1758 WERROR move_driver_to_download_area(struct pipes_struct *p,
1759 struct spoolss_AddDriverInfoCtr *r,
1760 WERROR *perr)
1762 struct spoolss_AddDriverInfo3 *driver;
1763 struct spoolss_AddDriverInfo3 converted_driver;
1764 const char *short_architecture;
1765 struct smb_filename *smb_dname = NULL;
1766 char *new_dir = NULL;
1767 connection_struct *conn = NULL;
1768 NTSTATUS nt_status;
1769 int i;
1770 TALLOC_CTX *ctx = talloc_tos();
1771 int ver = 0;
1772 char *oldcwd;
1773 fstring printdollar;
1774 int printdollar_snum;
1776 *perr = WERR_OK;
1778 switch (r->level) {
1779 case 3:
1780 driver = r->info.info3;
1781 break;
1782 case 6:
1783 convert_level_6_to_level3(&converted_driver, r->info.info6);
1784 driver = &converted_driver;
1785 break;
1786 default:
1787 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1788 return WERR_UNKNOWN_LEVEL;
1791 short_architecture = get_short_archi(driver->architecture);
1792 if (!short_architecture) {
1793 return WERR_UNKNOWN_PRINTER_DRIVER;
1796 fstrcpy(printdollar, "print$");
1798 printdollar_snum = find_service(printdollar);
1799 if (printdollar_snum == -1) {
1800 *perr = WERR_NO_SUCH_SHARE;
1801 return WERR_NO_SUCH_SHARE;
1804 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1805 lp_pathname(printdollar_snum),
1806 p->server_info, &oldcwd);
1807 if (!NT_STATUS_IS_OK(nt_status)) {
1808 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1809 "returned %s\n", nt_errstr(nt_status)));
1810 *perr = ntstatus_to_werror(nt_status);
1811 return *perr;
1814 new_dir = talloc_asprintf(ctx,
1815 "%s/%d",
1816 short_architecture,
1817 driver->version);
1818 if (!new_dir) {
1819 *perr = WERR_NOMEM;
1820 goto err_exit;
1822 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1823 if (!NT_STATUS_IS_OK(nt_status)) {
1824 *perr = WERR_NOMEM;
1825 goto err_exit;
1828 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1830 create_directory(conn, NULL, smb_dname);
1832 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1833 * listed for this driver which has already been moved, skip it (note:
1834 * drivers may list the same file name several times. Then check if the
1835 * file already exists in archi\version\, if so, check that the version
1836 * info (or time stamps if version info is unavailable) is newer (or the
1837 * date is later). If it is, move it to archi\version\filexxx.yyy.
1838 * Otherwise, delete the file.
1840 * If a file is not moved to archi\version\ because of an error, all the
1841 * rest of the 'unmoved' driver files are removed from archi\. If one or
1842 * more of the driver's files was already moved to archi\version\, it
1843 * potentially leaves the driver in a partially updated state. Version
1844 * trauma will most likely occur if an client attempts to use any printer
1845 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1846 * done is appropriate... later JRR
1849 DEBUG(5,("Moving files now !\n"));
1851 if (driver->driver_path && strlen(driver->driver_path)) {
1853 *perr = move_driver_file_to_download_area(ctx,
1854 conn,
1855 driver->driver_path,
1856 short_architecture,
1857 driver->version,
1858 ver);
1859 if (!W_ERROR_IS_OK(*perr)) {
1860 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1861 ver = -1;
1863 goto err_exit;
1867 if (driver->data_file && strlen(driver->data_file)) {
1868 if (!strequal(driver->data_file, driver->driver_path)) {
1870 *perr = move_driver_file_to_download_area(ctx,
1871 conn,
1872 driver->data_file,
1873 short_architecture,
1874 driver->version,
1875 ver);
1876 if (!W_ERROR_IS_OK(*perr)) {
1877 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1878 ver = -1;
1880 goto err_exit;
1885 if (driver->config_file && strlen(driver->config_file)) {
1886 if (!strequal(driver->config_file, driver->driver_path) &&
1887 !strequal(driver->config_file, driver->data_file)) {
1889 *perr = move_driver_file_to_download_area(ctx,
1890 conn,
1891 driver->config_file,
1892 short_architecture,
1893 driver->version,
1894 ver);
1895 if (!W_ERROR_IS_OK(*perr)) {
1896 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1897 ver = -1;
1899 goto err_exit;
1904 if (driver->help_file && strlen(driver->help_file)) {
1905 if (!strequal(driver->help_file, driver->driver_path) &&
1906 !strequal(driver->help_file, driver->data_file) &&
1907 !strequal(driver->help_file, driver->config_file)) {
1909 *perr = move_driver_file_to_download_area(ctx,
1910 conn,
1911 driver->help_file,
1912 short_architecture,
1913 driver->version,
1914 ver);
1915 if (!W_ERROR_IS_OK(*perr)) {
1916 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1917 ver = -1;
1919 goto err_exit;
1924 if (driver->dependent_files && driver->dependent_files->string) {
1925 for (i=0; driver->dependent_files->string[i]; i++) {
1926 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1927 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1928 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1929 !strequal(driver->dependent_files->string[i], driver->help_file)) {
1930 int j;
1931 for (j=0; j < i; j++) {
1932 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1933 goto NextDriver;
1937 *perr = move_driver_file_to_download_area(ctx,
1938 conn,
1939 driver->dependent_files->string[i],
1940 short_architecture,
1941 driver->version,
1942 ver);
1943 if (!W_ERROR_IS_OK(*perr)) {
1944 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1945 ver = -1;
1947 goto err_exit;
1950 NextDriver: ;
1954 err_exit:
1955 TALLOC_FREE(smb_dname);
1957 if (conn != NULL) {
1958 vfs_ChDir(conn, oldcwd);
1959 conn_free(conn);
1962 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1963 return WERR_OK;
1965 if (ver == -1) {
1966 return WERR_UNKNOWN_PRINTER_DRIVER;
1968 return (*perr);
1971 /****************************************************************************
1972 ****************************************************************************/
1973 int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
1975 enum ndr_err_code ndr_err;
1976 DATA_BLOB blob;
1977 int len = 0;
1979 if (devmode) {
1980 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
1981 devmode,
1982 (ndr_push_flags_fn_t)
1983 ndr_push_spoolss_DeviceMode);
1984 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1985 DEBUG(10, ("pack_devicemode: "
1986 "error encoding spoolss_DeviceMode\n"));
1987 goto done;
1989 } else {
1990 ZERO_STRUCT(blob);
1993 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
1995 if (devmode) {
1996 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
1999 done:
2000 return len;
2003 /****************************************************************************
2004 ****************************************************************************/
2005 int unpack_devicemode(TALLOC_CTX *mem_ctx,
2006 const uint8 *buf, int buflen,
2007 struct spoolss_DeviceMode **devmode)
2009 struct spoolss_DeviceMode *dm;
2010 enum ndr_err_code ndr_err;
2011 char *data = NULL;
2012 int data_len = 0;
2013 DATA_BLOB blob;
2014 int len = 0;
2016 *devmode = NULL;
2018 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2019 if (!data) {
2020 return len;
2023 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2024 if (!dm) {
2025 goto done;
2028 blob = data_blob_const(data, data_len);
2030 ndr_err = ndr_pull_struct_blob(&blob, dm, dm,
2031 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
2032 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2033 DEBUG(10, ("unpack_devicemode: "
2034 "error parsing spoolss_DeviceMode\n"));
2035 goto done;
2038 DEBUG(8, ("Unpacked devicemode [%s](%s)\n",
2039 dm->devicename, dm->formname));
2040 if (dm->driverextra_data.data) {
2041 DEBUG(8, ("with a private section of %d bytes\n",
2042 dm->__driverextra_length));
2045 *devmode = dm;
2047 done:
2048 SAFE_FREE(data);
2049 return len;
2052 /****************************************************************************
2053 Create and allocate a default devicemode.
2054 ****************************************************************************/
2056 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2057 const char *devicename,
2058 struct spoolss_DeviceMode **devmode)
2060 struct spoolss_DeviceMode *dm;
2061 char *dname;
2063 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2064 if (dm == NULL) {
2065 return WERR_NOMEM;
2068 dname = talloc_asprintf(dm, "%s", devicename);
2069 if (dname == NULL) {
2070 return WERR_NOMEM;
2072 if (strlen(dname) > MAXDEVICENAME) {
2073 dname[MAXDEVICENAME] = '\0';
2075 dm->devicename = dname;
2077 dm->formname = talloc_strdup(dm, "Letter");
2078 if (dm->formname == NULL) {
2079 return WERR_NOMEM;
2082 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2083 dm->driverversion = 0x0400;
2084 dm->size = 0x00DC;
2085 dm->__driverextra_length = 0;
2086 dm->fields = DEVMODE_FORMNAME |
2087 DEVMODE_TTOPTION |
2088 DEVMODE_PRINTQUALITY |
2089 DEVMODE_DEFAULTSOURCE |
2090 DEVMODE_COPIES |
2091 DEVMODE_SCALE |
2092 DEVMODE_PAPERSIZE |
2093 DEVMODE_ORIENTATION;
2094 dm->orientation = DMORIENT_PORTRAIT;
2095 dm->papersize = DMPAPER_LETTER;
2096 dm->paperlength = 0;
2097 dm->paperwidth = 0;
2098 dm->scale = 0x64;
2099 dm->copies = 1;
2100 dm->defaultsource = DMBIN_FORMSOURCE;
2101 dm->printquality = DMRES_HIGH; /* 0x0258 */
2102 dm->color = DMRES_MONOCHROME;
2103 dm->duplex = DMDUP_SIMPLEX;
2104 dm->yresolution = 0;
2105 dm->ttoption = DMTT_SUBDEV;
2106 dm->collate = DMCOLLATE_FALSE;
2107 dm->icmmethod = 0;
2108 dm->icmintent = 0;
2109 dm->mediatype = 0;
2110 dm->dithertype = 0;
2112 dm->logpixels = 0;
2113 dm->bitsperpel = 0;
2114 dm->pelswidth = 0;
2115 dm->pelsheight = 0;
2116 dm->displayflags = 0;
2117 dm->displayfrequency = 0;
2118 dm->reserved1 = 0;
2119 dm->reserved2 = 0;
2120 dm->panningwidth = 0;
2121 dm->panningheight = 0;
2123 dm->driverextra_data.data = NULL;
2124 dm->driverextra_data.length = 0;
2126 *devmode = dm;
2127 return WERR_OK;
2130 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2131 struct spoolss_security_descriptor **secdesc)
2133 struct security_ace ace[7]; /* max number of ace entries */
2134 int i = 0;
2135 uint32_t sa;
2136 struct security_acl *psa = NULL;
2137 struct security_descriptor *psd = NULL;
2138 struct dom_sid adm_sid;
2139 size_t sd_size;
2141 /* Create an ACE where Everyone is allowed to print */
2143 sa = PRINTER_ACE_PRINT;
2144 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2145 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2147 /* Add the domain admins group if we are a DC */
2149 if ( IS_DC ) {
2150 struct dom_sid domadmins_sid;
2152 sid_compose(&domadmins_sid, get_global_sam_sid(),
2153 DOMAIN_RID_ADMINS);
2155 sa = PRINTER_ACE_FULL_CONTROL;
2156 init_sec_ace(&ace[i++], &domadmins_sid,
2157 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2158 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2159 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2160 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2162 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2163 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2165 sa = PRINTER_ACE_FULL_CONTROL;
2166 init_sec_ace(&ace[i++], &adm_sid,
2167 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2168 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2169 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2170 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2173 /* add BUILTIN\Administrators as FULL CONTROL */
2175 sa = PRINTER_ACE_FULL_CONTROL;
2176 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2177 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2178 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2179 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2180 SEC_ACE_TYPE_ACCESS_ALLOWED,
2181 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2183 /* add BUILTIN\Print Operators as FULL CONTROL */
2185 sa = PRINTER_ACE_FULL_CONTROL;
2186 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2187 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2188 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2189 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2190 SEC_ACE_TYPE_ACCESS_ALLOWED,
2191 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2193 /* Make the security descriptor owned by the BUILTIN\Administrators */
2195 /* The ACL revision number in rpc_secdesc.h differs from the one
2196 created by NT when setting ACE entries in printer
2197 descriptors. NT4 complains about the property being edited by a
2198 NT5 machine. */
2200 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2201 psd = make_sec_desc(mem_ctx,
2202 SD_REVISION,
2203 SEC_DESC_SELF_RELATIVE,
2204 &global_sid_Builtin_Administrators,
2205 &global_sid_Builtin_Administrators,
2206 NULL,
2207 psa,
2208 &sd_size);
2211 if (psd == NULL) {
2212 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2213 return WERR_NOMEM;
2216 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2217 (unsigned int)sd_size));
2219 *secdesc = psd;
2221 return WERR_OK;
2224 /****************************************************************************
2225 Allocate and initialize a new slot.
2226 ***************************************************************************/
2228 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2230 NT_PRINTER_KEY *d;
2231 int key_index;
2232 WERROR werr;
2234 if ( !name || !data )
2235 return -1;
2237 /* allocate another slot in the NT_PRINTER_KEY array */
2239 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2240 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2241 return -1;
2244 data->keys = d;
2246 key_index = data->num_keys;
2248 /* initialze new key */
2250 data->keys[key_index].name = talloc_strdup( data, name );
2252 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2253 if (!W_ERROR_IS_OK(werr)) {
2254 return -1;
2257 data->num_keys++;
2259 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2261 return key_index;
2264 /****************************************************************************
2265 search for a registry key name in the existing printer data
2266 ***************************************************************************/
2268 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2270 int i;
2272 for ( i=0; i<data->num_keys; i++ ) {
2273 if ( strequal( data->keys[i].name, name ) ) {
2275 /* cleanup memory */
2277 TALLOC_FREE( data->keys[i].name );
2278 TALLOC_FREE( data->keys[i].values );
2280 /* if not the end of the array, move remaining elements down one slot */
2282 data->num_keys--;
2283 if ( data->num_keys && (i < data->num_keys) )
2284 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2286 break;
2291 return data->num_keys;
2294 /****************************************************************************
2295 search for a registry key name in the existing printer data
2296 ***************************************************************************/
2298 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2300 int key_index = -1;
2301 int i;
2303 if ( !data || !name )
2304 return -1;
2306 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2308 /* loop over all existing keys */
2310 for ( i=0; i<data->num_keys; i++ ) {
2311 if ( strequal(data->keys[i].name, name) ) {
2312 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2313 key_index = i;
2314 break;
2319 return key_index;
2322 /****************************************************************************
2323 ***************************************************************************/
2325 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2327 int i, j;
2328 int key_len;
2329 int num_subkeys = 0;
2330 char *p;
2331 fstring *subkeys_ptr = NULL;
2332 fstring subkeyname;
2334 *subkeys = NULL;
2336 if ( !data )
2337 return 0;
2339 if ( !key )
2340 return -1;
2342 /* special case of asking for the top level printer data registry key names */
2344 if ( strlen(key) == 0 ) {
2345 for ( i=0; i<data->num_keys; i++ ) {
2347 /* found a match, so allocate space and copy the name */
2349 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2350 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2351 num_subkeys+1));
2352 return -1;
2355 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2356 num_subkeys++;
2359 goto done;
2362 /* asking for the subkeys of some key */
2363 /* subkey paths are stored in the key name using '\' as the delimiter */
2365 for ( i=0; i<data->num_keys; i++ ) {
2366 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2368 /* if we found the exact key, then break */
2369 key_len = strlen( key );
2370 if ( strlen(data->keys[i].name) == key_len )
2371 break;
2373 /* get subkey path */
2375 p = data->keys[i].name + key_len;
2376 if ( *p == '\\' )
2377 p++;
2378 fstrcpy( subkeyname, p );
2379 if ( (p = strchr( subkeyname, '\\' )) )
2380 *p = '\0';
2382 /* don't add a key more than once */
2384 for ( j=0; j<num_subkeys; j++ ) {
2385 if ( strequal( subkeys_ptr[j], subkeyname ) )
2386 break;
2389 if ( j != num_subkeys )
2390 continue;
2392 /* found a match, so allocate space and copy the name */
2394 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2395 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2396 num_subkeys+1));
2397 return 0;
2400 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2401 num_subkeys++;
2406 /* return error if the key was not found */
2408 if ( i == data->num_keys ) {
2409 SAFE_FREE(subkeys_ptr);
2410 return -1;
2413 done:
2414 /* tag off the end */
2416 if (num_subkeys)
2417 fstrcpy(subkeys_ptr[num_subkeys], "" );
2419 *subkeys = subkeys_ptr;
2421 return num_subkeys;
2424 #ifdef HAVE_ADS
2425 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2426 const char *sz)
2428 regval_ctr_delvalue(ctr, val_name);
2429 regval_ctr_addvalue_sz(ctr, val_name, sz);
2432 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2433 uint32 dword)
2435 regval_ctr_delvalue(ctr, val_name);
2436 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2437 (uint8 *) &dword, sizeof(dword));
2440 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2441 bool b)
2443 uint8 bin_bool = (b ? 1 : 0);
2444 regval_ctr_delvalue(ctr, val_name);
2445 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2446 (uint8 *) &bin_bool, sizeof(bin_bool));
2449 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2450 const char *multi_sz)
2452 const char *a[2];
2454 a[0] = multi_sz;
2455 a[1] = NULL;
2457 regval_ctr_delvalue(ctr, val_name);
2458 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2461 /****************************************************************************
2462 * Map spoolss_PrinterInfo2 data into DsSpooler keys for publishing.
2464 * @param mem_ctx allocation context
2465 * @param info2 spoolss_PrinterInfo2 describing printer
2466 * @param pdata the talloced printer data
2467 * @return bool indicating success or failure
2468 ***************************************************************************/
2470 static bool map_nt_printer_info2_to_dsspooler(TALLOC_CTX *mem_ctx,
2471 struct spoolss_PrinterInfo2 *info2,
2472 NT_PRINTER_DATA **pdata)
2474 NT_PRINTER_DATA *data;
2475 struct regval_ctr *ctr = NULL;
2476 fstring longname;
2477 const char *dnssuffix;
2478 char *allocated_string = NULL;
2479 const char *ascii_str;
2480 int i;
2482 data = talloc_zero(mem_ctx, NT_PRINTER_DATA);
2483 if (!data) return false;
2485 /* init data */
2486 i = add_new_printer_key(data, SPOOL_DSSPOOLER_KEY);
2487 ctr = data->keys[i].values;
2489 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2490 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2492 /* we make the assumption that the netbios name is the same
2493 as the DNS name sinc ethe former will be what we used to
2494 join the domain */
2496 dnssuffix = get_mydnsdomname(talloc_tos());
2497 if (dnssuffix && *dnssuffix) {
2498 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2499 } else {
2500 fstrcpy( longname, global_myname() );
2503 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2505 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
2506 talloc_free(data);
2507 return false;
2509 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2510 SAFE_FREE(allocated_string);
2512 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2513 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2514 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2515 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2516 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2517 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2518 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2519 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2520 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2522 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2523 (info2->attributes &
2524 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2526 switch (info2->attributes & 0x3) {
2527 case 0:
2528 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2529 break;
2530 case 1:
2531 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2532 break;
2533 case 2:
2534 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2535 break;
2536 default:
2537 ascii_str = "unknown";
2539 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2541 *pdata = data;
2542 return true;
2545 /*****************************************************************
2546 ****************************************************************/
2548 static void store_printer_guid(const char *printer, struct GUID guid)
2550 TALLOC_CTX *tmp_ctx;
2551 struct auth_serversupplied_info *server_info = NULL;
2552 const char *guid_str;
2553 DATA_BLOB blob;
2554 NTSTATUS status;
2555 WERROR result;
2557 tmp_ctx = talloc_new(NULL);
2558 if (!tmp_ctx) {
2559 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2560 return;
2563 status = make_server_info_system(tmp_ctx, &server_info);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 DEBUG(0, ("store_printer_guid: "
2566 "Could not create system server_info\n"));
2567 goto done;
2570 guid_str = GUID_string(tmp_ctx, &guid);
2571 if (!guid_str) {
2572 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2573 goto done;
2576 /* We used to store this as a REG_BINARY but that causes
2577 Vista to whine */
2579 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
2580 DEBUG(0, ("store_printer_guid: "
2581 "Could not marshall string %s for objectGUID\n",
2582 guid_str));
2583 goto done;
2586 result = winreg_set_printer_dataex(tmp_ctx, server_info, printer,
2587 SPOOL_DSSPOOLER_KEY, "objectGUID",
2588 REG_SZ, blob.data, blob.length);
2589 if (!W_ERROR_IS_OK(result)) {
2590 DEBUG(0, ("store_printer_guid: "
2591 "Failed to store GUID for printer %s\n", printer));
2594 done:
2595 talloc_free(tmp_ctx);
2598 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2599 struct spoolss_PrinterInfo2 *pinfo2)
2601 ADS_STATUS ads_rc;
2602 LDAPMessage *res;
2603 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
2604 char *srv_dn_utf8, **srv_cn_utf8;
2605 TALLOC_CTX *ctx;
2606 ADS_MODLIST mods;
2607 const char *attrs[] = {"objectGUID", NULL};
2608 struct GUID guid;
2609 WERROR win_rc = WERR_OK;
2610 size_t converted_size;
2611 NT_PRINTER_DATA *pdata;
2612 const char *printer = pinfo2->sharename;
2614 /* build the ads mods */
2615 ctx = talloc_init("nt_printer_publish_ads");
2616 if (ctx == NULL) {
2617 return WERR_NOMEM;
2620 DEBUG(5, ("publishing printer %s\n", printer));
2622 if (!map_nt_printer_info2_to_dsspooler(ctx, pinfo2, &pdata)) {
2623 TALLOC_FREE(ctx);
2624 return WERR_SERVER_UNAVAILABLE;
2627 /* figure out where to publish */
2628 ads_find_machine_acct(ads, &res, global_myname());
2630 /* We use ldap_get_dn here as we need the answer
2631 * in utf8 to call ldap_explode_dn(). JRA. */
2633 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2634 if (!srv_dn_utf8) {
2635 TALLOC_FREE(ctx);
2636 return WERR_SERVER_UNAVAILABLE;
2638 ads_msgfree(ads, res);
2639 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2640 if (!srv_cn_utf8) {
2641 TALLOC_FREE(ctx);
2642 ldap_memfree(srv_dn_utf8);
2643 return WERR_SERVER_UNAVAILABLE;
2645 /* Now convert to CH_UNIX. */
2646 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
2647 TALLOC_FREE(ctx);
2648 ldap_memfree(srv_dn_utf8);
2649 ldap_memfree(srv_cn_utf8);
2650 return WERR_SERVER_UNAVAILABLE;
2652 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
2653 TALLOC_FREE(ctx);
2654 ldap_memfree(srv_dn_utf8);
2655 ldap_memfree(srv_cn_utf8);
2656 TALLOC_FREE(srv_dn);
2657 return WERR_SERVER_UNAVAILABLE;
2660 ldap_memfree(srv_dn_utf8);
2661 ldap_memfree(srv_cn_utf8);
2663 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
2664 if (!srv_cn_escaped) {
2665 TALLOC_FREE(ctx);
2666 return WERR_SERVER_UNAVAILABLE;
2668 sharename_escaped = escape_rdn_val_string_alloc(printer);
2669 if (!sharename_escaped) {
2670 SAFE_FREE(srv_cn_escaped);
2671 TALLOC_FREE(ctx);
2672 return WERR_SERVER_UNAVAILABLE;
2675 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
2677 SAFE_FREE(srv_cn_escaped);
2678 SAFE_FREE(sharename_escaped);
2680 mods = ads_init_mods(ctx);
2682 if (mods == NULL) {
2683 SAFE_FREE(prt_dn);
2684 TALLOC_FREE(ctx);
2685 return WERR_NOMEM;
2688 get_local_printer_publishing_data(ctx, &mods, pdata);
2689 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
2691 /* publish it */
2692 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2693 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
2694 int i;
2695 for (i=0; mods[i] != 0; i++)
2697 mods[i] = (LDAPMod *)-1;
2698 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2701 if (!ADS_ERR_OK(ads_rc)) {
2702 DEBUG(3, ("error publishing %s: %s\n",
2703 printer, ads_errstr(ads_rc)));
2706 /* retreive the guid and store it locally */
2707 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2708 ZERO_STRUCT(guid);
2709 ads_pull_guid(ads, res, &guid);
2710 ads_msgfree(ads, res);
2711 store_printer_guid(printer, guid);
2713 TALLOC_FREE(ctx);
2715 return win_rc;
2718 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2719 const char *printer)
2721 ADS_STATUS ads_rc;
2722 LDAPMessage *res = NULL;
2723 char *prt_dn = NULL;
2725 DEBUG(5, ("unpublishing printer %s\n", printer));
2727 /* remove the printer from the directory */
2728 ads_rc = ads_find_printer_on_server(ads, &res,
2729 printer, global_myname());
2731 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
2732 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2733 if (!prt_dn) {
2734 ads_msgfree(ads, res);
2735 return WERR_NOMEM;
2737 ads_rc = ads_del_dn(ads, prt_dn);
2738 TALLOC_FREE(prt_dn);
2741 if (res) {
2742 ads_msgfree(ads, res);
2744 return WERR_OK;
2747 /****************************************************************************
2748 * Publish a printer in the directory
2750 * @param mem_ctx memory context
2751 * @param server_info server_info to access winreg pipe
2752 * @param pinfo2 printer information
2753 * @param action publish/unpublish action
2754 * @return WERROR indicating status of publishing
2755 ***************************************************************************/
2757 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2758 struct auth_serversupplied_info *server_info,
2759 struct spoolss_PrinterInfo2 *pinfo2,
2760 int action)
2762 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
2763 struct spoolss_SetPrinterInfo2 *sinfo2;
2764 ADS_STATUS ads_rc;
2765 ADS_STRUCT *ads = NULL;
2766 WERROR win_rc;
2768 sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
2769 if (!sinfo2) {
2770 return WERR_NOMEM;
2773 switch (action) {
2774 case DSPRINT_PUBLISH:
2775 case DSPRINT_UPDATE:
2776 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2777 break;
2778 case DSPRINT_UNPUBLISH:
2779 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2780 break;
2781 default:
2782 win_rc = WERR_NOT_SUPPORTED;
2783 goto done;
2786 sinfo2->attributes = pinfo2->attributes;
2788 win_rc = winreg_update_printer(mem_ctx, server_info,
2789 pinfo2->sharename, info2_mask,
2790 sinfo2, NULL, NULL);
2791 if (!W_ERROR_IS_OK(win_rc)) {
2792 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2793 goto done;
2796 TALLOC_FREE(sinfo2);
2798 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2799 if (!ads) {
2800 DEBUG(3, ("ads_init() failed\n"));
2801 win_rc = WERR_SERVER_UNAVAILABLE;
2802 goto done;
2804 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2805 SAFE_FREE(ads->auth.password);
2806 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2807 NULL, NULL);
2809 /* ads_connect() will find the DC for us */
2810 ads_rc = ads_connect(ads);
2811 if (!ADS_ERR_OK(ads_rc)) {
2812 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2813 win_rc = WERR_ACCESS_DENIED;
2814 goto done;
2817 switch (action) {
2818 case DSPRINT_PUBLISH:
2819 case DSPRINT_UPDATE:
2820 win_rc = nt_printer_publish_ads(ads, pinfo2);
2821 break;
2822 case DSPRINT_UNPUBLISH:
2823 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
2824 break;
2827 done:
2828 ads_destroy(&ads);
2829 return win_rc;
2832 WERROR check_published_printers(void)
2834 ADS_STATUS ads_rc;
2835 ADS_STRUCT *ads = NULL;
2836 int snum;
2837 int n_services = lp_numservices();
2838 TALLOC_CTX *tmp_ctx = NULL;
2839 struct auth_serversupplied_info *server_info = NULL;
2840 struct spoolss_PrinterInfo2 *pinfo2;
2841 NTSTATUS status;
2842 WERROR result;
2844 tmp_ctx = talloc_new(NULL);
2845 if (!tmp_ctx) return WERR_NOMEM;
2847 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2848 if (!ads) {
2849 DEBUG(3, ("ads_init() failed\n"));
2850 return WERR_SERVER_UNAVAILABLE;
2852 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2853 SAFE_FREE(ads->auth.password);
2854 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2855 NULL, NULL);
2857 /* ads_connect() will find the DC for us */
2858 ads_rc = ads_connect(ads);
2859 if (!ADS_ERR_OK(ads_rc)) {
2860 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2861 result = WERR_ACCESS_DENIED;
2862 goto done;
2865 status = make_server_info_system(tmp_ctx, &server_info);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 DEBUG(0, ("check_published_printers: "
2868 "Could not create system server_info\n"));
2869 result = WERR_ACCESS_DENIED;
2870 goto done;
2873 for (snum = 0; snum < n_services; snum++) {
2874 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
2875 continue;
2878 result = winreg_get_printer(tmp_ctx, server_info, NULL,
2879 lp_servicename(snum), &pinfo2);
2880 if (!W_ERROR_IS_OK(result)) {
2881 continue;
2884 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2885 nt_printer_publish_ads(ads, pinfo2);
2888 TALLOC_FREE(pinfo2);
2891 result = WERR_OK;
2892 done:
2893 ads_destroy(&ads);
2894 ads_kdestroy("MEMORY:prtpub_cache");
2895 talloc_free(tmp_ctx);
2896 return result;
2899 bool is_printer_published(TALLOC_CTX *mem_ctx,
2900 struct auth_serversupplied_info *server_info,
2901 char *servername, char *printer, struct GUID *guid,
2902 struct spoolss_PrinterInfo2 **info2)
2904 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
2905 enum winreg_Type type;
2906 uint8_t *data;
2907 uint32_t data_size;
2908 WERROR result;
2909 NTSTATUS status;
2911 result = winreg_get_printer(mem_ctx, server_info,
2912 servername, printer, &pinfo2);
2913 if (!W_ERROR_IS_OK(result)) {
2914 return false;
2917 if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
2918 TALLOC_FREE(pinfo2);
2919 return false;
2922 if (!guid) {
2923 goto done;
2926 /* fetching printer guids really ought to be a separate function. */
2928 result = winreg_get_printer_dataex(mem_ctx, server_info, printer,
2929 SPOOL_DSSPOOLER_KEY, "objectGUID",
2930 &type, &data, &data_size);
2931 if (!W_ERROR_IS_OK(result)) {
2932 TALLOC_FREE(pinfo2);
2933 return false;
2936 /* We used to store the guid as REG_BINARY, then swapped
2937 to REG_SZ for Vista compatibility so check for both */
2939 switch (type) {
2940 case REG_SZ:
2941 status = GUID_from_string((char *)data, guid);
2942 if (!NT_STATUS_IS_OK(status)) {
2943 TALLOC_FREE(pinfo2);
2944 return false;
2946 break;
2948 case REG_BINARY:
2949 if (data_size != sizeof(struct GUID)) {
2950 TALLOC_FREE(pinfo2);
2951 return false;
2953 memcpy(guid, data, sizeof(struct GUID));
2954 break;
2955 default:
2956 DEBUG(0,("is_printer_published: GUID value stored as "
2957 "invaluid type (%d)\n", type));
2958 break;
2961 done:
2962 if (info2) {
2963 *info2 = talloc_move(mem_ctx, &pinfo2);
2965 talloc_free(pinfo2);
2966 return true;
2968 #else
2969 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2970 struct auth_serversupplied_info *server_info,
2971 struct spoolss_PrinterInfo2 *pinfo2,
2972 int action)
2974 return WERR_OK;
2977 WERROR check_published_printers(void)
2979 return WERR_OK;
2982 bool is_printer_published(TALLOC_CTX *mem_ctx,
2983 struct auth_serversupplied_info *server_info,
2984 char *servername, char *printer, struct GUID *guid,
2985 struct spoolss_PrinterInfo2 **info2)
2987 return False;
2989 #endif /* HAVE_ADS */
2991 /****************************************************************************
2992 ***************************************************************************/
2994 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2996 NT_PRINTER_DATA *data;
2997 int i;
2998 int removed_keys = 0;
2999 int empty_slot;
3001 data = p2->data;
3002 empty_slot = data->num_keys;
3004 if ( !key )
3005 return WERR_INVALID_PARAM;
3007 /* remove all keys */
3009 if ( !strlen(key) ) {
3011 TALLOC_FREE( data );
3013 p2->data = NULL;
3015 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3016 p2->printername ));
3018 return WERR_OK;
3021 /* remove a specific key (and all subkeys) */
3023 for ( i=0; i<data->num_keys; i++ ) {
3024 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3025 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3026 data->keys[i].name));
3028 TALLOC_FREE( data->keys[i].name );
3029 TALLOC_FREE( data->keys[i].values );
3031 /* mark the slot as empty */
3033 ZERO_STRUCTP( &data->keys[i] );
3037 /* find the first empty slot */
3039 for ( i=0; i<data->num_keys; i++ ) {
3040 if ( !data->keys[i].name ) {
3041 empty_slot = i;
3042 removed_keys++;
3043 break;
3047 if ( i == data->num_keys )
3048 /* nothing was removed */
3049 return WERR_INVALID_PARAM;
3051 /* move everything down */
3053 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3054 if ( data->keys[i].name ) {
3055 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3056 ZERO_STRUCTP( &data->keys[i] );
3057 empty_slot++;
3058 removed_keys++;
3062 /* update count */
3064 data->num_keys -= removed_keys;
3066 /* sanity check to see if anything is left */
3068 if ( !data->num_keys ) {
3069 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3071 SAFE_FREE( data->keys );
3072 ZERO_STRUCTP( data );
3075 return WERR_OK;
3078 /****************************************************************************
3079 ***************************************************************************/
3081 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3083 WERROR result = WERR_OK;
3084 int key_index;
3086 /* we must have names on non-zero length */
3088 if ( !key || !*key|| !value || !*value )
3089 return WERR_INVALID_NAME;
3091 /* find the printer key first */
3093 key_index = lookup_printerkey( p2->data, key );
3094 if ( key_index == -1 )
3095 return WERR_OK;
3097 /* make sure the value exists so we can return the correct error code */
3099 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3100 return WERR_BADFILE;
3102 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3104 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3105 key, value ));
3107 return result;
3110 /****************************************************************************
3111 ***************************************************************************/
3113 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3114 uint32 type, uint8 *data, int real_len )
3116 WERROR result = WERR_OK;
3117 int key_index;
3119 /* we must have names on non-zero length */
3121 if ( !key || !*key|| !value || !*value )
3122 return WERR_INVALID_NAME;
3124 /* find the printer key first */
3126 key_index = lookup_printerkey( p2->data, key );
3127 if ( key_index == -1 )
3128 key_index = add_new_printer_key( p2->data, key );
3130 if ( key_index == -1 )
3131 return WERR_NOMEM;
3133 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3134 type, data, real_len );
3136 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3137 key, value, type, real_len ));
3139 return result;
3142 /****************************************************************************
3143 ***************************************************************************/
3145 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3147 int key_index;
3149 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3150 return NULL;
3152 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3153 key, value ));
3155 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3158 /****************************************************************************
3159 ***************************************************************************/
3161 static char *win_driver;
3162 static char *os2_driver;
3164 static const char *get_win_driver(void)
3166 if (win_driver == NULL) {
3167 return "";
3169 return win_driver;
3172 static const char *get_os2_driver(void)
3174 if (os2_driver == NULL) {
3175 return "";
3177 return os2_driver;
3180 static bool set_driver_mapping(const char *from, const char *to)
3182 SAFE_FREE(win_driver);
3183 SAFE_FREE(os2_driver);
3185 win_driver = SMB_STRDUP(from);
3186 os2_driver = SMB_STRDUP(to);
3188 if (win_driver == NULL || os2_driver == NULL) {
3189 SAFE_FREE(win_driver);
3190 SAFE_FREE(os2_driver);
3191 return false;
3193 return true;
3197 * @internal
3199 * @brief Map a Windows driver to a OS/2 driver.
3201 * @param[in] mem_ctx The memory context to use.
3203 * @param[in,out] pdrivername The drivername of Windows to remap.
3205 * @return WERR_OK on success, a corresponding WERROR on failure.
3207 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3209 const char *mapfile = lp_os2_driver_map();
3210 char **lines = NULL;
3211 const char *drivername;
3212 int numlines = 0;
3213 int i;
3215 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3216 return WERR_INVALID_PARAMETER;
3219 drivername = *pdrivername;
3221 if (mapfile[0] == '\0') {
3222 return WERR_BADFILE;
3225 if (strequal(drivername, get_win_driver())) {
3226 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3227 drivername, get_os2_driver()));
3228 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3229 if (drivername == NULL) {
3230 return WERR_NOMEM;
3232 *pdrivername = drivername;
3233 return WERR_OK;
3236 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3237 if (numlines == 0 || lines == NULL) {
3238 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3239 TALLOC_FREE(lines);
3240 return WERR_EMPTY;
3243 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3245 for( i = 0; i < numlines; i++) {
3246 char *nt_name = lines[i];
3247 char *os2_name = strchr(nt_name, '=');
3249 if (os2_name == NULL) {
3250 continue;
3253 *os2_name++ = '\0';
3255 while (isspace(*nt_name)) {
3256 nt_name++;
3259 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3260 continue;
3264 int l = strlen(nt_name);
3265 while (l && isspace(nt_name[l - 1])) {
3266 nt_name[l - 1] = 0;
3267 l--;
3271 while (isspace(*os2_name)) {
3272 os2_name++;
3276 int l = strlen(os2_name);
3277 while (l && isspace(os2_name[l-1])) {
3278 os2_name[l-1] = 0;
3279 l--;
3283 if (strequal(nt_name, drivername)) {
3284 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3285 set_driver_mapping(drivername, os2_name);
3286 drivername = talloc_strdup(mem_ctx, os2_name);
3287 TALLOC_FREE(lines);
3288 if (drivername == NULL) {
3289 return WERR_NOMEM;
3291 *pdrivername = drivername;
3292 return WERR_OK;
3296 TALLOC_FREE(lines);
3297 return WERR_OK;
3300 /****************************************************************************
3301 Deletes a NT_PRINTER_INFO_LEVEL struct.
3302 ****************************************************************************/
3304 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3306 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3308 if ( !printer )
3309 return 0;
3311 switch (level) {
3312 case 2:
3313 TALLOC_FREE(printer->info_2);
3314 break;
3316 default:
3317 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
3318 return 1;
3321 TALLOC_FREE(*pp_printer);
3323 return 0;
3326 /****************************************************************************
3327 ****************************************************************************/
3329 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
3330 struct spoolss_DriverInfo8 *_info8)
3332 struct spoolss_DriverInfo8 info8;
3334 ZERO_STRUCT(info8);
3336 switch (r->level) {
3337 case 3:
3338 info8.version = r->info.info3->version;
3339 info8.driver_name = r->info.info3->driver_name;
3340 info8.architecture = r->info.info3->architecture;
3341 info8.driver_path = r->info.info3->driver_path;
3342 info8.data_file = r->info.info3->data_file;
3343 info8.config_file = r->info.info3->config_file;
3344 info8.help_file = r->info.info3->help_file;
3345 info8.monitor_name = r->info.info3->monitor_name;
3346 info8.default_datatype = r->info.info3->default_datatype;
3347 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
3348 info8.dependent_files = r->info.info3->dependent_files->string;
3350 break;
3351 case 6:
3352 info8.version = r->info.info6->version;
3353 info8.driver_name = r->info.info6->driver_name;
3354 info8.architecture = r->info.info6->architecture;
3355 info8.driver_path = r->info.info6->driver_path;
3356 info8.data_file = r->info.info6->data_file;
3357 info8.config_file = r->info.info6->config_file;
3358 info8.help_file = r->info.info6->help_file;
3359 info8.monitor_name = r->info.info6->monitor_name;
3360 info8.default_datatype = r->info.info6->default_datatype;
3361 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
3362 info8.dependent_files = r->info.info6->dependent_files->string;
3364 info8.driver_date = r->info.info6->driver_date;
3365 info8.driver_version = r->info.info6->driver_version;
3366 info8.manufacturer_name = r->info.info6->manufacturer_name;
3367 info8.manufacturer_url = r->info.info6->manufacturer_url;
3368 info8.hardware_id = r->info.info6->hardware_id;
3369 info8.provider = r->info.info6->provider;
3370 break;
3371 case 8:
3372 info8.version = r->info.info8->version;
3373 info8.driver_name = r->info.info8->driver_name;
3374 info8.architecture = r->info.info8->architecture;
3375 info8.driver_path = r->info.info8->driver_path;
3376 info8.data_file = r->info.info8->data_file;
3377 info8.config_file = r->info.info8->config_file;
3378 info8.help_file = r->info.info8->help_file;
3379 info8.monitor_name = r->info.info8->monitor_name;
3380 info8.default_datatype = r->info.info8->default_datatype;
3381 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
3382 info8.dependent_files = r->info.info8->dependent_files->string;
3384 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
3385 info8.previous_names = r->info.info8->previous_names->string;
3387 info8.driver_date = r->info.info8->driver_date;
3388 info8.driver_version = r->info.info8->driver_version;
3389 info8.manufacturer_name = r->info.info8->manufacturer_name;
3390 info8.manufacturer_url = r->info.info8->manufacturer_url;
3391 info8.hardware_id = r->info.info8->hardware_id;
3392 info8.provider = r->info.info8->provider;
3393 info8.print_processor = r->info.info8->print_processor;
3394 info8.vendor_setup = r->info.info8->vendor_setup;
3395 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
3396 info8.color_profiles = r->info.info8->color_profiles->string;
3398 info8.inf_path = r->info.info8->inf_path;
3399 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
3400 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
3401 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
3403 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
3404 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
3405 break;
3406 default:
3407 return false;
3410 *_info8 = info8;
3412 return true;
3416 /****************************************************************************
3417 Determine whether or not a particular driver is currently assigned
3418 to a printer
3419 ****************************************************************************/
3421 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
3422 struct auth_serversupplied_info *server_info,
3423 const struct spoolss_DriverInfo8 *r)
3425 int snum;
3426 int n_services = lp_numservices();
3427 bool in_use = False;
3428 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3429 WERROR result;
3431 if (!r) {
3432 return false;
3435 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3437 /* loop through the printers.tdb and check for the drivername */
3439 for (snum=0; snum<n_services && !in_use; snum++) {
3440 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
3441 continue;
3444 result = winreg_get_printer(mem_ctx, server_info, NULL,
3445 lp_servicename(snum), &pinfo2);
3446 if (!W_ERROR_IS_OK(result)) {
3447 continue; /* skip */
3450 if (strequal(r->driver_name, pinfo2->drivername)) {
3451 in_use = True;
3454 TALLOC_FREE(pinfo2);
3457 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3459 if ( in_use ) {
3460 struct spoolss_DriverInfo8 *driver;
3461 WERROR werr;
3463 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
3465 /* we can still remove the driver if there is one of
3466 "Windows NT x86" version 2 or 3 left */
3468 if (!strequal("Windows NT x86", r->architecture)) {
3469 werr = winreg_get_driver(mem_ctx, server_info,
3470 "Windows NT x86",
3471 r->driver_name,
3472 DRIVER_ANY_VERSION,
3473 &driver);
3474 } else if (r->version == 2) {
3475 werr = winreg_get_driver(mem_ctx, server_info,
3476 "Windows NT x86",
3477 r->driver_name,
3478 3, &driver);
3479 } else if (r->version == 3) {
3480 werr = winreg_get_driver(mem_ctx, server_info,
3481 "Windows NT x86",
3482 r->driver_name,
3483 2, &driver);
3484 } else {
3485 DEBUG(0, ("printer_driver_in_use: ERROR!"
3486 " unknown driver version (%d)\n",
3487 r->version));
3488 werr = WERR_UNKNOWN_PRINTER_DRIVER;
3491 /* now check the error code */
3493 if ( W_ERROR_IS_OK(werr) ) {
3494 /* it's ok to remove the driver, we have other architctures left */
3495 in_use = False;
3496 talloc_free(driver);
3500 /* report that the driver is not in use by default */
3502 return in_use;
3506 /**********************************************************************
3507 Check to see if a ogiven file is in use by *info
3508 *********************************************************************/
3510 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
3512 int i = 0;
3514 if ( !info )
3515 return False;
3517 /* mz: skip files that are in the list but already deleted */
3518 if (!file || !file[0]) {
3519 return false;
3522 if (strequal(file, info->driver_path))
3523 return True;
3525 if (strequal(file, info->data_file))
3526 return True;
3528 if (strequal(file, info->config_file))
3529 return True;
3531 if (strequal(file, info->help_file))
3532 return True;
3534 /* see of there are any dependent files to examine */
3536 if (!info->dependent_files)
3537 return False;
3539 while (info->dependent_files[i] && *info->dependent_files[i]) {
3540 if (strequal(file, info->dependent_files[i]))
3541 return True;
3542 i++;
3545 return False;
3549 /**********************************************************************
3550 Utility function to remove the dependent file pointed to by the
3551 input parameter from the list
3552 *********************************************************************/
3554 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
3557 /* bump everything down a slot */
3559 while (files && files[idx+1]) {
3560 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
3561 idx++;
3564 files[idx] = NULL;
3566 return;
3569 /**********************************************************************
3570 Check if any of the files used by src are also used by drv
3571 *********************************************************************/
3573 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
3574 struct spoolss_DriverInfo8 *src,
3575 const struct spoolss_DriverInfo8 *drv)
3577 bool in_use = False;
3578 int i = 0;
3580 if ( !src || !drv )
3581 return False;
3583 /* check each file. Remove it from the src structure if it overlaps */
3585 if (drv_file_in_use(src->driver_path, drv)) {
3586 in_use = True;
3587 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
3588 src->driver_path = talloc_strdup(mem_ctx, "");
3589 if (!src->driver_path) { return false; }
3592 if (drv_file_in_use(src->data_file, drv)) {
3593 in_use = True;
3594 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
3595 src->data_file = talloc_strdup(mem_ctx, "");
3596 if (!src->data_file) { return false; }
3599 if (drv_file_in_use(src->config_file, drv)) {
3600 in_use = True;
3601 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
3602 src->config_file = talloc_strdup(mem_ctx, "");
3603 if (!src->config_file) { return false; }
3606 if (drv_file_in_use(src->help_file, drv)) {
3607 in_use = True;
3608 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
3609 src->help_file = talloc_strdup(mem_ctx, "");
3610 if (!src->help_file) { return false; }
3613 /* are there any dependentfiles to examine? */
3615 if (!src->dependent_files)
3616 return in_use;
3618 while (src->dependent_files[i] && *src->dependent_files[i]) {
3619 if (drv_file_in_use(src->dependent_files[i], drv)) {
3620 in_use = True;
3621 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
3622 trim_dependent_file(mem_ctx, src->dependent_files, i);
3623 } else
3624 i++;
3627 return in_use;
3630 /****************************************************************************
3631 Determine whether or not a particular driver files are currently being
3632 used by any other driver.
3634 Return value is True if any files were in use by other drivers
3635 and False otherwise.
3637 Upon return, *info has been modified to only contain the driver files
3638 which are not in use
3640 Fix from mz:
3642 This needs to check all drivers to ensure that all files in use
3643 have been removed from *info, not just the ones in the first
3644 match.
3645 ****************************************************************************/
3647 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
3648 struct auth_serversupplied_info *server_info,
3649 struct spoolss_DriverInfo8 *info)
3651 int i;
3652 uint32 version;
3653 struct spoolss_DriverInfo8 *driver;
3654 bool in_use = false;
3655 uint32_t num_drivers;
3656 const char **drivers;
3657 WERROR result;
3659 if ( !info )
3660 return False;
3662 version = info->version;
3664 /* loop over all driver versions */
3666 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
3668 /* get the list of drivers */
3670 result = winreg_get_driver_list(mem_ctx, server_info,
3671 info->architecture, version,
3672 &num_drivers, &drivers);
3673 if (!W_ERROR_IS_OK(result)) {
3674 return true;
3677 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
3678 num_drivers, info->architecture, version));
3680 /* check each driver for overlap in files */
3682 for (i = 0; i < num_drivers; i++) {
3683 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
3685 driver = NULL;
3687 result = winreg_get_driver(mem_ctx, server_info,
3688 info->architecture, drivers[i],
3689 version, &driver);
3690 if (!W_ERROR_IS_OK(result)) {
3691 talloc_free(drivers);
3692 return True;
3695 /* check if d2 uses any files from d1 */
3696 /* only if this is a different driver than the one being deleted */
3698 if (!strequal(info->driver_name, driver->driver_name)) {
3699 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
3700 /* mz: Do not instantly return -
3701 * we need to ensure this file isn't
3702 * also in use by other drivers. */
3703 in_use = true;
3707 talloc_free(driver);
3710 talloc_free(drivers);
3712 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
3714 return in_use;
3717 static NTSTATUS driver_unlink_internals(connection_struct *conn,
3718 const char *name)
3720 struct smb_filename *smb_fname = NULL;
3721 NTSTATUS status;
3723 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
3724 &smb_fname);
3725 if (!NT_STATUS_IS_OK(status)) {
3726 return status;
3729 status = unlink_internals(conn, NULL, 0, smb_fname, false);
3731 TALLOC_FREE(smb_fname);
3732 return status;
3735 /****************************************************************************
3736 Actually delete the driver files. Make sure that
3737 printer_driver_files_in_use() return False before calling
3738 this.
3739 ****************************************************************************/
3741 bool delete_driver_files(struct auth_serversupplied_info *server_info,
3742 const struct spoolss_DriverInfo8 *r)
3744 int i = 0;
3745 char *s;
3746 const char *file;
3747 connection_struct *conn;
3748 NTSTATUS nt_status;
3749 char *oldcwd;
3750 fstring printdollar;
3751 int printdollar_snum;
3752 bool ret = false;
3754 if (!r) {
3755 return false;
3758 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
3759 r->driver_name, r->version));
3761 fstrcpy(printdollar, "print$");
3763 printdollar_snum = find_service(printdollar);
3764 if (printdollar_snum == -1) {
3765 return false;
3768 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
3769 lp_pathname(printdollar_snum),
3770 server_info, &oldcwd);
3771 if (!NT_STATUS_IS_OK(nt_status)) {
3772 DEBUG(0,("delete_driver_files: create_conn_struct "
3773 "returned %s\n", nt_errstr(nt_status)));
3774 return false;
3777 if ( !CAN_WRITE(conn) ) {
3778 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
3779 goto fail;
3782 /* now delete the files; must strip the '\print$' string from
3783 fron of path */
3785 if (r->driver_path && r->driver_path[0]) {
3786 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
3787 file = s;
3788 DEBUG(10,("deleting driverfile [%s]\n", s));
3789 driver_unlink_internals(conn, file);
3793 if (r->config_file && r->config_file[0]) {
3794 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
3795 file = s;
3796 DEBUG(10,("deleting configfile [%s]\n", s));
3797 driver_unlink_internals(conn, file);
3801 if (r->data_file && r->data_file[0]) {
3802 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
3803 file = s;
3804 DEBUG(10,("deleting datafile [%s]\n", s));
3805 driver_unlink_internals(conn, file);
3809 if (r->help_file && r->help_file[0]) {
3810 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
3811 file = s;
3812 DEBUG(10,("deleting helpfile [%s]\n", s));
3813 driver_unlink_internals(conn, file);
3817 /* check if we are done removing files */
3819 if (r->dependent_files) {
3820 while (r->dependent_files[i] && r->dependent_files[i][0]) {
3821 char *p;
3823 /* bypass the "\print$" portion of the path */
3825 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
3826 file = p;
3827 DEBUG(10,("deleting dependent file [%s]\n", file));
3828 driver_unlink_internals(conn, file);
3831 i++;
3835 goto done;
3836 fail:
3837 ret = false;
3838 done:
3839 if (conn != NULL) {
3840 vfs_ChDir(conn, oldcwd);
3841 conn_free(conn);
3843 return ret;
3846 /****************************************************************************
3847 Store a security desc for a printer.
3848 ****************************************************************************/
3850 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
3852 struct sec_desc_buf *new_secdesc_ctr = NULL;
3853 struct sec_desc_buf *old_secdesc_ctr = NULL;
3854 TALLOC_CTX *mem_ctx = NULL;
3855 TDB_DATA kbuf;
3856 TDB_DATA dbuf;
3857 DATA_BLOB blob;
3858 WERROR status;
3859 NTSTATUS nt_status;
3861 mem_ctx = talloc_init("nt_printing_setsec");
3862 if (mem_ctx == NULL)
3863 return WERR_NOMEM;
3865 /* The old owner and group sids of the security descriptor are not
3866 present when new ACEs are added or removed by changing printer
3867 permissions through NT. If they are NULL in the new security
3868 descriptor then copy them over from the old one. */
3870 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
3871 struct dom_sid *owner_sid, *group_sid;
3872 struct security_acl *dacl, *sacl;
3873 struct security_descriptor *psd = NULL;
3874 size_t size;
3876 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
3877 status = WERR_NOMEM;
3878 goto out;
3881 /* Pick out correct owner and group sids */
3883 owner_sid = secdesc_ctr->sd->owner_sid ?
3884 secdesc_ctr->sd->owner_sid :
3885 old_secdesc_ctr->sd->owner_sid;
3887 group_sid = secdesc_ctr->sd->group_sid ?
3888 secdesc_ctr->sd->group_sid :
3889 old_secdesc_ctr->sd->group_sid;
3891 dacl = secdesc_ctr->sd->dacl ?
3892 secdesc_ctr->sd->dacl :
3893 old_secdesc_ctr->sd->dacl;
3895 sacl = secdesc_ctr->sd->sacl ?
3896 secdesc_ctr->sd->sacl :
3897 old_secdesc_ctr->sd->sacl;
3899 /* Make a deep copy of the security descriptor */
3901 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
3902 owner_sid, group_sid,
3903 sacl,
3904 dacl,
3905 &size);
3907 if (!psd) {
3908 status = WERR_NOMEM;
3909 goto out;
3912 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3915 if (!new_secdesc_ctr) {
3916 new_secdesc_ctr = secdesc_ctr;
3919 /* Store the security descriptor in a tdb */
3921 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
3922 &blob.data, &blob.length);
3923 if (!NT_STATUS_IS_OK(nt_status)) {
3924 status = ntstatus_to_werror(nt_status);
3925 goto out;
3928 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
3930 dbuf.dptr = (unsigned char *)blob.data;
3931 dbuf.dsize = blob.length;
3933 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
3934 status = WERR_OK;
3935 } else {
3936 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
3937 status = WERR_BADFUNC;
3940 /* Free malloc'ed memory */
3941 talloc_free(blob.data);
3943 out:
3945 if (mem_ctx)
3946 talloc_destroy(mem_ctx);
3947 return status;
3950 /****************************************************************************
3951 Construct a default security descriptor buffer for a printer.
3952 ****************************************************************************/
3954 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
3956 struct security_ace ace[7]; /* max number of ace entries */
3957 int i = 0;
3958 uint32_t sa;
3959 struct security_acl *psa = NULL;
3960 struct sec_desc_buf *sdb = NULL;
3961 struct security_descriptor *psd = NULL;
3962 struct dom_sid adm_sid;
3963 size_t sd_size;
3965 /* Create an ACE where Everyone is allowed to print */
3967 sa = PRINTER_ACE_PRINT;
3968 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3969 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3971 /* Add the domain admins group if we are a DC */
3973 if ( IS_DC ) {
3974 struct dom_sid domadmins_sid;
3976 sid_compose(&domadmins_sid, get_global_sam_sid(),
3977 DOMAIN_RID_ADMINS);
3979 sa = PRINTER_ACE_FULL_CONTROL;
3980 init_sec_ace(&ace[i++], &domadmins_sid,
3981 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3982 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3983 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3984 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3986 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
3987 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
3989 sa = PRINTER_ACE_FULL_CONTROL;
3990 init_sec_ace(&ace[i++], &adm_sid,
3991 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
3992 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
3993 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3994 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3997 /* add BUILTIN\Administrators as FULL CONTROL */
3999 sa = PRINTER_ACE_FULL_CONTROL;
4000 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4001 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4002 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4003 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4004 SEC_ACE_TYPE_ACCESS_ALLOWED,
4005 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4007 /* add BUILTIN\Print Operators as FULL CONTROL */
4009 sa = PRINTER_ACE_FULL_CONTROL;
4010 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4011 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4012 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4013 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4014 SEC_ACE_TYPE_ACCESS_ALLOWED,
4015 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4017 /* Make the security descriptor owned by the BUILTIN\Administrators */
4019 /* The ACL revision number in rpc_secdesc.h differs from the one
4020 created by NT when setting ACE entries in printer
4021 descriptors. NT4 complains about the property being edited by a
4022 NT5 machine. */
4024 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
4025 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
4026 &global_sid_Builtin_Administrators,
4027 &global_sid_Builtin_Administrators,
4028 NULL, psa, &sd_size);
4031 if (!psd) {
4032 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4033 return NULL;
4036 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4038 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4039 (unsigned int)sd_size));
4041 return sdb;
4044 /****************************************************************************
4045 Get a security desc for a printer.
4046 ****************************************************************************/
4048 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
4050 TDB_DATA kbuf;
4051 TDB_DATA dbuf;
4052 DATA_BLOB blob;
4053 char *temp;
4054 NTSTATUS status;
4056 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
4057 sharename = temp + 1;
4060 /* Fetch security descriptor from tdb */
4062 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
4064 dbuf = tdb_fetch(tdb_printers, kbuf);
4065 if (dbuf.dptr) {
4067 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
4068 secdesc_ctr);
4069 SAFE_FREE(dbuf.dptr);
4071 if (NT_STATUS_IS_OK(status)) {
4072 return true;
4076 *secdesc_ctr = construct_default_printer_sdb(ctx);
4077 if (!*secdesc_ctr) {
4078 return false;
4081 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
4082 &blob.data, &blob.length);
4083 if (NT_STATUS_IS_OK(status)) {
4084 dbuf.dptr = (unsigned char *)blob.data;
4085 dbuf.dsize = blob.length;
4086 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
4087 talloc_free(blob.data);
4090 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4091 this security descriptor has been created when winbindd was
4092 down. Take ownership of security descriptor. */
4094 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
4095 struct dom_sid owner_sid;
4097 /* Change sd owner to workgroup administrator */
4099 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4100 struct sec_desc_buf *new_secdesc_ctr = NULL;
4101 struct security_descriptor *psd = NULL;
4102 size_t size;
4104 /* Create new sd */
4106 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
4108 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
4109 &owner_sid,
4110 (*secdesc_ctr)->sd->group_sid,
4111 (*secdesc_ctr)->sd->sacl,
4112 (*secdesc_ctr)->sd->dacl,
4113 &size);
4115 if (!psd) {
4116 return False;
4119 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4120 if (!new_secdesc_ctr) {
4121 return False;
4124 /* Swap with other one */
4126 *secdesc_ctr = new_secdesc_ctr;
4128 /* Set it */
4130 nt_printing_setsec(sharename, *secdesc_ctr);
4134 if (DEBUGLEVEL >= 10) {
4135 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
4136 int i;
4138 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4139 sharename, the_acl->num_aces));
4141 for (i = 0; i < the_acl->num_aces; i++) {
4142 DEBUG(10, ("%s %d %d 0x%08x\n",
4143 sid_string_dbg(&the_acl->aces[i].trustee),
4144 the_acl->aces[i].type, the_acl->aces[i].flags,
4145 the_acl->aces[i].access_mask));
4149 return True;
4152 /* error code:
4153 0: everything OK
4154 1: level not implemented
4155 2: file doesn't exist
4156 3: can't allocate memory
4157 4: can't free memory
4158 5: non existant struct
4162 A printer and a printer driver are 2 different things.
4163 NT manages them separatelly, Samba does the same.
4164 Why ? Simply because it's easier and it makes sense !
4166 Now explanation: You have 3 printers behind your samba server,
4167 2 of them are the same make and model (laser A and B). But laser B
4168 has an 3000 sheet feeder and laser A doesn't such an option.
4169 Your third printer is an old dot-matrix model for the accounting :-).
4171 If the /usr/local/samba/lib directory (default dir), you will have
4172 5 files to describe all of this.
4174 3 files for the printers (1 by printer):
4175 NTprinter_laser A
4176 NTprinter_laser B
4177 NTprinter_accounting
4178 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4179 NTdriver_printer model X
4180 NTdriver_printer model Y
4182 jfm: I should use this comment for the text file to explain
4183 same thing for the forms BTW.
4184 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4188 /* Convert generic access rights to printer object specific access rights.
4189 It turns out that NT4 security descriptors use generic access rights and
4190 NT5 the object specific ones. */
4192 void map_printer_permissions(struct security_descriptor *sd)
4194 int i;
4196 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4197 se_map_generic(&sd->dacl->aces[i].access_mask,
4198 &printer_generic_mapping);
4202 void map_job_permissions(struct security_descriptor *sd)
4204 int i;
4206 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4207 se_map_generic(&sd->dacl->aces[i].access_mask,
4208 &job_generic_mapping);
4213 /****************************************************************************
4214 Check a user has permissions to perform the given operation. We use the
4215 permission constants defined in include/rpc_spoolss.h to check the various
4216 actions we perform when checking printer access.
4218 PRINTER_ACCESS_ADMINISTER:
4219 print_queue_pause, print_queue_resume, update_printer_sec,
4220 update_printer, spoolss_addprinterex_level_2,
4221 _spoolss_setprinterdata
4223 PRINTER_ACCESS_USE:
4224 print_job_start
4226 JOB_ACCESS_ADMINISTER:
4227 print_job_delete, print_job_pause, print_job_resume,
4228 print_queue_purge
4230 Try access control in the following order (for performance reasons):
4231 1) root and SE_PRINT_OPERATOR can do anything (easy check)
4232 2) check security descriptor (bit comparisons in memory)
4233 3) "printer admins" (may result in numerous calls to winbind)
4235 ****************************************************************************/
4236 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
4237 int access_type)
4239 struct spoolss_security_descriptor *secdesc = NULL;
4240 uint32 access_granted;
4241 size_t sd_size;
4242 NTSTATUS status;
4243 WERROR result;
4244 const char *pname;
4245 TALLOC_CTX *mem_ctx = NULL;
4246 SE_PRIV se_printop = SE_PRINT_OPERATOR;
4248 /* If user is NULL then use the current_user structure */
4250 /* Always allow root or SE_PRINT_OPERATROR to do anything */
4252 if (server_info->utok.uid == sec_initial_uid()
4253 || user_has_privileges(server_info->ptok, &se_printop ) ) {
4254 return True;
4257 /* Get printer name */
4259 pname = lp_printername(snum);
4261 if (!pname || !*pname) {
4262 errno = EACCES;
4263 return False;
4266 /* Get printer security descriptor */
4268 if(!(mem_ctx = talloc_init("print_access_check"))) {
4269 errno = ENOMEM;
4270 return False;
4273 result = winreg_get_printer_secdesc(mem_ctx,
4274 server_info,
4275 pname,
4276 &secdesc);
4277 if (!W_ERROR_IS_OK(result)) {
4278 talloc_destroy(mem_ctx);
4279 errno = ENOMEM;
4280 return False;
4283 if (access_type == JOB_ACCESS_ADMINISTER) {
4284 struct spoolss_security_descriptor *parent_secdesc = secdesc;
4286 /* Create a child security descriptor to check permissions
4287 against. This is because print jobs are child objects
4288 objects of a printer. */
4289 status = se_create_child_secdesc(mem_ctx,
4290 &secdesc,
4291 &sd_size,
4292 parent_secdesc,
4293 parent_secdesc->owner_sid,
4294 parent_secdesc->group_sid,
4295 false);
4296 if (!NT_STATUS_IS_OK(status)) {
4297 talloc_destroy(mem_ctx);
4298 errno = map_errno_from_nt_status(status);
4299 return False;
4302 map_job_permissions(secdesc);
4303 } else {
4304 map_printer_permissions(secdesc);
4307 /* Check access */
4308 status = se_access_check(secdesc, server_info->ptok, access_type,
4309 &access_granted);
4311 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
4313 /* see if we need to try the printer admin list */
4315 if (!NT_STATUS_IS_OK(status) &&
4316 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
4317 server_info->info3->base.domain.string,
4318 NULL, server_info->ptok,
4319 lp_printer_admin(snum)))) {
4320 talloc_destroy(mem_ctx);
4321 return True;
4324 talloc_destroy(mem_ctx);
4326 if (!NT_STATUS_IS_OK(status)) {
4327 errno = EACCES;
4330 return NT_STATUS_IS_OK(status);
4333 /****************************************************************************
4334 Check the time parameters allow a print operation.
4335 *****************************************************************************/
4337 bool print_time_access_check(struct auth_serversupplied_info *server_info,
4338 const char *servicename)
4340 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4341 WERROR result;
4342 bool ok = False;
4343 time_t now = time(NULL);
4344 struct tm *t;
4345 uint32 mins;
4347 result = winreg_get_printer(NULL, server_info,
4348 NULL, servicename, &pinfo2);
4349 if (!W_ERROR_IS_OK(result)) {
4350 return False;
4353 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
4354 ok = True;
4357 t = gmtime(&now);
4358 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4360 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
4361 ok = True;
4364 TALLOC_FREE(pinfo2);
4366 if (!ok) {
4367 errno = EACCES;
4370 return ok;
4373 void nt_printer_remove(TALLOC_CTX *mem_ctx,
4374 struct auth_serversupplied_info *server_info,
4375 const char *printer)
4377 WERROR result;
4379 result = winreg_delete_printer_key(mem_ctx, server_info, printer, "");
4380 if (!W_ERROR_IS_OK(result)) {
4381 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",
4382 printer));