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/>.
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.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 = {
57 const struct standard_mapping printer_std_mapping = {
64 /* Map generic permissions to print server object specific permissions */
66 const struct generic_mapping printserver_generic_mapping = {
73 const struct generic_mapping printserver_std_mapping = {
80 /* Map generic permissions to job object specific permissions */
82 const struct generic_mapping job_generic_mapping = {
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 },
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 )
239 fstrcpy(share, sharename);
242 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
243 key = string_term_tdb_data(keystr ? keystr : "");
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 )
259 fstrcpy(share, sharename );
262 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
263 key = string_term_tdb_data(keystr ? keystr : "");
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)));
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)));
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)));
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)));
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)));
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)));
324 SAFE_FREE(dbuf.dptr);
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 )
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;
350 if (!data.dptr || data.dsize == 0) {
354 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 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 );
374 /* is this even valid? */
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;
388 case GENERIC_ALL_ACCESS:
389 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
392 case READ_CONTROL_ACCESS:
393 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
395 default: /* no change */
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 );
409 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
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 ));
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 ));
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)
445 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
447 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
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();
471 if (!data.dptr || data.dsize == 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) );
483 /* ignore this record */
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",
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",
504 /*******************************************************************
505 *******************************************************************/
507 static bool upgrade_to_version_5(void)
512 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
514 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
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";
534 if ( tdb_drivers && tdb_printers && tdb_forms )
538 tdb_close(tdb_drivers);
539 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
541 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
542 state_path("ntdrivers.tdb"), strerror(errno) ));
547 tdb_close(tdb_printers);
548 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
550 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
551 state_path("ntprinters.tdb"), strerror(errno) ));
556 tdb_close(tdb_forms);
557 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
559 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
560 state_path("ntforms.tdb"), strerror(errno) ));
564 /* handle a Samba upgrade */
566 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
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())
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() )
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() )
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));
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)));
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)
641 TALLOC_CTX *ctx = talloc_tos();
642 char *name = talloc_strdup(ctx, old_name);
645 return NT_STATUS_NO_MEMORY;
648 name = unix_clean_name(ctx, 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;
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) {
673 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
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)
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
700 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
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));
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)
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));
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;
774 for (kbuf = tdb_firstkey(tdb_forms);
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)
781 dbuf = tdb_fetch(tdb_forms, kbuf);
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)
793 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
795 DEBUG(0,("get_ntforms: Realloc fail.\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();
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,
828 buf = TALLOC_ARRAY(ctx, char, len);
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,
836 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
841 dbuf.dptr = (uint8 *)buf;
842 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
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)
863 * NT tries to add forms even when
864 * they are already in the base
865 * only update the values if already present
870 for (n=0; n<*count; n++) {
871 if ( strequal((*list)[n].name, form->form_name) ) {
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"));
882 fstrcpy((*list)[n].name, form->form_name);
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));
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)
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));
919 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
920 *ret = WERR_INVALID_FORM_NAME;
924 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
928 if (tdb_delete_bystring(tdb_forms, key) != 0) {
937 /****************************************************************************
938 Update a form struct.
939 ****************************************************************************/
941 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
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)))
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
966 ****************************************************************************/
968 const char *get_short_archi(const char *long_archi)
972 DEBUG(107,("Getting architecture dependant directory\n"));
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));
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)
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));
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",
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",
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)
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));
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));
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)
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));
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",
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));
1105 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
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));
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));
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. */
1144 /* Allocate a bit more space to speed up things */
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));
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) {
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",
1177 byte_count = bc + (byte_count - i);
1178 if (byte_count<VS_VERSION_INFO_SIZE) break;
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));
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));
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)));
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;
1240 time_t new_create_time;
1244 time_t old_create_time;
1246 struct smb_filename *smb_fname = NULL;
1247 files_struct *fsp = NULL;
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)) {
1263 status = SMB_VFS_CREATE_FILE(
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 */
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),
1290 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1296 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1298 use_version = false;
1299 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
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);
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)) {
1316 status = SMB_VFS_CREATE_FILE(
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 */
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));
1341 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1347 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1349 use_version = false;
1350 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
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);
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));
1371 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
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));
1384 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1392 close_file(NULL, fsp, NORMAL_CLOSE);
1395 TALLOC_FREE(smb_fname);
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,
1409 struct smb_filename *smb_fname = NULL;
1410 char *driverpath = NULL;
1411 files_struct *fsp = NULL;
1412 connection_struct *conn = NULL;
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"));
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"));
1434 fstrcpy(printdollar, "print$");
1436 printdollar_snum = find_service(printdollar);
1437 if (printdollar_snum == -1) {
1438 *perr = WERR_NO_SUCH_SHARE;
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);
1452 /* Open the driver file (Portable Executable format) and determine the
1453 * deriver the cversion. */
1454 driverpath = talloc_asprintf(talloc_tos(),
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);
1469 nt_status = vfs_file_exist(conn, smb_fname);
1470 if (!NT_STATUS_IS_OK(nt_status)) {
1471 *perr = WERR_BADFILE;
1475 status = SMB_VFS_CREATE_FILE(
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 */
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;
1503 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1504 if (ret == -1) goto error_exit;
1507 DEBUG(6,("get_correct_cversion: Version info not "
1509 smb_fname_str_dbg(smb_fname)));
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.
1520 cversion = major & 0x0000ffff;
1522 case 2: /* WinNT drivers */
1523 case 3: /* Win2K drivers */
1527 DEBUG(6,("get_correct_cversion: cversion "
1528 "invalid [%s] cversion = %d\n",
1529 smb_fname_str_dbg(smb_fname),
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));
1547 TALLOC_FREE(smb_fname);
1549 close_file(NULL, fsp, NORMAL_CLOSE);
1552 vfs_ChDir(conn, oldcwd);
1555 if (cversion != -1) {
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)); \
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,
1581 const char *short_architecture;
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);
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
1626 *version = get_correct_cversion(rpc_pipe, short_architecture,
1627 *driver_path, &err);
1628 if (*version == -1) {
1635 /****************************************************************************
1636 ****************************************************************************/
1638 WERROR clean_up_driver_struct(TALLOC_CTX *mem_ctx,
1639 struct pipes_struct *rpc_pipe,
1640 struct spoolss_AddDriverInfoCtr *r)
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);
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);
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,
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;
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);
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)) {
1723 /* Setup a synthetic smb_filename struct */
1724 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1725 if (!smb_fname_new) {
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,
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;
1753 TALLOC_FREE(smb_fname_old);
1754 TALLOC_FREE(smb_fname_new);
1758 WERROR move_driver_to_download_area(struct pipes_struct *p,
1759 struct spoolss_AddDriverInfoCtr *r,
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;
1770 TALLOC_CTX *ctx = talloc_tos();
1773 fstring printdollar;
1774 int printdollar_snum;
1780 driver = r->info.info3;
1783 convert_level_6_to_level3(&converted_driver, r->info.info6);
1784 driver = &converted_driver;
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);
1814 new_dir = talloc_asprintf(ctx,
1822 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1823 if (!NT_STATUS_IS_OK(nt_status)) {
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,
1855 driver->driver_path,
1859 if (!W_ERROR_IS_OK(*perr)) {
1860 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
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,
1876 if (!W_ERROR_IS_OK(*perr)) {
1877 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
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,
1891 driver->config_file,
1895 if (!W_ERROR_IS_OK(*perr)) {
1896 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
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,
1915 if (!W_ERROR_IS_OK(*perr)) {
1916 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
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)) {
1931 for (j=0; j < i; j++) {
1932 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
1937 *perr = move_driver_file_to_download_area(ctx,
1939 driver->dependent_files->string[i],
1943 if (!W_ERROR_IS_OK(*perr)) {
1944 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1955 TALLOC_FREE(smb_dname);
1958 vfs_ChDir(conn, oldcwd);
1962 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
1966 return WERR_UNKNOWN_PRINTER_DRIVER;
1971 /****************************************************************************
1972 ****************************************************************************/
1973 int pack_devicemode(struct spoolss_DeviceMode *devmode, uint8 *buf, int buflen)
1975 enum ndr_err_code ndr_err;
1980 ndr_err = ndr_push_struct_blob(&blob, talloc_tos(),
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"));
1993 len = tdb_pack(buf, buflen, "B", blob.length, blob.data);
1996 DEBUG(8, ("Packed devicemode [%s]\n", devmode->formname));
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;
2018 len = tdb_unpack(buf, buflen, "B", &data_len, &data);
2023 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
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"));
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));
2052 /****************************************************************************
2053 Pack all values in all printer keys
2054 ***************************************************************************/
2056 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2060 struct regval_blob *val;
2061 struct regval_ctr *val_ctr;
2068 /* loop over all keys */
2070 for ( i=0; i<data->num_keys; i++ ) {
2071 val_ctr = data->keys[i].values;
2072 num_values = regval_ctr_numvals( val_ctr );
2074 /* pack the keyname followed by a empty value */
2076 len += tdb_pack(buf+len, buflen-len, "pPdB",
2077 &data->keys[i].name,
2083 /* now loop over all values */
2085 for ( j=0; j<num_values; j++ ) {
2086 /* pathname should be stored as <key>\<value> */
2088 val = regval_ctr_specific_value( val_ctr, j );
2089 if (asprintf(&path, "%s\\%s",
2091 regval_name(val)) < 0) {
2095 len += tdb_pack(buf+len, buflen-len, "pPdB",
2100 regval_data_p(val) );
2102 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2110 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2116 /****************************************************************************
2117 Delete a printer - this just deletes the printer info file, any open
2118 handles are not affected.
2119 ****************************************************************************/
2121 uint32 del_a_printer(const char *sharename)
2124 char *printdb_path = NULL;
2125 TALLOC_CTX *ctx = talloc_tos();
2127 kbuf = make_printer_tdbkey(ctx, sharename);
2128 tdb_delete(tdb_printers, kbuf);
2130 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2131 tdb_delete(tdb_printers, kbuf);
2133 close_all_print_db();
2135 if (geteuid() == sec_initial_uid()) {
2136 if (asprintf(&printdb_path, "%s%s.tdb",
2137 cache_path("printing/"),
2141 unlink(printdb_path);
2142 SAFE_FREE(printdb_path);
2148 /****************************************************************************
2149 ****************************************************************************/
2150 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2156 TDB_DATA kbuf, dbuf;
2159 * in addprinter: no servername and the printer is the name
2160 * in setprinter: servername is \\server
2161 * and printer is \\server\\printer
2163 * Samba manages only local printers.
2164 * we currently don't support things like i
2165 * path=\\other_server\printer
2167 * We only store the printername, not \\server\printername
2170 if ( info->servername[0] != '\0' ) {
2171 trim_string(info->printername, info->servername, NULL);
2172 trim_char(info->printername, '\\', '\0');
2173 info->servername[0]='\0';
2177 * JFM: one day I'll forget.
2178 * below that's info->portname because that's the SAMBA sharename
2179 * and I made NT 'thinks' it's the portname
2180 * the info->sharename is the thing you can name when you add a printer
2181 * that's the short-name when you create shared printer for 95/98
2182 * So I've made a limitation in SAMBA: you can only have 1 printer model
2183 * behind a SAMBA share.
2191 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2194 info->default_priority,
2211 info->printprocessor,
2215 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2216 retlen = pack_values( info->data, buf+len, buflen-len );
2223 if (buflen != len) {
2224 buf = (uint8 *)SMB_REALLOC(buf, len);
2226 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2234 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2239 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2242 if (!W_ERROR_IS_OK(ret))
2243 DEBUG(8, ("error updating printer to tdb on disk\n"));
2247 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2248 info->sharename, info->drivername, info->portname, len));
2253 /****************************************************************************
2254 Create and allocate a default devicemode.
2255 ****************************************************************************/
2257 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2258 const char *devicename,
2259 struct spoolss_DeviceMode **devmode)
2261 struct spoolss_DeviceMode *dm;
2264 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2269 dname = talloc_asprintf(dm, "%s", devicename);
2270 if (dname == NULL) {
2273 if (strlen(dname) > MAXDEVICENAME) {
2274 dname[MAXDEVICENAME] = '\0';
2276 dm->devicename = dname;
2278 dm->formname = talloc_strdup(dm, "Letter");
2279 if (dm->formname == NULL) {
2283 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2284 dm->driverversion = 0x0400;
2286 dm->__driverextra_length = 0;
2287 dm->fields = DEVMODE_FORMNAME |
2289 DEVMODE_PRINTQUALITY |
2290 DEVMODE_DEFAULTSOURCE |
2294 DEVMODE_ORIENTATION;
2295 dm->orientation = DMORIENT_PORTRAIT;
2296 dm->papersize = DMPAPER_LETTER;
2297 dm->paperlength = 0;
2301 dm->defaultsource = DMBIN_FORMSOURCE;
2302 dm->printquality = DMRES_HIGH; /* 0x0258 */
2303 dm->color = DMRES_MONOCHROME;
2304 dm->duplex = DMDUP_SIMPLEX;
2305 dm->yresolution = 0;
2306 dm->ttoption = DMTT_SUBDEV;
2307 dm->collate = DMCOLLATE_FALSE;
2317 dm->displayflags = 0;
2318 dm->displayfrequency = 0;
2321 dm->panningwidth = 0;
2322 dm->panningheight = 0;
2324 dm->driverextra_data.data = NULL;
2325 dm->driverextra_data.length = 0;
2331 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2332 struct spoolss_security_descriptor **secdesc)
2334 struct security_ace ace[7]; /* max number of ace entries */
2337 struct security_acl *psa = NULL;
2338 struct security_descriptor *psd = NULL;
2339 struct dom_sid adm_sid;
2342 /* Create an ACE where Everyone is allowed to print */
2344 sa = PRINTER_ACE_PRINT;
2345 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2346 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2348 /* Add the domain admins group if we are a DC */
2351 struct dom_sid domadmins_sid;
2353 sid_compose(&domadmins_sid, get_global_sam_sid(),
2356 sa = PRINTER_ACE_FULL_CONTROL;
2357 init_sec_ace(&ace[i++], &domadmins_sid,
2358 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2359 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2360 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2361 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2363 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2364 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
2366 sa = PRINTER_ACE_FULL_CONTROL;
2367 init_sec_ace(&ace[i++], &adm_sid,
2368 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2369 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2370 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2371 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2374 /* add BUILTIN\Administrators as FULL CONTROL */
2376 sa = PRINTER_ACE_FULL_CONTROL;
2377 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2378 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2379 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2380 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2381 SEC_ACE_TYPE_ACCESS_ALLOWED,
2382 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2384 /* add BUILTIN\Print Operators as FULL CONTROL */
2386 sa = PRINTER_ACE_FULL_CONTROL;
2387 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2388 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2389 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2390 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
2391 SEC_ACE_TYPE_ACCESS_ALLOWED,
2392 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2394 /* Make the security descriptor owned by the BUILTIN\Administrators */
2396 /* The ACL revision number in rpc_secdesc.h differs from the one
2397 created by NT when setting ACE entries in printer
2398 descriptors. NT4 complains about the property being edited by a
2401 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2402 psd = make_sec_desc(mem_ctx,
2404 SEC_DESC_SELF_RELATIVE,
2405 &global_sid_Builtin_Administrators,
2406 &global_sid_Builtin_Administrators,
2413 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2417 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2418 (unsigned int)sd_size));
2425 /****************************************************************************
2426 Allocate and initialize a new slot.
2427 ***************************************************************************/
2429 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2435 if ( !name || !data )
2438 /* allocate another slot in the NT_PRINTER_KEY array */
2440 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2441 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2447 key_index = data->num_keys;
2449 /* initialze new key */
2451 data->keys[key_index].name = talloc_strdup( data, name );
2453 werr = regval_ctr_init(data, &(data->keys[key_index].values));
2454 if (!W_ERROR_IS_OK(werr)) {
2460 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2465 /****************************************************************************
2466 search for a registry key name in the existing printer data
2467 ***************************************************************************/
2469 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2473 for ( i=0; i<data->num_keys; i++ ) {
2474 if ( strequal( data->keys[i].name, name ) ) {
2476 /* cleanup memory */
2478 TALLOC_FREE( data->keys[i].name );
2479 TALLOC_FREE( data->keys[i].values );
2481 /* if not the end of the array, move remaining elements down one slot */
2484 if ( data->num_keys && (i < data->num_keys) )
2485 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2492 return data->num_keys;
2495 /****************************************************************************
2496 search for a registry key name in the existing printer data
2497 ***************************************************************************/
2499 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2504 if ( !data || !name )
2507 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2509 /* loop over all existing keys */
2511 for ( i=0; i<data->num_keys; i++ ) {
2512 if ( strequal(data->keys[i].name, name) ) {
2513 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2523 /****************************************************************************
2524 ***************************************************************************/
2526 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2530 int num_subkeys = 0;
2532 fstring *subkeys_ptr = NULL;
2543 /* special case of asking for the top level printer data registry key names */
2545 if ( strlen(key) == 0 ) {
2546 for ( i=0; i<data->num_keys; i++ ) {
2548 /* found a match, so allocate space and copy the name */
2550 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2551 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2556 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2563 /* asking for the subkeys of some key */
2564 /* subkey paths are stored in the key name using '\' as the delimiter */
2566 for ( i=0; i<data->num_keys; i++ ) {
2567 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2569 /* if we found the exact key, then break */
2570 key_len = strlen( key );
2571 if ( strlen(data->keys[i].name) == key_len )
2574 /* get subkey path */
2576 p = data->keys[i].name + key_len;
2579 fstrcpy( subkeyname, p );
2580 if ( (p = strchr( subkeyname, '\\' )) )
2583 /* don't add a key more than once */
2585 for ( j=0; j<num_subkeys; j++ ) {
2586 if ( strequal( subkeys_ptr[j], subkeyname ) )
2590 if ( j != num_subkeys )
2593 /* found a match, so allocate space and copy the name */
2595 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2596 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2601 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2607 /* return error if the key was not found */
2609 if ( i == data->num_keys ) {
2610 SAFE_FREE(subkeys_ptr);
2615 /* tag off the end */
2618 fstrcpy(subkeys_ptr[num_subkeys], "" );
2620 *subkeys = subkeys_ptr;
2626 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2629 regval_ctr_delvalue(ctr, val_name);
2630 regval_ctr_addvalue_sz(ctr, val_name, sz);
2633 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2636 regval_ctr_delvalue(ctr, val_name);
2637 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2638 (uint8 *) &dword, sizeof(dword));
2641 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2644 uint8 bin_bool = (b ? 1 : 0);
2645 regval_ctr_delvalue(ctr, val_name);
2646 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2647 (uint8 *) &bin_bool, sizeof(bin_bool));
2650 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2651 const char *multi_sz)
2658 regval_ctr_delvalue(ctr, val_name);
2659 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
2662 /****************************************************************************
2663 * Map spoolss_PrinterInfo2 data into DsSpooler keys for publishing.
2665 * @param mem_ctx allocation context
2666 * @param info2 spoolss_PrinterInfo2 describing printer
2667 * @param pdata the talloced printer data
2668 * @return bool indicating success or failure
2669 ***************************************************************************/
2671 static bool map_nt_printer_info2_to_dsspooler(TALLOC_CTX *mem_ctx,
2672 struct spoolss_PrinterInfo2 *info2,
2673 NT_PRINTER_DATA **pdata)
2675 NT_PRINTER_DATA *data;
2676 struct regval_ctr *ctr = NULL;
2678 const char *dnssuffix;
2679 char *allocated_string = NULL;
2680 const char *ascii_str;
2683 data = talloc_zero(mem_ctx, NT_PRINTER_DATA);
2684 if (!data) return false;
2687 i = add_new_printer_key(data, SPOOL_DSSPOOLER_KEY);
2688 ctr = data->keys[i].values;
2690 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2691 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2693 /* we make the assumption that the netbios name is the same
2694 as the DNS name sinc ethe former will be what we used to
2697 dnssuffix = get_mydnsdomname(talloc_tos());
2698 if (dnssuffix && *dnssuffix) {
2699 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2701 fstrcpy( longname, global_myname() );
2704 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2706 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
2710 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2711 SAFE_FREE(allocated_string);
2713 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2714 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2715 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2716 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2717 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2718 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2719 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2720 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2721 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2723 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2724 (info2->attributes &
2725 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2727 switch (info2->attributes & 0x3) {
2729 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2732 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2735 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2738 ascii_str = "unknown";
2740 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2746 /*****************************************************************
2747 ****************************************************************/
2749 static void store_printer_guid(const char *printer, struct GUID guid)
2751 TALLOC_CTX *tmp_ctx;
2752 struct auth_serversupplied_info *server_info = NULL;
2753 const char *guid_str;
2758 tmp_ctx = talloc_new(NULL);
2760 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2764 status = make_server_info_system(tmp_ctx, &server_info);
2765 if (!NT_STATUS_IS_OK(status)) {
2766 DEBUG(0, ("store_printer_guid: "
2767 "Could not create system server_info\n"));
2771 guid_str = GUID_string(tmp_ctx, &guid);
2773 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2777 /* We used to store this as a REG_BINARY but that causes
2780 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
2781 DEBUG(0, ("store_printer_guid: "
2782 "Could not marshall string %s for objectGUID\n",
2787 result = winreg_set_printer_dataex(tmp_ctx, server_info, printer,
2788 SPOOL_DSSPOOLER_KEY, "objectGUID",
2789 REG_SZ, blob.data, blob.length);
2790 if (!W_ERROR_IS_OK(result)) {
2791 DEBUG(0, ("store_printer_guid: "
2792 "Failed to store GUID for printer %s\n", printer));
2796 talloc_free(tmp_ctx);
2799 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2800 struct spoolss_PrinterInfo2 *pinfo2)
2804 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
2805 char *srv_dn_utf8, **srv_cn_utf8;
2808 const char *attrs[] = {"objectGUID", NULL};
2810 WERROR win_rc = WERR_OK;
2811 size_t converted_size;
2812 NT_PRINTER_DATA *pdata;
2813 const char *printer = pinfo2->sharename;
2815 /* build the ads mods */
2816 ctx = talloc_init("nt_printer_publish_ads");
2821 DEBUG(5, ("publishing printer %s\n", printer));
2823 if (!map_nt_printer_info2_to_dsspooler(ctx, pinfo2, &pdata)) {
2825 return WERR_SERVER_UNAVAILABLE;
2828 /* figure out where to publish */
2829 ads_find_machine_acct(ads, &res, global_myname());
2831 /* We use ldap_get_dn here as we need the answer
2832 * in utf8 to call ldap_explode_dn(). JRA. */
2834 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2837 return WERR_SERVER_UNAVAILABLE;
2839 ads_msgfree(ads, res);
2840 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2843 ldap_memfree(srv_dn_utf8);
2844 return WERR_SERVER_UNAVAILABLE;
2846 /* Now convert to CH_UNIX. */
2847 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
2849 ldap_memfree(srv_dn_utf8);
2850 ldap_memfree(srv_cn_utf8);
2851 return WERR_SERVER_UNAVAILABLE;
2853 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
2855 ldap_memfree(srv_dn_utf8);
2856 ldap_memfree(srv_cn_utf8);
2857 TALLOC_FREE(srv_dn);
2858 return WERR_SERVER_UNAVAILABLE;
2861 ldap_memfree(srv_dn_utf8);
2862 ldap_memfree(srv_cn_utf8);
2864 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
2865 if (!srv_cn_escaped) {
2867 return WERR_SERVER_UNAVAILABLE;
2869 sharename_escaped = escape_rdn_val_string_alloc(printer);
2870 if (!sharename_escaped) {
2871 SAFE_FREE(srv_cn_escaped);
2873 return WERR_SERVER_UNAVAILABLE;
2876 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
2878 SAFE_FREE(srv_cn_escaped);
2879 SAFE_FREE(sharename_escaped);
2881 mods = ads_init_mods(ctx);
2889 get_local_printer_publishing_data(ctx, &mods, pdata);
2890 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);
2893 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2894 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
2896 for (i=0; mods[i] != 0; i++)
2898 mods[i] = (LDAPMod *)-1;
2899 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2902 if (!ADS_ERR_OK(ads_rc)) {
2903 DEBUG(3, ("error publishing %s: %s\n",
2904 printer, ads_errstr(ads_rc)));
2907 /* retreive the guid and store it locally */
2908 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2910 ads_pull_guid(ads, res, &guid);
2911 ads_msgfree(ads, res);
2912 store_printer_guid(printer, guid);
2919 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2920 const char *printer)
2923 LDAPMessage *res = NULL;
2924 char *prt_dn = NULL;
2926 DEBUG(5, ("unpublishing printer %s\n", printer));
2928 /* remove the printer from the directory */
2929 ads_rc = ads_find_printer_on_server(ads, &res,
2930 printer, global_myname());
2932 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
2933 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2935 ads_msgfree(ads, res);
2938 ads_rc = ads_del_dn(ads, prt_dn);
2939 TALLOC_FREE(prt_dn);
2943 ads_msgfree(ads, res);
2948 /****************************************************************************
2949 * Publish a printer in the directory
2951 * @param mem_ctx memory context
2952 * @param server_info server_info to access winreg pipe
2953 * @param pinfo2 printer information
2954 * @param action publish/unpublish action
2955 * @return WERROR indicating status of publishing
2956 ***************************************************************************/
2958 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
2959 struct auth_serversupplied_info *server_info,
2960 struct spoolss_PrinterInfo2 *pinfo2,
2963 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
2964 struct spoolss_SetPrinterInfo2 *sinfo2;
2966 ADS_STRUCT *ads = NULL;
2969 sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
2975 case DSPRINT_PUBLISH:
2976 case DSPRINT_UPDATE:
2977 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2979 case DSPRINT_UNPUBLISH:
2980 pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2983 win_rc = WERR_NOT_SUPPORTED;
2987 sinfo2->attributes = pinfo2->attributes;
2989 win_rc = winreg_update_printer(mem_ctx, server_info,
2990 pinfo2->sharename, info2_mask,
2991 sinfo2, NULL, NULL);
2992 if (!W_ERROR_IS_OK(win_rc)) {
2993 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2997 TALLOC_FREE(sinfo2);
2999 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3001 DEBUG(3, ("ads_init() failed\n"));
3002 win_rc = WERR_SERVER_UNAVAILABLE;
3005 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3006 SAFE_FREE(ads->auth.password);
3007 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3010 /* ads_connect() will find the DC for us */
3011 ads_rc = ads_connect(ads);
3012 if (!ADS_ERR_OK(ads_rc)) {
3013 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3014 win_rc = WERR_ACCESS_DENIED;
3019 case DSPRINT_PUBLISH:
3020 case DSPRINT_UPDATE:
3021 win_rc = nt_printer_publish_ads(ads, pinfo2);
3023 case DSPRINT_UNPUBLISH:
3024 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
3033 WERROR check_published_printers(void)
3036 ADS_STRUCT *ads = NULL;
3038 int n_services = lp_numservices();
3039 TALLOC_CTX *tmp_ctx = NULL;
3040 struct auth_serversupplied_info *server_info = NULL;
3041 struct spoolss_PrinterInfo2 *pinfo2;
3045 tmp_ctx = talloc_new(NULL);
3046 if (!tmp_ctx) return WERR_NOMEM;
3048 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3050 DEBUG(3, ("ads_init() failed\n"));
3051 return WERR_SERVER_UNAVAILABLE;
3053 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3054 SAFE_FREE(ads->auth.password);
3055 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3058 /* ads_connect() will find the DC for us */
3059 ads_rc = ads_connect(ads);
3060 if (!ADS_ERR_OK(ads_rc)) {
3061 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3062 result = WERR_ACCESS_DENIED;
3066 status = make_server_info_system(tmp_ctx, &server_info);
3067 if (!NT_STATUS_IS_OK(status)) {
3068 DEBUG(0, ("check_published_printers: "
3069 "Could not create system server_info\n"));
3070 result = WERR_ACCESS_DENIED;
3074 for (snum = 0; snum < n_services; snum++) {
3075 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
3079 result = winreg_get_printer(tmp_ctx, server_info, NULL,
3080 lp_servicename(snum), &pinfo2);
3081 if (!W_ERROR_IS_OK(result)) {
3085 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
3086 nt_printer_publish_ads(ads, pinfo2);
3089 TALLOC_FREE(pinfo2);
3095 ads_kdestroy("MEMORY:prtpub_cache");
3096 talloc_free(tmp_ctx);
3100 bool is_printer_published(TALLOC_CTX *mem_ctx,
3101 struct auth_serversupplied_info *server_info,
3102 char *servername, char *printer, struct GUID *guid,
3103 struct spoolss_PrinterInfo2 **info2)
3105 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3106 enum winreg_Type type;
3112 result = winreg_get_printer(mem_ctx, server_info,
3113 servername, printer, &pinfo2);
3114 if (!W_ERROR_IS_OK(result)) {
3118 if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
3119 TALLOC_FREE(pinfo2);
3127 /* fetching printer guids really ought to be a separate function. */
3129 result = winreg_get_printer_dataex(mem_ctx, server_info, printer,
3130 SPOOL_DSSPOOLER_KEY, "objectGUID",
3131 &type, &data, &data_size);
3132 if (!W_ERROR_IS_OK(result)) {
3133 TALLOC_FREE(pinfo2);
3137 /* We used to store the guid as REG_BINARY, then swapped
3138 to REG_SZ for Vista compatibility so check for both */
3142 status = GUID_from_string((char *)data, guid);
3143 if (!NT_STATUS_IS_OK(status)) {
3144 TALLOC_FREE(pinfo2);
3150 if (data_size != sizeof(struct GUID)) {
3151 TALLOC_FREE(pinfo2);
3154 memcpy(guid, data, sizeof(struct GUID));
3157 DEBUG(0,("is_printer_published: GUID value stored as "
3158 "invaluid type (%d)\n", type));
3164 *info2 = talloc_move(mem_ctx, &pinfo2);
3166 talloc_free(pinfo2);
3170 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
3171 struct auth_serversupplied_info *server_info,
3172 struct spoolss_PrinterInfo2 *pinfo2,
3178 WERROR check_published_printers(void)
3183 bool is_printer_published(TALLOC_CTX *mem_ctx,
3184 struct auth_serversupplied_info *server_info,
3185 char *servername, char *printer, struct GUID *guid,
3186 struct spoolss_PrinterInfo2 **info2)
3190 #endif /* HAVE_ADS */
3192 /****************************************************************************
3193 ***************************************************************************/
3195 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3197 NT_PRINTER_DATA *data;
3199 int removed_keys = 0;
3203 empty_slot = data->num_keys;
3206 return WERR_INVALID_PARAM;
3208 /* remove all keys */
3210 if ( !strlen(key) ) {
3212 TALLOC_FREE( data );
3216 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3222 /* remove a specific key (and all subkeys) */
3224 for ( i=0; i<data->num_keys; i++ ) {
3225 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3226 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3227 data->keys[i].name));
3229 TALLOC_FREE( data->keys[i].name );
3230 TALLOC_FREE( data->keys[i].values );
3232 /* mark the slot as empty */
3234 ZERO_STRUCTP( &data->keys[i] );
3238 /* find the first empty slot */
3240 for ( i=0; i<data->num_keys; i++ ) {
3241 if ( !data->keys[i].name ) {
3248 if ( i == data->num_keys )
3249 /* nothing was removed */
3250 return WERR_INVALID_PARAM;
3252 /* move everything down */
3254 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3255 if ( data->keys[i].name ) {
3256 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3257 ZERO_STRUCTP( &data->keys[i] );
3265 data->num_keys -= removed_keys;
3267 /* sanity check to see if anything is left */
3269 if ( !data->num_keys ) {
3270 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3272 SAFE_FREE( data->keys );
3273 ZERO_STRUCTP( data );
3279 /****************************************************************************
3280 ***************************************************************************/
3282 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3284 WERROR result = WERR_OK;
3287 /* we must have names on non-zero length */
3289 if ( !key || !*key|| !value || !*value )
3290 return WERR_INVALID_NAME;
3292 /* find the printer key first */
3294 key_index = lookup_printerkey( p2->data, key );
3295 if ( key_index == -1 )
3298 /* make sure the value exists so we can return the correct error code */
3300 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3301 return WERR_BADFILE;
3303 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3305 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3311 /****************************************************************************
3312 ***************************************************************************/
3314 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3315 uint32 type, uint8 *data, int real_len )
3317 WERROR result = WERR_OK;
3320 /* we must have names on non-zero length */
3322 if ( !key || !*key|| !value || !*value )
3323 return WERR_INVALID_NAME;
3325 /* find the printer key first */
3327 key_index = lookup_printerkey( p2->data, key );
3328 if ( key_index == -1 )
3329 key_index = add_new_printer_key( p2->data, key );
3331 if ( key_index == -1 )
3334 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3335 type, data, real_len );
3337 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3338 key, value, type, real_len ));
3343 /****************************************************************************
3344 ***************************************************************************/
3346 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3350 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3353 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3356 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3359 /****************************************************************************
3360 Unpack a list of registry values frem the TDB
3361 ***************************************************************************/
3363 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3368 const char *valuename = NULL;
3369 const char *keyname = NULL;
3373 struct regval_blob *regval_p;
3376 /* add the "PrinterDriverData" key first for performance reasons */
3378 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3380 /* loop and unpack the rest of the registry values */
3384 /* check to see if there are any more registry values */
3387 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3391 /* unpack the next regval */
3393 len += tdb_unpack(buf+len, buflen-len, "fdB",
3399 /* lookup for subkey names which have a type of REG_NONE */
3400 /* there's no data with this entry */
3402 if ( type == REG_NONE ) {
3403 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3404 add_new_printer_key( printer_data, string );
3409 * break of the keyname from the value name.
3410 * Valuenames can have embedded '\'s so be careful.
3411 * only support one level of keys. See the
3412 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3416 str = strchr_m( string, '\\');
3418 /* Put in "PrinterDriverData" is no key specified */
3421 keyname = SPOOL_PRINTERDATA_KEY;
3430 /* see if we need a new key */
3432 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3433 key_index = add_new_printer_key( printer_data, keyname );
3435 if ( key_index == -1 ) {
3436 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3441 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3443 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3444 Thanks to Martin Zielinski for the hint. */
3446 if ( type == REG_BINARY &&
3447 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3448 strequal( valuename, "objectGUID" ) )
3452 /* convert the GUID to a UNICODE string */
3454 memcpy( &guid, data_p, sizeof(struct GUID) );
3456 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3458 GUID_string(talloc_tos(), &guid));
3463 regval_ctr_addvalue( printer_data->keys[key_index].values,
3464 valuename, type, data_p,
3468 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3475 /****************************************************************************
3476 ***************************************************************************/
3478 static char *win_driver;
3479 static char *os2_driver;
3481 static const char *get_win_driver(void)
3483 if (win_driver == NULL) {
3489 static const char *get_os2_driver(void)
3491 if (os2_driver == NULL) {
3497 static bool set_driver_mapping(const char *from, const char *to)
3499 SAFE_FREE(win_driver);
3500 SAFE_FREE(os2_driver);
3502 win_driver = SMB_STRDUP(from);
3503 os2_driver = SMB_STRDUP(to);
3505 if (win_driver == NULL || os2_driver == NULL) {
3506 SAFE_FREE(win_driver);
3507 SAFE_FREE(os2_driver);
3513 static void map_to_os2_driver(fstring drivername)
3515 char *mapfile = lp_os2_driver_map();
3516 char **lines = NULL;
3520 if (!strlen(drivername))
3526 if (strequal(drivername, get_win_driver())) {
3527 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3528 drivername, get_os2_driver()));
3529 fstrcpy(drivername, get_os2_driver());
3533 lines = file_lines_load(mapfile, &numlines,0,NULL);
3534 if (numlines == 0 || lines == NULL) {
3535 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3540 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3542 for( i = 0; i < numlines; i++) {
3543 char *nt_name = lines[i];
3544 char *os2_name = strchr(nt_name,'=');
3551 while (isspace(*nt_name))
3554 if (!*nt_name || strchr("#;",*nt_name))
3558 int l = strlen(nt_name);
3559 while (l && isspace(nt_name[l-1])) {
3565 while (isspace(*os2_name))
3569 int l = strlen(os2_name);
3570 while (l && isspace(os2_name[l-1])) {
3576 if (strequal(nt_name,drivername)) {
3577 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3578 set_driver_mapping(drivername,os2_name);
3579 fstrcpy(drivername,os2_name);
3591 * @brief Map a Windows driver to a OS/2 driver.
3593 * @param[in] mem_ctx The memory context to use.
3595 * @param[in,out] pdrivername The drivername of Windows to remap.
3597 * @return WERR_OK on success, a corresponding WERROR on failure.
3599 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3601 const char *mapfile = lp_os2_driver_map();
3602 char **lines = NULL;
3603 const char *drivername;
3607 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3608 return WERR_INVALID_PARAMETER;
3611 drivername = *pdrivername;
3613 if (mapfile[0] == '\0') {
3614 return WERR_BADFILE;
3617 if (strequal(drivername, get_win_driver())) {
3618 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3619 drivername, get_os2_driver()));
3620 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3621 if (drivername == NULL) {
3624 *pdrivername = drivername;
3628 lines = file_lines_load(mapfile, &numlines, 0, NULL);
3629 if (numlines == 0 || lines == NULL) {
3630 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile));
3635 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3637 for( i = 0; i < numlines; i++) {
3638 char *nt_name = lines[i];
3639 char *os2_name = strchr(nt_name, '=');
3641 if (os2_name == NULL) {
3647 while (isspace(*nt_name)) {
3651 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3656 int l = strlen(nt_name);
3657 while (l && isspace(nt_name[l - 1])) {
3663 while (isspace(*os2_name)) {
3668 int l = strlen(os2_name);
3669 while (l && isspace(os2_name[l-1])) {
3675 if (strequal(nt_name, drivername)) {
3676 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3677 set_driver_mapping(drivername, os2_name);
3678 drivername = talloc_strdup(mem_ctx, os2_name);
3680 if (drivername == NULL) {
3683 *pdrivername = drivername;
3692 /****************************************************************************
3693 Get a default printer info 2 struct.
3694 ****************************************************************************/
3696 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3697 const char *servername,
3698 const char* sharename,
3701 int snum = lp_servicenumber(sharename);
3704 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3705 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3706 servername, sharename);
3707 fstrcpy(info->sharename, sharename);
3708 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3710 /* by setting the driver name to an empty string, a local NT admin
3711 can now run the **local** APW to install a local printer driver
3712 for a Samba shared printer in 2.2. Without this, drivers **must** be
3713 installed on the Samba server for NT clients --jerry */
3714 #if 0 /* JERRY --do not uncomment-- */
3715 if (!*info->drivername)
3716 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3720 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3722 strlcpy(info->comment, "", sizeof(info->comment));
3723 fstrcpy(info->printprocessor, "winprint");
3724 fstrcpy(info->datatype, "RAW");
3727 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3728 /* Pull the location and comment strings from cups if we don't
3730 if ( !strlen(info->location) || !strlen(info->comment) ) {
3731 char *comment = NULL;
3732 char *location = NULL;
3733 if (cups_pull_comment_location(info, info->sharename,
3734 &comment, &location)) {
3735 strlcpy(info->comment, comment, sizeof(info->comment));
3736 fstrcpy(info->location, location);
3737 TALLOC_FREE(comment);
3738 TALLOC_FREE(location);
3744 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3746 info->starttime = 0; /* Minutes since 12:00am GMT */
3747 info->untiltime = 0; /* Minutes since 12:00am GMT */
3749 info->default_priority = 1;
3750 info->setuptime = (uint32)time(NULL);
3753 * I changed this as I think it is better to have a generic
3754 * DEVMODE than to crash Win2k explorer.exe --jerry
3755 * See the HP Deskjet 990c Win2k drivers for an example.
3757 * However the default devmode appears to cause problems
3758 * with the HP CLJ 8500 PCL driver. Hence the addition of
3759 * the "default devmode" parameter --jerry 22/01/2002
3762 if (lp_default_devmode(snum)) {
3763 result = spoolss_create_default_devmode(info,
3766 if (!W_ERROR_IS_OK(result)) {
3770 info->devmode = NULL;
3773 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3777 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
3782 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
3787 TALLOC_FREE(info->devmode);
3789 return WERR_ACCESS_DENIED;
3792 /****************************************************************************
3793 ****************************************************************************/
3795 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
3796 const char *servername,
3797 const char *sharename,
3801 int snum = lp_servicenumber(sharename);
3802 TDB_DATA kbuf, dbuf;
3803 fstring printername;
3804 char *comment = NULL;
3807 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
3809 dbuf = tdb_fetch(tdb_printers, kbuf);
3811 return get_a_printer_2_default(info, servername,
3812 sharename, get_loc_com);
3815 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3818 &info->default_priority,
3825 &info->c_setprinter,
3835 info->printprocessor,
3840 strlcpy(info->comment, comment, sizeof(info->comment));
3844 /* Samba has to have shared raw drivers. */
3845 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3846 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3848 /* Restore the stripped strings. */
3849 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3851 if ( lp_force_printername(snum) ) {
3852 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3854 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3857 fstrcpy(info->printername, printername);
3860 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3861 /* Pull the location and comment strings from cups if we don't
3863 if ( !strlen(info->location) || !strlen(info->comment) ) {
3864 char *location = NULL;
3866 if (cups_pull_comment_location(info, info->sharename,
3867 &comment, &location)) {
3868 strlcpy(info->comment, comment, sizeof(info->comment));
3869 fstrcpy(info->location, location);
3870 TALLOC_FREE(comment);
3871 TALLOC_FREE(location);
3877 len += unpack_devicemode(info, dbuf.dptr+len,
3882 * Some client drivers freak out if there is a NULL devmode
3883 * (probably the driver is not checking before accessing
3884 * the devmode pointer) --jerry
3886 * See comments in get_a_printer_2_default()
3889 if (lp_default_devmode(snum) && !info->devmode) {
3890 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3892 result = spoolss_create_default_devmode(info, printername,
3894 if (!W_ERROR_IS_OK(result)) {
3899 if (info->devmode) {
3900 info->devmode->devicename = talloc_strdup(info->devmode,
3902 if (!info->devmode->devicename) {
3903 result = WERR_NOMEM;
3908 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3909 DEBUG(0,("unpack_values: talloc() failed!\n"));
3910 result = WERR_NOMEM;
3913 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3915 /* This will get the current RPC talloc context, but we should be
3916 passing this as a parameter... fixme... JRA ! */
3918 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3919 result = WERR_NOMEM;
3923 /* Fix for OS/2 drivers. */
3925 if (get_remote_arch() == RA_OS2) {
3926 map_to_os2_driver(info->drivername);
3929 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3930 sharename, info->printername, info->drivername));
3935 SAFE_FREE(dbuf.dptr);
3939 /****************************************************************************
3940 Debugging function, dump at level 6 the struct in the logs.
3941 ****************************************************************************/
3942 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3945 NT_PRINTER_INFO_LEVEL_2 *info2;
3947 DEBUG(106,("Dumping printer at level [%d]\n", level));
3952 if (printer->info_2 == NULL)
3956 info2=printer->info_2;
3958 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3959 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3960 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3961 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3962 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3963 DEBUGADD(106,("status:[%d]\n", info2->status));
3964 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3965 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3966 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3967 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3968 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3970 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3971 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3972 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3973 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3974 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3975 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3976 DEBUGADD(106,("location:[%s]\n", info2->location));
3977 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3978 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3979 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3980 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3986 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3994 /****************************************************************************
3995 Update the changeid time.
3996 This is SO NASTY as some drivers need this to change, others need it
3997 static. This value will change every second, and I must hope that this
3998 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4000 ****************************************************************************/
4002 static uint32 rev_changeid(void)
4006 get_process_uptime(&tv);
4009 /* Return changeid as msec since spooler restart */
4010 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4013 * This setting seems to work well but is too untested
4014 * to replace the above calculation. Left in for experiementation
4015 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4017 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4023 * The function below are the high level ones.
4024 * only those ones must be called from the spoolss code.
4028 /****************************************************************************
4029 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4030 ****************************************************************************/
4032 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4036 dump_a_printer(printer, level);
4042 * Update the changestamp. Emperical tests show that the
4043 * ChangeID is always updated,but c_setprinter is
4044 * global spooler variable (not per printer).
4047 /* ChangeID **must** be increasing over the lifetime
4048 of client's spoolss service in order for the
4049 client's cache to show updates */
4051 printer->info_2->changeid = rev_changeid();
4054 * Because one day someone will ask:
4055 * NT->NT An admin connection to a remote
4056 * printer show changes imeediately in
4057 * the properities dialog
4059 * A non-admin connection will only show the
4060 * changes after viewing the properites page
4061 * 2 times. Seems to be related to a
4062 * race condition in the client between the spooler
4063 * updating the local cache and the Explorer.exe GUI
4064 * actually displaying the properties.
4066 * This is fixed in Win2k. admin/non-admin
4067 * connections both display changes immediately.
4072 result=update_a_printer_2(printer->info_2);
4076 result=WERR_UNKNOWN_LEVEL;
4083 /****************************************************************************
4084 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4086 Previously the code had a memory allocation problem because it always
4087 used the TALLOC_CTX from the Printer_entry*. This context lasts
4088 as a long as the original handle is open. So if the client made a lot
4089 of getprinter[data]() calls, the memory usage would climb. Now we use
4090 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4091 still use the Printer_entry->ctx for maintaining the cache copy though
4092 since that object must live as long as the handle by definition.
4095 ****************************************************************************/
4097 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4098 const char *sharename, bool get_loc_com)
4103 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4105 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4106 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4112 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4113 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4114 TALLOC_FREE( *pp_printer );
4119 fstrcpy( servername, print_hnd->servername );
4121 fstrcpy( servername, "%L" );
4122 standard_sub_basic( "", "", servername,
4123 sizeof(servername)-1 );
4126 result = get_a_printer_2( (*pp_printer)->info_2,
4127 servername, sharename, get_loc_com);
4129 /* we have a new printer now. Save it with this handle */
4131 if ( !W_ERROR_IS_OK(result) ) {
4132 TALLOC_FREE( *pp_printer );
4133 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4134 sharename, (unsigned int)level, win_errstr(result)));
4138 dump_a_printer( *pp_printer, level);
4143 TALLOC_FREE( *pp_printer );
4144 return WERR_UNKNOWN_LEVEL;
4150 WERROR get_a_printer( Printer_entry *print_hnd,
4151 NT_PRINTER_INFO_LEVEL **pp_printer,
4153 const char *sharename)
4155 return get_a_printer_internal(print_hnd, pp_printer, level,
4159 WERROR get_a_printer_search( Printer_entry *print_hnd,
4160 NT_PRINTER_INFO_LEVEL **pp_printer,
4162 const char *sharename)
4164 return get_a_printer_internal(print_hnd, pp_printer, level,
4168 /****************************************************************************
4169 Deletes a NT_PRINTER_INFO_LEVEL struct.
4170 ****************************************************************************/
4172 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4174 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4181 TALLOC_FREE(printer->info_2);
4185 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4189 TALLOC_FREE(*pp_printer);
4194 /****************************************************************************
4195 ****************************************************************************/
4197 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4198 struct spoolss_DriverInfo8 *_info8)
4200 struct spoolss_DriverInfo8 info8;
4206 info8.version = r->info.info3->version;
4207 info8.driver_name = r->info.info3->driver_name;
4208 info8.architecture = r->info.info3->architecture;
4209 info8.driver_path = r->info.info3->driver_path;
4210 info8.data_file = r->info.info3->data_file;
4211 info8.config_file = r->info.info3->config_file;
4212 info8.help_file = r->info.info3->help_file;
4213 info8.monitor_name = r->info.info3->monitor_name;
4214 info8.default_datatype = r->info.info3->default_datatype;
4215 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4216 info8.dependent_files = r->info.info3->dependent_files->string;
4220 info8.version = r->info.info6->version;
4221 info8.driver_name = r->info.info6->driver_name;
4222 info8.architecture = r->info.info6->architecture;
4223 info8.driver_path = r->info.info6->driver_path;
4224 info8.data_file = r->info.info6->data_file;
4225 info8.config_file = r->info.info6->config_file;
4226 info8.help_file = r->info.info6->help_file;
4227 info8.monitor_name = r->info.info6->monitor_name;
4228 info8.default_datatype = r->info.info6->default_datatype;
4229 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4230 info8.dependent_files = r->info.info6->dependent_files->string;
4232 info8.driver_date = r->info.info6->driver_date;
4233 info8.driver_version = r->info.info6->driver_version;
4234 info8.manufacturer_name = r->info.info6->manufacturer_name;
4235 info8.manufacturer_url = r->info.info6->manufacturer_url;
4236 info8.hardware_id = r->info.info6->hardware_id;
4237 info8.provider = r->info.info6->provider;
4240 info8.version = r->info.info8->version;
4241 info8.driver_name = r->info.info8->driver_name;
4242 info8.architecture = r->info.info8->architecture;
4243 info8.driver_path = r->info.info8->driver_path;
4244 info8.data_file = r->info.info8->data_file;
4245 info8.config_file = r->info.info8->config_file;
4246 info8.help_file = r->info.info8->help_file;
4247 info8.monitor_name = r->info.info8->monitor_name;
4248 info8.default_datatype = r->info.info8->default_datatype;
4249 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4250 info8.dependent_files = r->info.info8->dependent_files->string;
4252 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4253 info8.previous_names = r->info.info8->previous_names->string;
4255 info8.driver_date = r->info.info8->driver_date;
4256 info8.driver_version = r->info.info8->driver_version;
4257 info8.manufacturer_name = r->info.info8->manufacturer_name;
4258 info8.manufacturer_url = r->info.info8->manufacturer_url;
4259 info8.hardware_id = r->info.info8->hardware_id;
4260 info8.provider = r->info.info8->provider;
4261 info8.print_processor = r->info.info8->print_processor;
4262 info8.vendor_setup = r->info.info8->vendor_setup;
4263 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4264 info8.color_profiles = r->info.info8->color_profiles->string;
4266 info8.inf_path = r->info.info8->inf_path;
4267 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4268 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4269 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4271 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4272 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4284 /****************************************************************************
4285 Determine whether or not a particular driver is currently assigned
4287 ****************************************************************************/
4289 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
4290 struct auth_serversupplied_info *server_info,
4291 const struct spoolss_DriverInfo8 *r)
4294 int n_services = lp_numservices();
4295 bool in_use = False;
4296 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4303 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4305 /* loop through the printers.tdb and check for the drivername */
4307 for (snum=0; snum<n_services && !in_use; snum++) {
4308 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
4312 result = winreg_get_printer(mem_ctx, server_info, NULL,
4313 lp_servicename(snum), &pinfo2);
4314 if (!W_ERROR_IS_OK(result)) {
4315 continue; /* skip */
4318 if (strequal(r->driver_name, pinfo2->drivername)) {
4322 TALLOC_FREE(pinfo2);
4325 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4328 struct spoolss_DriverInfo8 *driver;
4331 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4333 /* we can still remove the driver if there is one of
4334 "Windows NT x86" version 2 or 3 left */
4336 if (!strequal("Windows NT x86", r->architecture)) {
4337 werr = winreg_get_driver(mem_ctx, server_info,
4342 } else if (r->version == 2) {
4343 werr = winreg_get_driver(mem_ctx, server_info,
4347 } else if (r->version == 3) {
4348 werr = winreg_get_driver(mem_ctx, server_info,
4353 DEBUG(0, ("printer_driver_in_use: ERROR!"
4354 " unknown driver version (%d)\n",
4356 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4359 /* now check the error code */
4361 if ( W_ERROR_IS_OK(werr) ) {
4362 /* it's ok to remove the driver, we have other architctures left */
4364 talloc_free(driver);
4368 /* report that the driver is not in use by default */
4374 /**********************************************************************
4375 Check to see if a ogiven file is in use by *info
4376 *********************************************************************/
4378 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4385 /* mz: skip files that are in the list but already deleted */
4386 if (!file || !file[0]) {
4390 if (strequal(file, info->driver_path))
4393 if (strequal(file, info->data_file))
4396 if (strequal(file, info->config_file))
4399 if (strequal(file, info->help_file))
4402 /* see of there are any dependent files to examine */
4404 if (!info->dependent_files)
4407 while (info->dependent_files[i] && *info->dependent_files[i]) {
4408 if (strequal(file, info->dependent_files[i]))
4417 /**********************************************************************
4418 Utility function to remove the dependent file pointed to by the
4419 input parameter from the list
4420 *********************************************************************/
4422 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4425 /* bump everything down a slot */
4427 while (files && files[idx+1]) {
4428 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4437 /**********************************************************************
4438 Check if any of the files used by src are also used by drv
4439 *********************************************************************/
4441 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4442 struct spoolss_DriverInfo8 *src,
4443 const struct spoolss_DriverInfo8 *drv)
4445 bool in_use = False;
4451 /* check each file. Remove it from the src structure if it overlaps */
4453 if (drv_file_in_use(src->driver_path, drv)) {
4455 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4456 src->driver_path = talloc_strdup(mem_ctx, "");
4457 if (!src->driver_path) { return false; }
4460 if (drv_file_in_use(src->data_file, drv)) {
4462 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4463 src->data_file = talloc_strdup(mem_ctx, "");
4464 if (!src->data_file) { return false; }
4467 if (drv_file_in_use(src->config_file, drv)) {
4469 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4470 src->config_file = talloc_strdup(mem_ctx, "");
4471 if (!src->config_file) { return false; }
4474 if (drv_file_in_use(src->help_file, drv)) {
4476 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4477 src->help_file = talloc_strdup(mem_ctx, "");
4478 if (!src->help_file) { return false; }
4481 /* are there any dependentfiles to examine? */
4483 if (!src->dependent_files)
4486 while (src->dependent_files[i] && *src->dependent_files[i]) {
4487 if (drv_file_in_use(src->dependent_files[i], drv)) {
4489 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4490 trim_dependent_file(mem_ctx, src->dependent_files, i);
4498 /****************************************************************************
4499 Determine whether or not a particular driver files are currently being
4500 used by any other driver.
4502 Return value is True if any files were in use by other drivers
4503 and False otherwise.
4505 Upon return, *info has been modified to only contain the driver files
4506 which are not in use
4510 This needs to check all drivers to ensure that all files in use
4511 have been removed from *info, not just the ones in the first
4513 ****************************************************************************/
4515 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4516 struct auth_serversupplied_info *server_info,
4517 struct spoolss_DriverInfo8 *info)
4521 struct spoolss_DriverInfo8 *driver;
4522 bool in_use = false;
4523 uint32_t num_drivers;
4524 const char **drivers;
4530 version = info->version;
4532 /* loop over all driver versions */
4534 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
4536 /* get the list of drivers */
4538 result = winreg_get_driver_list(mem_ctx, server_info,
4539 info->architecture, version,
4540 &num_drivers, &drivers);
4541 if (!W_ERROR_IS_OK(result)) {
4545 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
4546 num_drivers, info->architecture, version));
4548 /* check each driver for overlap in files */
4550 for (i = 0; i < num_drivers; i++) {
4551 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
4555 result = winreg_get_driver(mem_ctx, server_info,
4556 info->architecture, drivers[i],
4558 if (!W_ERROR_IS_OK(result)) {
4559 talloc_free(drivers);
4563 /* check if d2 uses any files from d1 */
4564 /* only if this is a different driver than the one being deleted */
4566 if (!strequal(info->driver_name, driver->driver_name)) {
4567 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4568 /* mz: Do not instantly return -
4569 * we need to ensure this file isn't
4570 * also in use by other drivers. */
4575 talloc_free(driver);
4578 talloc_free(drivers);
4580 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
4585 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4588 struct smb_filename *smb_fname = NULL;
4591 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4593 if (!NT_STATUS_IS_OK(status)) {
4597 status = unlink_internals(conn, NULL, 0, smb_fname, false);
4599 TALLOC_FREE(smb_fname);
4603 /****************************************************************************
4604 Actually delete the driver files. Make sure that
4605 printer_driver_files_in_use() return False before calling
4607 ****************************************************************************/
4609 bool delete_driver_files(struct auth_serversupplied_info *server_info,
4610 const struct spoolss_DriverInfo8 *r)
4615 connection_struct *conn;
4618 fstring printdollar;
4619 int printdollar_snum;
4626 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4627 r->driver_name, r->version));
4629 fstrcpy(printdollar, "print$");
4631 printdollar_snum = find_service(printdollar);
4632 if (printdollar_snum == -1) {
4636 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4637 lp_pathname(printdollar_snum),
4638 server_info, &oldcwd);
4639 if (!NT_STATUS_IS_OK(nt_status)) {
4640 DEBUG(0,("delete_driver_files: create_conn_struct "
4641 "returned %s\n", nt_errstr(nt_status)));
4645 if ( !CAN_WRITE(conn) ) {
4646 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4650 /* now delete the files; must strip the '\print$' string from
4653 if (r->driver_path && r->driver_path[0]) {
4654 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4656 DEBUG(10,("deleting driverfile [%s]\n", s));
4657 driver_unlink_internals(conn, file);
4661 if (r->config_file && r->config_file[0]) {
4662 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4664 DEBUG(10,("deleting configfile [%s]\n", s));
4665 driver_unlink_internals(conn, file);
4669 if (r->data_file && r->data_file[0]) {
4670 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4672 DEBUG(10,("deleting datafile [%s]\n", s));
4673 driver_unlink_internals(conn, file);
4677 if (r->help_file && r->help_file[0]) {
4678 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4680 DEBUG(10,("deleting helpfile [%s]\n", s));
4681 driver_unlink_internals(conn, file);
4685 /* check if we are done removing files */
4687 if (r->dependent_files) {
4688 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4691 /* bypass the "\print$" portion of the path */
4693 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4695 DEBUG(10,("deleting dependent file [%s]\n", file));
4696 driver_unlink_internals(conn, file);
4708 vfs_ChDir(conn, oldcwd);
4714 /****************************************************************************
4715 Store a security desc for a printer.
4716 ****************************************************************************/
4718 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
4720 struct sec_desc_buf *new_secdesc_ctr = NULL;
4721 struct sec_desc_buf *old_secdesc_ctr = NULL;
4722 TALLOC_CTX *mem_ctx = NULL;
4729 mem_ctx = talloc_init("nt_printing_setsec");
4730 if (mem_ctx == NULL)
4733 /* The old owner and group sids of the security descriptor are not
4734 present when new ACEs are added or removed by changing printer
4735 permissions through NT. If they are NULL in the new security
4736 descriptor then copy them over from the old one. */
4738 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
4739 struct dom_sid *owner_sid, *group_sid;
4740 struct security_acl *dacl, *sacl;
4741 struct security_descriptor *psd = NULL;
4744 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
4745 status = WERR_NOMEM;
4749 /* Pick out correct owner and group sids */
4751 owner_sid = secdesc_ctr->sd->owner_sid ?
4752 secdesc_ctr->sd->owner_sid :
4753 old_secdesc_ctr->sd->owner_sid;
4755 group_sid = secdesc_ctr->sd->group_sid ?
4756 secdesc_ctr->sd->group_sid :
4757 old_secdesc_ctr->sd->group_sid;
4759 dacl = secdesc_ctr->sd->dacl ?
4760 secdesc_ctr->sd->dacl :
4761 old_secdesc_ctr->sd->dacl;
4763 sacl = secdesc_ctr->sd->sacl ?
4764 secdesc_ctr->sd->sacl :
4765 old_secdesc_ctr->sd->sacl;
4767 /* Make a deep copy of the security descriptor */
4769 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
4770 owner_sid, group_sid,
4776 status = WERR_NOMEM;
4780 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4783 if (!new_secdesc_ctr) {
4784 new_secdesc_ctr = secdesc_ctr;
4787 /* Store the security descriptor in a tdb */
4789 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
4790 &blob.data, &blob.length);
4791 if (!NT_STATUS_IS_OK(nt_status)) {
4792 status = ntstatus_to_werror(nt_status);
4796 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
4798 dbuf.dptr = (unsigned char *)blob.data;
4799 dbuf.dsize = blob.length;
4801 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
4804 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4805 status = WERR_BADFUNC;
4808 /* Free malloc'ed memory */
4809 talloc_free(blob.data);
4814 talloc_destroy(mem_ctx);
4818 /****************************************************************************
4819 Construct a default security descriptor buffer for a printer.
4820 ****************************************************************************/
4822 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
4824 struct security_ace ace[7]; /* max number of ace entries */
4827 struct security_acl *psa = NULL;
4828 struct sec_desc_buf *sdb = NULL;
4829 struct security_descriptor *psd = NULL;
4830 struct dom_sid adm_sid;
4833 /* Create an ACE where Everyone is allowed to print */
4835 sa = PRINTER_ACE_PRINT;
4836 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4837 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4839 /* Add the domain admins group if we are a DC */
4842 struct dom_sid domadmins_sid;
4844 sid_compose(&domadmins_sid, get_global_sam_sid(),
4847 sa = PRINTER_ACE_FULL_CONTROL;
4848 init_sec_ace(&ace[i++], &domadmins_sid,
4849 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4850 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4851 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4852 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4854 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
4855 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
4857 sa = PRINTER_ACE_FULL_CONTROL;
4858 init_sec_ace(&ace[i++], &adm_sid,
4859 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4860 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4861 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4862 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4865 /* add BUILTIN\Administrators as FULL CONTROL */
4867 sa = PRINTER_ACE_FULL_CONTROL;
4868 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4869 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4870 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4871 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4872 SEC_ACE_TYPE_ACCESS_ALLOWED,
4873 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4875 /* add BUILTIN\Print Operators as FULL CONTROL */
4877 sa = PRINTER_ACE_FULL_CONTROL;
4878 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4879 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4880 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4881 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4882 SEC_ACE_TYPE_ACCESS_ALLOWED,
4883 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4885 /* Make the security descriptor owned by the BUILTIN\Administrators */
4887 /* The ACL revision number in rpc_secdesc.h differs from the one
4888 created by NT when setting ACE entries in printer
4889 descriptors. NT4 complains about the property being edited by a
4892 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
4893 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
4894 &global_sid_Builtin_Administrators,
4895 &global_sid_Builtin_Administrators,
4896 NULL, psa, &sd_size);
4900 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4904 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4906 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4907 (unsigned int)sd_size));
4912 /****************************************************************************
4913 Get a security desc for a printer.
4914 ****************************************************************************/
4916 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
4924 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
4925 sharename = temp + 1;
4928 /* Fetch security descriptor from tdb */
4930 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
4932 dbuf = tdb_fetch(tdb_printers, kbuf);
4935 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
4937 SAFE_FREE(dbuf.dptr);
4939 if (NT_STATUS_IS_OK(status)) {
4944 *secdesc_ctr = construct_default_printer_sdb(ctx);
4945 if (!*secdesc_ctr) {
4949 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
4950 &blob.data, &blob.length);
4951 if (NT_STATUS_IS_OK(status)) {
4952 dbuf.dptr = (unsigned char *)blob.data;
4953 dbuf.dsize = blob.length;
4954 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
4955 talloc_free(blob.data);
4958 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4959 this security descriptor has been created when winbindd was
4960 down. Take ownership of security descriptor. */
4962 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
4963 struct dom_sid owner_sid;
4965 /* Change sd owner to workgroup administrator */
4967 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4968 struct sec_desc_buf *new_secdesc_ctr = NULL;
4969 struct security_descriptor *psd = NULL;
4974 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
4976 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
4978 (*secdesc_ctr)->sd->group_sid,
4979 (*secdesc_ctr)->sd->sacl,
4980 (*secdesc_ctr)->sd->dacl,
4987 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4988 if (!new_secdesc_ctr) {
4992 /* Swap with other one */
4994 *secdesc_ctr = new_secdesc_ctr;
4998 nt_printing_setsec(sharename, *secdesc_ctr);
5002 if (DEBUGLEVEL >= 10) {
5003 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
5006 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5007 sharename, the_acl->num_aces));
5009 for (i = 0; i < the_acl->num_aces; i++) {
5010 DEBUG(10, ("%s %d %d 0x%08x\n",
5011 sid_string_dbg(&the_acl->aces[i].trustee),
5012 the_acl->aces[i].type, the_acl->aces[i].flags,
5013 the_acl->aces[i].access_mask));
5022 1: level not implemented
5023 2: file doesn't exist
5024 3: can't allocate memory
5025 4: can't free memory
5026 5: non existant struct
5030 A printer and a printer driver are 2 different things.
5031 NT manages them separatelly, Samba does the same.
5032 Why ? Simply because it's easier and it makes sense !
5034 Now explanation: You have 3 printers behind your samba server,
5035 2 of them are the same make and model (laser A and B). But laser B
5036 has an 3000 sheet feeder and laser A doesn't such an option.
5037 Your third printer is an old dot-matrix model for the accounting :-).
5039 If the /usr/local/samba/lib directory (default dir), you will have
5040 5 files to describe all of this.
5042 3 files for the printers (1 by printer):
5045 NTprinter_accounting
5046 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5047 NTdriver_printer model X
5048 NTdriver_printer model Y
5050 jfm: I should use this comment for the text file to explain
5051 same thing for the forms BTW.
5052 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5056 /* Convert generic access rights to printer object specific access rights.
5057 It turns out that NT4 security descriptors use generic access rights and
5058 NT5 the object specific ones. */
5060 void map_printer_permissions(struct security_descriptor *sd)
5064 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5065 se_map_generic(&sd->dacl->aces[i].access_mask,
5066 &printer_generic_mapping);
5070 void map_job_permissions(struct security_descriptor *sd)
5074 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5075 se_map_generic(&sd->dacl->aces[i].access_mask,
5076 &job_generic_mapping);
5081 /****************************************************************************
5082 Check a user has permissions to perform the given operation. We use the
5083 permission constants defined in include/rpc_spoolss.h to check the various
5084 actions we perform when checking printer access.
5086 PRINTER_ACCESS_ADMINISTER:
5087 print_queue_pause, print_queue_resume, update_printer_sec,
5088 update_printer, spoolss_addprinterex_level_2,
5089 _spoolss_setprinterdata
5094 JOB_ACCESS_ADMINISTER:
5095 print_job_delete, print_job_pause, print_job_resume,
5098 Try access control in the following order (for performance reasons):
5099 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5100 2) check security descriptor (bit comparisons in memory)
5101 3) "printer admins" (may result in numerous calls to winbind)
5103 ****************************************************************************/
5104 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5107 struct spoolss_security_descriptor *secdesc = NULL;
5108 uint32 access_granted;
5113 TALLOC_CTX *mem_ctx = NULL;
5114 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5116 /* If user is NULL then use the current_user structure */
5118 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5120 if (server_info->utok.uid == sec_initial_uid()
5121 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5125 /* Get printer name */
5127 pname = lp_printername(snum);
5129 if (!pname || !*pname) {
5134 /* Get printer security descriptor */
5136 if(!(mem_ctx = talloc_init("print_access_check"))) {
5141 result = winreg_get_printer_secdesc(mem_ctx,
5145 if (!W_ERROR_IS_OK(result)) {
5146 talloc_destroy(mem_ctx);
5151 if (access_type == JOB_ACCESS_ADMINISTER) {
5152 struct spoolss_security_descriptor *parent_secdesc = secdesc;
5154 /* Create a child security descriptor to check permissions
5155 against. This is because print jobs are child objects
5156 objects of a printer. */
5157 status = se_create_child_secdesc(mem_ctx,
5161 parent_secdesc->owner_sid,
5162 parent_secdesc->group_sid,
5164 if (!NT_STATUS_IS_OK(status)) {
5165 talloc_destroy(mem_ctx);
5166 errno = map_errno_from_nt_status(status);
5170 map_job_permissions(secdesc);
5172 map_printer_permissions(secdesc);
5176 status = se_access_check(secdesc, server_info->ptok, access_type,
5179 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5181 /* see if we need to try the printer admin list */
5183 if (!NT_STATUS_IS_OK(status) &&
5184 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5185 server_info->info3->base.domain.string,
5186 NULL, server_info->ptok,
5187 lp_printer_admin(snum)))) {
5188 talloc_destroy(mem_ctx);
5192 talloc_destroy(mem_ctx);
5194 if (!NT_STATUS_IS_OK(status)) {
5198 return NT_STATUS_IS_OK(status);
5201 /****************************************************************************
5202 Check the time parameters allow a print operation.
5203 *****************************************************************************/
5205 bool print_time_access_check(struct auth_serversupplied_info *server_info,
5206 const char *servicename)
5208 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5211 time_t now = time(NULL);
5215 result = winreg_get_printer(NULL, server_info,
5216 NULL, servicename, &pinfo2);
5217 if (!W_ERROR_IS_OK(result)) {
5221 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
5226 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5228 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
5232 TALLOC_FREE(pinfo2);
5241 /****************************************************************************
5242 Fill in the servername sent in the _spoolss_open_printer_ex() call
5243 ****************************************************************************/
5245 char* get_server_name( Printer_entry *printer )
5247 return printer->servername;