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 the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2665 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2666 * @return bool indicating success or failure
2667 ***************************************************************************/
2669 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2671 struct regval_ctr *ctr = NULL;
2673 const char *dnssuffix;
2674 char *allocated_string = NULL;
2675 const char *ascii_str;
2678 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2679 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2680 ctr = info2->data->keys[i].values;
2682 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2683 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2685 /* we make the assumption that the netbios name is the same
2686 as the DNS name sinc ethe former will be what we used to
2689 dnssuffix = get_mydnsdomname(talloc_tos());
2690 if (dnssuffix && *dnssuffix) {
2691 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2693 fstrcpy( longname, global_myname() );
2696 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2698 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
2701 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2702 SAFE_FREE(allocated_string);
2704 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2705 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2706 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2707 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2708 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2709 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2710 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2711 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2712 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2714 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2715 (info2->attributes &
2716 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2718 switch (info2->attributes & 0x3) {
2720 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2723 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2726 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2729 ascii_str = "unknown";
2731 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2736 /*****************************************************************
2737 ****************************************************************/
2739 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2743 struct regval_ctr *ctr=NULL;
2745 /* find the DsSpooler key */
2746 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2747 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2748 ctr = info2->data->keys[i].values;
2750 regval_ctr_delvalue(ctr, "objectGUID");
2752 /* We used to store this as a REG_BINARY but that causes
2755 regval_ctr_addvalue_sz(ctr, "objectGUID",
2756 GUID_string(talloc_tos(), &guid));
2759 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2760 NT_PRINTER_INFO_LEVEL *printer)
2764 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
2765 char *srv_dn_utf8, **srv_cn_utf8;
2768 const char *attrs[] = {"objectGUID", NULL};
2770 WERROR win_rc = WERR_OK;
2771 size_t converted_size;
2773 /* build the ads mods */
2774 ctx = talloc_init("nt_printer_publish_ads");
2779 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2781 /* figure out where to publish */
2782 ads_find_machine_acct(ads, &res, global_myname());
2784 /* We use ldap_get_dn here as we need the answer
2785 * in utf8 to call ldap_explode_dn(). JRA. */
2787 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2790 return WERR_SERVER_UNAVAILABLE;
2792 ads_msgfree(ads, res);
2793 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2796 ldap_memfree(srv_dn_utf8);
2797 return WERR_SERVER_UNAVAILABLE;
2799 /* Now convert to CH_UNIX. */
2800 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
2802 ldap_memfree(srv_dn_utf8);
2803 ldap_memfree(srv_cn_utf8);
2804 return WERR_SERVER_UNAVAILABLE;
2806 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
2808 ldap_memfree(srv_dn_utf8);
2809 ldap_memfree(srv_cn_utf8);
2810 TALLOC_FREE(srv_dn);
2811 return WERR_SERVER_UNAVAILABLE;
2814 ldap_memfree(srv_dn_utf8);
2815 ldap_memfree(srv_cn_utf8);
2817 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
2818 if (!srv_cn_escaped) {
2820 return WERR_SERVER_UNAVAILABLE;
2822 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
2823 if (!sharename_escaped) {
2824 SAFE_FREE(srv_cn_escaped);
2826 return WERR_SERVER_UNAVAILABLE;
2829 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
2831 SAFE_FREE(srv_cn_escaped);
2832 SAFE_FREE(sharename_escaped);
2834 mods = ads_init_mods(ctx);
2842 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
2843 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2844 printer->info_2->sharename);
2847 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2848 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
2850 for (i=0; mods[i] != 0; i++)
2852 mods[i] = (LDAPMod *)-1;
2853 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2856 if (!ADS_ERR_OK(ads_rc))
2857 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2859 /* retreive the guid and store it locally */
2860 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2862 ads_pull_guid(ads, res, &guid);
2863 ads_msgfree(ads, res);
2864 store_printer_guid(printer->info_2, guid);
2865 win_rc = mod_a_printer(printer, 2);
2872 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2873 NT_PRINTER_INFO_LEVEL *printer)
2876 LDAPMessage *res = NULL;
2877 char *prt_dn = NULL;
2879 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2881 /* remove the printer from the directory */
2882 ads_rc = ads_find_printer_on_server(ads, &res,
2883 printer->info_2->sharename, global_myname());
2885 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
2886 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2888 ads_msgfree(ads, res);
2891 ads_rc = ads_del_dn(ads, prt_dn);
2892 TALLOC_FREE(prt_dn);
2896 ads_msgfree(ads, res);
2901 /****************************************************************************
2902 * Publish a printer in the directory
2904 * @param snum describing printer service
2905 * @return WERROR indicating status of publishing
2906 ***************************************************************************/
2908 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2911 ADS_STRUCT *ads = NULL;
2912 NT_PRINTER_INFO_LEVEL *printer = NULL;
2915 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2916 if (!W_ERROR_IS_OK(win_rc))
2920 case DSPRINT_PUBLISH:
2921 case DSPRINT_UPDATE:
2922 /* set the DsSpooler info and attributes */
2923 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2924 win_rc = WERR_NOMEM;
2928 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2930 case DSPRINT_UNPUBLISH:
2931 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2934 win_rc = WERR_NOT_SUPPORTED;
2938 win_rc = mod_a_printer(printer, 2);
2939 if (!W_ERROR_IS_OK(win_rc)) {
2940 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2944 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2946 DEBUG(3, ("ads_init() failed\n"));
2947 win_rc = WERR_SERVER_UNAVAILABLE;
2950 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2951 SAFE_FREE(ads->auth.password);
2952 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2955 /* ads_connect() will find the DC for us */
2956 ads_rc = ads_connect(ads);
2957 if (!ADS_ERR_OK(ads_rc)) {
2958 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2959 win_rc = WERR_ACCESS_DENIED;
2964 case DSPRINT_PUBLISH:
2965 case DSPRINT_UPDATE:
2966 win_rc = nt_printer_publish_ads(ads, printer);
2968 case DSPRINT_UNPUBLISH:
2969 win_rc = nt_printer_unpublish_ads(ads, printer);
2974 free_a_printer(&printer, 2);
2979 WERROR check_published_printers(void)
2982 ADS_STRUCT *ads = NULL;
2984 int n_services = lp_numservices();
2985 NT_PRINTER_INFO_LEVEL *printer = NULL;
2987 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
2989 DEBUG(3, ("ads_init() failed\n"));
2990 return WERR_SERVER_UNAVAILABLE;
2992 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2993 SAFE_FREE(ads->auth.password);
2994 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2997 /* ads_connect() will find the DC for us */
2998 ads_rc = ads_connect(ads);
2999 if (!ADS_ERR_OK(ads_rc)) {
3000 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3002 ads_kdestroy("MEMORY:prtpub_cache");
3003 return WERR_ACCESS_DENIED;
3006 for (snum = 0; snum < n_services; snum++) {
3007 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3010 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3011 lp_servicename(snum))) &&
3012 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3013 nt_printer_publish_ads(ads, printer);
3015 free_a_printer(&printer, 2);
3019 ads_kdestroy("MEMORY:prtpub_cache");
3023 bool is_printer_published(Printer_entry *print_hnd, int snum,
3026 NT_PRINTER_INFO_LEVEL *printer = NULL;
3027 struct regval_ctr *ctr;
3028 struct regval_blob *guid_val;
3034 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3036 if (!W_ERROR_IS_OK(win_rc) ||
3037 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3038 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3039 !(ctr = printer->info_2->data->keys[i].values) ||
3040 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3042 free_a_printer(&printer, 2);
3046 /* fetching printer guids really ought to be a separate function. */
3051 /* We used to store the guid as REG_BINARY, then swapped
3052 to REG_SZ for Vista compatibility so check for both */
3054 switch ( regval_type(guid_val) ){
3056 blob = data_blob_const(regval_data_p(guid_val),
3057 regval_size(guid_val));
3058 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3059 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3060 talloc_free(guid_str);
3063 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3067 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3070 DEBUG(0,("is_printer_published: GUID value stored as "
3071 "invaluid type (%d)\n", regval_type(guid_val) ));
3076 free_a_printer(&printer, 2);
3080 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3085 WERROR check_published_printers(void)
3090 bool is_printer_published(Printer_entry *print_hnd, int snum,
3095 #endif /* HAVE_ADS */
3097 /****************************************************************************
3098 ***************************************************************************/
3100 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3102 NT_PRINTER_DATA *data;
3104 int removed_keys = 0;
3108 empty_slot = data->num_keys;
3111 return WERR_INVALID_PARAM;
3113 /* remove all keys */
3115 if ( !strlen(key) ) {
3117 TALLOC_FREE( data );
3121 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3127 /* remove a specific key (and all subkeys) */
3129 for ( i=0; i<data->num_keys; i++ ) {
3130 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3131 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3132 data->keys[i].name));
3134 TALLOC_FREE( data->keys[i].name );
3135 TALLOC_FREE( data->keys[i].values );
3137 /* mark the slot as empty */
3139 ZERO_STRUCTP( &data->keys[i] );
3143 /* find the first empty slot */
3145 for ( i=0; i<data->num_keys; i++ ) {
3146 if ( !data->keys[i].name ) {
3153 if ( i == data->num_keys )
3154 /* nothing was removed */
3155 return WERR_INVALID_PARAM;
3157 /* move everything down */
3159 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3160 if ( data->keys[i].name ) {
3161 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3162 ZERO_STRUCTP( &data->keys[i] );
3170 data->num_keys -= removed_keys;
3172 /* sanity check to see if anything is left */
3174 if ( !data->num_keys ) {
3175 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3177 SAFE_FREE( data->keys );
3178 ZERO_STRUCTP( data );
3184 /****************************************************************************
3185 ***************************************************************************/
3187 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3189 WERROR result = WERR_OK;
3192 /* we must have names on non-zero length */
3194 if ( !key || !*key|| !value || !*value )
3195 return WERR_INVALID_NAME;
3197 /* find the printer key first */
3199 key_index = lookup_printerkey( p2->data, key );
3200 if ( key_index == -1 )
3203 /* make sure the value exists so we can return the correct error code */
3205 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3206 return WERR_BADFILE;
3208 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3210 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3216 /****************************************************************************
3217 ***************************************************************************/
3219 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3220 uint32 type, uint8 *data, int real_len )
3222 WERROR result = WERR_OK;
3225 /* we must have names on non-zero length */
3227 if ( !key || !*key|| !value || !*value )
3228 return WERR_INVALID_NAME;
3230 /* find the printer key first */
3232 key_index = lookup_printerkey( p2->data, key );
3233 if ( key_index == -1 )
3234 key_index = add_new_printer_key( p2->data, key );
3236 if ( key_index == -1 )
3239 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3240 type, data, real_len );
3242 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3243 key, value, type, real_len ));
3248 /****************************************************************************
3249 ***************************************************************************/
3251 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3255 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3258 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3261 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3264 /****************************************************************************
3265 Unpack a list of registry values frem the TDB
3266 ***************************************************************************/
3268 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3273 const char *valuename = NULL;
3274 const char *keyname = NULL;
3278 struct regval_blob *regval_p;
3281 /* add the "PrinterDriverData" key first for performance reasons */
3283 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3285 /* loop and unpack the rest of the registry values */
3289 /* check to see if there are any more registry values */
3292 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3296 /* unpack the next regval */
3298 len += tdb_unpack(buf+len, buflen-len, "fdB",
3304 /* lookup for subkey names which have a type of REG_NONE */
3305 /* there's no data with this entry */
3307 if ( type == REG_NONE ) {
3308 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3309 add_new_printer_key( printer_data, string );
3314 * break of the keyname from the value name.
3315 * Valuenames can have embedded '\'s so be careful.
3316 * only support one level of keys. See the
3317 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3321 str = strchr_m( string, '\\');
3323 /* Put in "PrinterDriverData" is no key specified */
3326 keyname = SPOOL_PRINTERDATA_KEY;
3335 /* see if we need a new key */
3337 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3338 key_index = add_new_printer_key( printer_data, keyname );
3340 if ( key_index == -1 ) {
3341 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3346 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3348 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3349 Thanks to Martin Zielinski for the hint. */
3351 if ( type == REG_BINARY &&
3352 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3353 strequal( valuename, "objectGUID" ) )
3357 /* convert the GUID to a UNICODE string */
3359 memcpy( &guid, data_p, sizeof(struct GUID) );
3361 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3363 GUID_string(talloc_tos(), &guid));
3368 regval_ctr_addvalue( printer_data->keys[key_index].values,
3369 valuename, type, data_p,
3373 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3380 /****************************************************************************
3381 ***************************************************************************/
3383 static char *win_driver;
3384 static char *os2_driver;
3386 static const char *get_win_driver(void)
3388 if (win_driver == NULL) {
3394 static const char *get_os2_driver(void)
3396 if (os2_driver == NULL) {
3402 static bool set_driver_mapping(const char *from, const char *to)
3404 SAFE_FREE(win_driver);
3405 SAFE_FREE(os2_driver);
3407 win_driver = SMB_STRDUP(from);
3408 os2_driver = SMB_STRDUP(to);
3410 if (win_driver == NULL || os2_driver == NULL) {
3411 SAFE_FREE(win_driver);
3412 SAFE_FREE(os2_driver);
3418 static void map_to_os2_driver(fstring drivername)
3420 char *mapfile = lp_os2_driver_map();
3421 char **lines = NULL;
3425 if (!strlen(drivername))
3431 if (strequal(drivername, get_win_driver())) {
3432 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3433 drivername, get_os2_driver()));
3434 fstrcpy(drivername, get_os2_driver());
3438 lines = file_lines_load(mapfile, &numlines,0,NULL);
3439 if (numlines == 0 || lines == NULL) {
3440 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3445 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3447 for( i = 0; i < numlines; i++) {
3448 char *nt_name = lines[i];
3449 char *os2_name = strchr(nt_name,'=');
3456 while (isspace(*nt_name))
3459 if (!*nt_name || strchr("#;",*nt_name))
3463 int l = strlen(nt_name);
3464 while (l && isspace(nt_name[l-1])) {
3470 while (isspace(*os2_name))
3474 int l = strlen(os2_name);
3475 while (l && isspace(os2_name[l-1])) {
3481 if (strequal(nt_name,drivername)) {
3482 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3483 set_driver_mapping(drivername,os2_name);
3484 fstrcpy(drivername,os2_name);
3496 * @brief Map a Windows driver to a OS/2 driver.
3498 * @param[in] mem_ctx The memory context to use.
3500 * @param[in,out] pdrivername The drivername of Windows to remap.
3502 * @return WERR_OK on success, a corresponding WERROR on failure.
3504 WERROR spoolss_map_to_os2_driver(TALLOC_CTX *mem_ctx, const char **pdrivername)
3506 const char *mapfile = lp_os2_driver_map();
3507 char **lines = NULL;
3508 const char *drivername;
3512 if (pdrivername == NULL || *pdrivername == NULL || *pdrivername[0] == '\0') {
3513 return WERR_INVALID_PARAMETER;
3516 drivername = *pdrivername;
3518 if (mapfile[0] == '\0') {
3519 return WERR_BADFILE;
3522 if (strequal(drivername, get_win_driver())) {
3523 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3524 drivername, get_os2_driver()));
3525 drivername = talloc_strdup(mem_ctx, get_os2_driver());
3526 if (drivername == NULL) {
3529 *pdrivername = drivername;
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, '=');
3546 if (os2_name == NULL) {
3552 while (isspace(*nt_name)) {
3556 if (*nt_name == '\0' || strchr("#;", *nt_name)) {
3561 int l = strlen(nt_name);
3562 while (l && isspace(nt_name[l - 1])) {
3568 while (isspace(*os2_name)) {
3573 int l = strlen(os2_name);
3574 while (l && isspace(os2_name[l-1])) {
3580 if (strequal(nt_name, drivername)) {
3581 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,os2_name));
3582 set_driver_mapping(drivername, os2_name);
3583 drivername = talloc_strdup(mem_ctx, os2_name);
3585 if (drivername == NULL) {
3588 *pdrivername = drivername;
3597 /****************************************************************************
3598 Get a default printer info 2 struct.
3599 ****************************************************************************/
3601 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3602 const char *servername,
3603 const char* sharename,
3606 int snum = lp_servicenumber(sharename);
3609 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3610 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3611 servername, sharename);
3612 fstrcpy(info->sharename, sharename);
3613 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3615 /* by setting the driver name to an empty string, a local NT admin
3616 can now run the **local** APW to install a local printer driver
3617 for a Samba shared printer in 2.2. Without this, drivers **must** be
3618 installed on the Samba server for NT clients --jerry */
3619 #if 0 /* JERRY --do not uncomment-- */
3620 if (!*info->drivername)
3621 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3625 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3627 strlcpy(info->comment, "", sizeof(info->comment));
3628 fstrcpy(info->printprocessor, "winprint");
3629 fstrcpy(info->datatype, "RAW");
3632 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3633 /* Pull the location and comment strings from cups if we don't
3635 if ( !strlen(info->location) || !strlen(info->comment) ) {
3636 char *comment = NULL;
3637 char *location = NULL;
3638 if (cups_pull_comment_location(info, info->sharename,
3639 &comment, &location)) {
3640 strlcpy(info->comment, comment, sizeof(info->comment));
3641 fstrcpy(info->location, location);
3642 TALLOC_FREE(comment);
3643 TALLOC_FREE(location);
3649 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3651 info->starttime = 0; /* Minutes since 12:00am GMT */
3652 info->untiltime = 0; /* Minutes since 12:00am GMT */
3654 info->default_priority = 1;
3655 info->setuptime = (uint32)time(NULL);
3658 * I changed this as I think it is better to have a generic
3659 * DEVMODE than to crash Win2k explorer.exe --jerry
3660 * See the HP Deskjet 990c Win2k drivers for an example.
3662 * However the default devmode appears to cause problems
3663 * with the HP CLJ 8500 PCL driver. Hence the addition of
3664 * the "default devmode" parameter --jerry 22/01/2002
3667 if (lp_default_devmode(snum)) {
3668 result = spoolss_create_default_devmode(info,
3671 if (!W_ERROR_IS_OK(result)) {
3675 info->devmode = NULL;
3678 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3682 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
3687 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
3692 TALLOC_FREE(info->devmode);
3694 return WERR_ACCESS_DENIED;
3697 /****************************************************************************
3698 ****************************************************************************/
3700 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
3701 const char *servername,
3702 const char *sharename,
3706 int snum = lp_servicenumber(sharename);
3707 TDB_DATA kbuf, dbuf;
3708 fstring printername;
3709 char *comment = NULL;
3712 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
3714 dbuf = tdb_fetch(tdb_printers, kbuf);
3716 return get_a_printer_2_default(info, servername,
3717 sharename, get_loc_com);
3720 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3723 &info->default_priority,
3730 &info->c_setprinter,
3740 info->printprocessor,
3745 strlcpy(info->comment, comment, sizeof(info->comment));
3749 /* Samba has to have shared raw drivers. */
3750 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3751 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3753 /* Restore the stripped strings. */
3754 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3756 if ( lp_force_printername(snum) ) {
3757 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3759 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3762 fstrcpy(info->printername, printername);
3765 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3766 /* Pull the location and comment strings from cups if we don't
3768 if ( !strlen(info->location) || !strlen(info->comment) ) {
3769 char *location = NULL;
3771 if (cups_pull_comment_location(info, info->sharename,
3772 &comment, &location)) {
3773 strlcpy(info->comment, comment, sizeof(info->comment));
3774 fstrcpy(info->location, location);
3775 TALLOC_FREE(comment);
3776 TALLOC_FREE(location);
3782 len += unpack_devicemode(info, dbuf.dptr+len,
3787 * Some client drivers freak out if there is a NULL devmode
3788 * (probably the driver is not checking before accessing
3789 * the devmode pointer) --jerry
3791 * See comments in get_a_printer_2_default()
3794 if (lp_default_devmode(snum) && !info->devmode) {
3795 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3797 result = spoolss_create_default_devmode(info, printername,
3799 if (!W_ERROR_IS_OK(result)) {
3804 if (info->devmode) {
3805 info->devmode->devicename = talloc_strdup(info->devmode,
3807 if (!info->devmode->devicename) {
3808 result = WERR_NOMEM;
3813 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3814 DEBUG(0,("unpack_values: talloc() failed!\n"));
3815 result = WERR_NOMEM;
3818 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3820 /* This will get the current RPC talloc context, but we should be
3821 passing this as a parameter... fixme... JRA ! */
3823 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3824 result = WERR_NOMEM;
3828 /* Fix for OS/2 drivers. */
3830 if (get_remote_arch() == RA_OS2) {
3831 map_to_os2_driver(info->drivername);
3834 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3835 sharename, info->printername, info->drivername));
3840 SAFE_FREE(dbuf.dptr);
3844 /****************************************************************************
3845 Debugging function, dump at level 6 the struct in the logs.
3846 ****************************************************************************/
3847 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3850 NT_PRINTER_INFO_LEVEL_2 *info2;
3852 DEBUG(106,("Dumping printer at level [%d]\n", level));
3857 if (printer->info_2 == NULL)
3861 info2=printer->info_2;
3863 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3864 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3865 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3866 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3867 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3868 DEBUGADD(106,("status:[%d]\n", info2->status));
3869 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3870 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3871 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3872 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3873 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3875 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3876 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3877 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3878 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3879 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3880 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3881 DEBUGADD(106,("location:[%s]\n", info2->location));
3882 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3883 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3884 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3885 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3891 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3899 /****************************************************************************
3900 Update the changeid time.
3901 This is SO NASTY as some drivers need this to change, others need it
3902 static. This value will change every second, and I must hope that this
3903 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3905 ****************************************************************************/
3907 static uint32 rev_changeid(void)
3911 get_process_uptime(&tv);
3914 /* Return changeid as msec since spooler restart */
3915 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3918 * This setting seems to work well but is too untested
3919 * to replace the above calculation. Left in for experiementation
3920 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3922 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3928 * The function below are the high level ones.
3929 * only those ones must be called from the spoolss code.
3933 /****************************************************************************
3934 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3935 ****************************************************************************/
3937 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3941 dump_a_printer(printer, level);
3947 * Update the changestamp. Emperical tests show that the
3948 * ChangeID is always updated,but c_setprinter is
3949 * global spooler variable (not per printer).
3952 /* ChangeID **must** be increasing over the lifetime
3953 of client's spoolss service in order for the
3954 client's cache to show updates */
3956 printer->info_2->changeid = rev_changeid();
3959 * Because one day someone will ask:
3960 * NT->NT An admin connection to a remote
3961 * printer show changes imeediately in
3962 * the properities dialog
3964 * A non-admin connection will only show the
3965 * changes after viewing the properites page
3966 * 2 times. Seems to be related to a
3967 * race condition in the client between the spooler
3968 * updating the local cache and the Explorer.exe GUI
3969 * actually displaying the properties.
3971 * This is fixed in Win2k. admin/non-admin
3972 * connections both display changes immediately.
3977 result=update_a_printer_2(printer->info_2);
3981 result=WERR_UNKNOWN_LEVEL;
3988 /****************************************************************************
3989 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3991 Previously the code had a memory allocation problem because it always
3992 used the TALLOC_CTX from the Printer_entry*. This context lasts
3993 as a long as the original handle is open. So if the client made a lot
3994 of getprinter[data]() calls, the memory usage would climb. Now we use
3995 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3996 still use the Printer_entry->ctx for maintaining the cache copy though
3997 since that object must live as long as the handle by definition.
4000 ****************************************************************************/
4002 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4003 const char *sharename, bool get_loc_com)
4008 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4010 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4011 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4017 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4018 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4019 TALLOC_FREE( *pp_printer );
4024 fstrcpy( servername, print_hnd->servername );
4026 fstrcpy( servername, "%L" );
4027 standard_sub_basic( "", "", servername,
4028 sizeof(servername)-1 );
4031 result = get_a_printer_2( (*pp_printer)->info_2,
4032 servername, sharename, get_loc_com);
4034 /* we have a new printer now. Save it with this handle */
4036 if ( !W_ERROR_IS_OK(result) ) {
4037 TALLOC_FREE( *pp_printer );
4038 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4039 sharename, (unsigned int)level, win_errstr(result)));
4043 dump_a_printer( *pp_printer, level);
4048 TALLOC_FREE( *pp_printer );
4049 return WERR_UNKNOWN_LEVEL;
4055 WERROR get_a_printer( Printer_entry *print_hnd,
4056 NT_PRINTER_INFO_LEVEL **pp_printer,
4058 const char *sharename)
4060 return get_a_printer_internal(print_hnd, pp_printer, level,
4064 WERROR get_a_printer_search( Printer_entry *print_hnd,
4065 NT_PRINTER_INFO_LEVEL **pp_printer,
4067 const char *sharename)
4069 return get_a_printer_internal(print_hnd, pp_printer, level,
4073 /****************************************************************************
4074 Deletes a NT_PRINTER_INFO_LEVEL struct.
4075 ****************************************************************************/
4077 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4079 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4086 TALLOC_FREE(printer->info_2);
4090 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4094 TALLOC_FREE(*pp_printer);
4099 /****************************************************************************
4100 ****************************************************************************/
4102 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4103 struct spoolss_DriverInfo8 *_info8)
4105 struct spoolss_DriverInfo8 info8;
4111 info8.version = r->info.info3->version;
4112 info8.driver_name = r->info.info3->driver_name;
4113 info8.architecture = r->info.info3->architecture;
4114 info8.driver_path = r->info.info3->driver_path;
4115 info8.data_file = r->info.info3->data_file;
4116 info8.config_file = r->info.info3->config_file;
4117 info8.help_file = r->info.info3->help_file;
4118 info8.monitor_name = r->info.info3->monitor_name;
4119 info8.default_datatype = r->info.info3->default_datatype;
4120 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4121 info8.dependent_files = r->info.info3->dependent_files->string;
4125 info8.version = r->info.info6->version;
4126 info8.driver_name = r->info.info6->driver_name;
4127 info8.architecture = r->info.info6->architecture;
4128 info8.driver_path = r->info.info6->driver_path;
4129 info8.data_file = r->info.info6->data_file;
4130 info8.config_file = r->info.info6->config_file;
4131 info8.help_file = r->info.info6->help_file;
4132 info8.monitor_name = r->info.info6->monitor_name;
4133 info8.default_datatype = r->info.info6->default_datatype;
4134 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4135 info8.dependent_files = r->info.info6->dependent_files->string;
4137 info8.driver_date = r->info.info6->driver_date;
4138 info8.driver_version = r->info.info6->driver_version;
4139 info8.manufacturer_name = r->info.info6->manufacturer_name;
4140 info8.manufacturer_url = r->info.info6->manufacturer_url;
4141 info8.hardware_id = r->info.info6->hardware_id;
4142 info8.provider = r->info.info6->provider;
4145 info8.version = r->info.info8->version;
4146 info8.driver_name = r->info.info8->driver_name;
4147 info8.architecture = r->info.info8->architecture;
4148 info8.driver_path = r->info.info8->driver_path;
4149 info8.data_file = r->info.info8->data_file;
4150 info8.config_file = r->info.info8->config_file;
4151 info8.help_file = r->info.info8->help_file;
4152 info8.monitor_name = r->info.info8->monitor_name;
4153 info8.default_datatype = r->info.info8->default_datatype;
4154 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4155 info8.dependent_files = r->info.info8->dependent_files->string;
4157 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4158 info8.previous_names = r->info.info8->previous_names->string;
4160 info8.driver_date = r->info.info8->driver_date;
4161 info8.driver_version = r->info.info8->driver_version;
4162 info8.manufacturer_name = r->info.info8->manufacturer_name;
4163 info8.manufacturer_url = r->info.info8->manufacturer_url;
4164 info8.hardware_id = r->info.info8->hardware_id;
4165 info8.provider = r->info.info8->provider;
4166 info8.print_processor = r->info.info8->print_processor;
4167 info8.vendor_setup = r->info.info8->vendor_setup;
4168 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4169 info8.color_profiles = r->info.info8->color_profiles->string;
4171 info8.inf_path = r->info.info8->inf_path;
4172 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4173 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4174 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4176 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4177 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4189 /****************************************************************************
4190 Determine whether or not a particular driver is currently assigned
4192 ****************************************************************************/
4194 bool printer_driver_in_use(TALLOC_CTX *mem_ctx,
4195 struct auth_serversupplied_info *server_info,
4196 const struct spoolss_DriverInfo8 *r)
4199 int n_services = lp_numservices();
4200 NT_PRINTER_INFO_LEVEL *printer = NULL;
4201 bool in_use = False;
4207 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4209 /* loop through the printers.tdb and check for the drivername */
4211 for (snum=0; snum<n_services && !in_use; snum++) {
4212 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4215 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4218 if (strequal(r->driver_name, printer->info_2->drivername))
4221 free_a_printer( &printer, 2 );
4224 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4227 struct spoolss_DriverInfo8 *driver;
4230 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4232 /* we can still remove the driver if there is one of
4233 "Windows NT x86" version 2 or 3 left */
4235 if (!strequal("Windows NT x86", r->architecture)) {
4236 werr = winreg_get_driver(mem_ctx, server_info,
4241 } else if (r->version == 2) {
4242 werr = winreg_get_driver(mem_ctx, server_info,
4246 } else if (r->version == 3) {
4247 werr = winreg_get_driver(mem_ctx, server_info,
4252 DEBUG(0, ("printer_driver_in_use: ERROR!"
4253 " unknown driver version (%d)\n",
4255 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4258 /* now check the error code */
4260 if ( W_ERROR_IS_OK(werr) ) {
4261 /* it's ok to remove the driver, we have other architctures left */
4263 talloc_free(driver);
4267 /* report that the driver is not in use by default */
4273 /**********************************************************************
4274 Check to see if a ogiven file is in use by *info
4275 *********************************************************************/
4277 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4284 /* mz: skip files that are in the list but already deleted */
4285 if (!file || !file[0]) {
4289 if (strequal(file, info->driver_path))
4292 if (strequal(file, info->data_file))
4295 if (strequal(file, info->config_file))
4298 if (strequal(file, info->help_file))
4301 /* see of there are any dependent files to examine */
4303 if (!info->dependent_files)
4306 while (info->dependent_files[i] && *info->dependent_files[i]) {
4307 if (strequal(file, info->dependent_files[i]))
4316 /**********************************************************************
4317 Utility function to remove the dependent file pointed to by the
4318 input parameter from the list
4319 *********************************************************************/
4321 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
4324 /* bump everything down a slot */
4326 while (files && files[idx+1]) {
4327 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
4336 /**********************************************************************
4337 Check if any of the files used by src are also used by drv
4338 *********************************************************************/
4340 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
4341 struct spoolss_DriverInfo8 *src,
4342 const struct spoolss_DriverInfo8 *drv)
4344 bool in_use = False;
4350 /* check each file. Remove it from the src structure if it overlaps */
4352 if (drv_file_in_use(src->driver_path, drv)) {
4354 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
4355 src->driver_path = talloc_strdup(mem_ctx, "");
4356 if (!src->driver_path) { return false; }
4359 if (drv_file_in_use(src->data_file, drv)) {
4361 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
4362 src->data_file = talloc_strdup(mem_ctx, "");
4363 if (!src->data_file) { return false; }
4366 if (drv_file_in_use(src->config_file, drv)) {
4368 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
4369 src->config_file = talloc_strdup(mem_ctx, "");
4370 if (!src->config_file) { return false; }
4373 if (drv_file_in_use(src->help_file, drv)) {
4375 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
4376 src->help_file = talloc_strdup(mem_ctx, "");
4377 if (!src->help_file) { return false; }
4380 /* are there any dependentfiles to examine? */
4382 if (!src->dependent_files)
4385 while (src->dependent_files[i] && *src->dependent_files[i]) {
4386 if (drv_file_in_use(src->dependent_files[i], drv)) {
4388 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
4389 trim_dependent_file(mem_ctx, src->dependent_files, i);
4397 /****************************************************************************
4398 Determine whether or not a particular driver files are currently being
4399 used by any other driver.
4401 Return value is True if any files were in use by other drivers
4402 and False otherwise.
4404 Upon return, *info has been modified to only contain the driver files
4405 which are not in use
4409 This needs to check all drivers to ensure that all files in use
4410 have been removed from *info, not just the ones in the first
4412 ****************************************************************************/
4414 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
4415 struct auth_serversupplied_info *server_info,
4416 struct spoolss_DriverInfo8 *info)
4420 struct spoolss_DriverInfo8 *driver;
4421 bool in_use = false;
4422 uint32_t num_drivers;
4423 const char **drivers;
4429 version = info->version;
4431 /* loop over all driver versions */
4433 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
4435 /* get the list of drivers */
4437 result = winreg_get_driver_list(mem_ctx, server_info,
4438 info->architecture, version,
4439 &num_drivers, &drivers);
4440 if (!W_ERROR_IS_OK(result)) {
4444 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
4445 num_drivers, info->architecture, version));
4447 /* check each driver for overlap in files */
4449 for (i = 0; i < num_drivers; i++) {
4450 DEBUGADD(5,("\tdriver: [%s]\n", drivers[i]));
4454 result = winreg_get_driver(mem_ctx, server_info,
4455 info->architecture, drivers[i],
4457 if (!W_ERROR_IS_OK(result)) {
4458 talloc_free(drivers);
4462 /* check if d2 uses any files from d1 */
4463 /* only if this is a different driver than the one being deleted */
4465 if (!strequal(info->driver_name, driver->driver_name)) {
4466 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
4467 /* mz: Do not instantly return -
4468 * we need to ensure this file isn't
4469 * also in use by other drivers. */
4474 talloc_free(driver);
4477 talloc_free(drivers);
4479 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
4484 static NTSTATUS driver_unlink_internals(connection_struct *conn,
4487 struct smb_filename *smb_fname = NULL;
4490 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
4492 if (!NT_STATUS_IS_OK(status)) {
4496 status = unlink_internals(conn, NULL, 0, smb_fname, false);
4498 TALLOC_FREE(smb_fname);
4502 /****************************************************************************
4503 Actually delete the driver files. Make sure that
4504 printer_driver_files_in_use() return False before calling
4506 ****************************************************************************/
4508 bool delete_driver_files(struct auth_serversupplied_info *server_info,
4509 const struct spoolss_DriverInfo8 *r)
4514 connection_struct *conn;
4517 fstring printdollar;
4518 int printdollar_snum;
4525 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
4526 r->driver_name, r->version));
4528 fstrcpy(printdollar, "print$");
4530 printdollar_snum = find_service(printdollar);
4531 if (printdollar_snum == -1) {
4535 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
4536 lp_pathname(printdollar_snum),
4537 server_info, &oldcwd);
4538 if (!NT_STATUS_IS_OK(nt_status)) {
4539 DEBUG(0,("delete_driver_files: create_conn_struct "
4540 "returned %s\n", nt_errstr(nt_status)));
4544 if ( !CAN_WRITE(conn) ) {
4545 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4549 /* now delete the files; must strip the '\print$' string from
4552 if (r->driver_path && r->driver_path[0]) {
4553 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
4555 DEBUG(10,("deleting driverfile [%s]\n", s));
4556 driver_unlink_internals(conn, file);
4560 if (r->config_file && r->config_file[0]) {
4561 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
4563 DEBUG(10,("deleting configfile [%s]\n", s));
4564 driver_unlink_internals(conn, file);
4568 if (r->data_file && r->data_file[0]) {
4569 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
4571 DEBUG(10,("deleting datafile [%s]\n", s));
4572 driver_unlink_internals(conn, file);
4576 if (r->help_file && r->help_file[0]) {
4577 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
4579 DEBUG(10,("deleting helpfile [%s]\n", s));
4580 driver_unlink_internals(conn, file);
4584 /* check if we are done removing files */
4586 if (r->dependent_files) {
4587 while (r->dependent_files[i] && r->dependent_files[i][0]) {
4590 /* bypass the "\print$" portion of the path */
4592 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
4594 DEBUG(10,("deleting dependent file [%s]\n", file));
4595 driver_unlink_internals(conn, file);
4607 vfs_ChDir(conn, oldcwd);
4613 /****************************************************************************
4614 Store a security desc for a printer.
4615 ****************************************************************************/
4617 WERROR nt_printing_setsec(const char *sharename, struct sec_desc_buf *secdesc_ctr)
4619 struct sec_desc_buf *new_secdesc_ctr = NULL;
4620 struct sec_desc_buf *old_secdesc_ctr = NULL;
4621 TALLOC_CTX *mem_ctx = NULL;
4628 mem_ctx = talloc_init("nt_printing_setsec");
4629 if (mem_ctx == NULL)
4632 /* The old owner and group sids of the security descriptor are not
4633 present when new ACEs are added or removed by changing printer
4634 permissions through NT. If they are NULL in the new security
4635 descriptor then copy them over from the old one. */
4637 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
4638 struct dom_sid *owner_sid, *group_sid;
4639 struct security_acl *dacl, *sacl;
4640 struct security_descriptor *psd = NULL;
4643 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
4644 status = WERR_NOMEM;
4648 /* Pick out correct owner and group sids */
4650 owner_sid = secdesc_ctr->sd->owner_sid ?
4651 secdesc_ctr->sd->owner_sid :
4652 old_secdesc_ctr->sd->owner_sid;
4654 group_sid = secdesc_ctr->sd->group_sid ?
4655 secdesc_ctr->sd->group_sid :
4656 old_secdesc_ctr->sd->group_sid;
4658 dacl = secdesc_ctr->sd->dacl ?
4659 secdesc_ctr->sd->dacl :
4660 old_secdesc_ctr->sd->dacl;
4662 sacl = secdesc_ctr->sd->sacl ?
4663 secdesc_ctr->sd->sacl :
4664 old_secdesc_ctr->sd->sacl;
4666 /* Make a deep copy of the security descriptor */
4668 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
4669 owner_sid, group_sid,
4675 status = WERR_NOMEM;
4679 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4682 if (!new_secdesc_ctr) {
4683 new_secdesc_ctr = secdesc_ctr;
4686 /* Store the security descriptor in a tdb */
4688 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
4689 &blob.data, &blob.length);
4690 if (!NT_STATUS_IS_OK(nt_status)) {
4691 status = ntstatus_to_werror(nt_status);
4695 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
4697 dbuf.dptr = (unsigned char *)blob.data;
4698 dbuf.dsize = blob.length;
4700 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
4703 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4704 status = WERR_BADFUNC;
4707 /* Free malloc'ed memory */
4708 talloc_free(blob.data);
4713 talloc_destroy(mem_ctx);
4717 /****************************************************************************
4718 Construct a default security descriptor buffer for a printer.
4719 ****************************************************************************/
4721 static struct sec_desc_buf *construct_default_printer_sdb(TALLOC_CTX *ctx)
4723 struct security_ace ace[7]; /* max number of ace entries */
4726 struct security_acl *psa = NULL;
4727 struct sec_desc_buf *sdb = NULL;
4728 struct security_descriptor *psd = NULL;
4729 struct dom_sid adm_sid;
4732 /* Create an ACE where Everyone is allowed to print */
4734 sa = PRINTER_ACE_PRINT;
4735 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4736 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4738 /* Add the domain admins group if we are a DC */
4741 struct dom_sid domadmins_sid;
4743 sid_compose(&domadmins_sid, get_global_sam_sid(),
4746 sa = PRINTER_ACE_FULL_CONTROL;
4747 init_sec_ace(&ace[i++], &domadmins_sid,
4748 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4749 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4750 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4751 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4753 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
4754 sid_append_rid(&adm_sid, DOMAIN_RID_ADMINISTRATOR);
4756 sa = PRINTER_ACE_FULL_CONTROL;
4757 init_sec_ace(&ace[i++], &adm_sid,
4758 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4759 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4760 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4761 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4764 /* add BUILTIN\Administrators as FULL CONTROL */
4766 sa = PRINTER_ACE_FULL_CONTROL;
4767 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4768 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4769 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4770 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
4771 SEC_ACE_TYPE_ACCESS_ALLOWED,
4772 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4774 /* add BUILTIN\Print Operators as FULL CONTROL */
4776 sa = PRINTER_ACE_FULL_CONTROL;
4777 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4778 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4779 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4780 init_sec_ace(&ace[i++], &global_sid_Builtin_Print_Operators,
4781 SEC_ACE_TYPE_ACCESS_ALLOWED,
4782 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4784 /* Make the security descriptor owned by the BUILTIN\Administrators */
4786 /* The ACL revision number in rpc_secdesc.h differs from the one
4787 created by NT when setting ACE entries in printer
4788 descriptors. NT4 complains about the property being edited by a
4791 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
4792 psd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
4793 &global_sid_Builtin_Administrators,
4794 &global_sid_Builtin_Administrators,
4795 NULL, psa, &sd_size);
4799 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4803 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4805 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4806 (unsigned int)sd_size));
4811 /****************************************************************************
4812 Get a security desc for a printer.
4813 ****************************************************************************/
4815 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, struct sec_desc_buf **secdesc_ctr)
4823 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
4824 sharename = temp + 1;
4827 /* Fetch security descriptor from tdb */
4829 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
4831 dbuf = tdb_fetch(tdb_printers, kbuf);
4834 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
4836 SAFE_FREE(dbuf.dptr);
4838 if (NT_STATUS_IS_OK(status)) {
4843 *secdesc_ctr = construct_default_printer_sdb(ctx);
4844 if (!*secdesc_ctr) {
4848 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
4849 &blob.data, &blob.length);
4850 if (NT_STATUS_IS_OK(status)) {
4851 dbuf.dptr = (unsigned char *)blob.data;
4852 dbuf.dsize = blob.length;
4853 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
4854 talloc_free(blob.data);
4857 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4858 this security descriptor has been created when winbindd was
4859 down. Take ownership of security descriptor. */
4861 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
4862 struct dom_sid owner_sid;
4864 /* Change sd owner to workgroup administrator */
4866 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4867 struct sec_desc_buf *new_secdesc_ctr = NULL;
4868 struct security_descriptor *psd = NULL;
4873 sid_append_rid(&owner_sid, DOMAIN_RID_ADMINISTRATOR);
4875 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
4877 (*secdesc_ctr)->sd->group_sid,
4878 (*secdesc_ctr)->sd->sacl,
4879 (*secdesc_ctr)->sd->dacl,
4886 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4887 if (!new_secdesc_ctr) {
4891 /* Swap with other one */
4893 *secdesc_ctr = new_secdesc_ctr;
4897 nt_printing_setsec(sharename, *secdesc_ctr);
4901 if (DEBUGLEVEL >= 10) {
4902 struct security_acl *the_acl = (*secdesc_ctr)->sd->dacl;
4905 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4906 sharename, the_acl->num_aces));
4908 for (i = 0; i < the_acl->num_aces; i++) {
4909 DEBUG(10, ("%s %d %d 0x%08x\n",
4910 sid_string_dbg(&the_acl->aces[i].trustee),
4911 the_acl->aces[i].type, the_acl->aces[i].flags,
4912 the_acl->aces[i].access_mask));
4921 1: level not implemented
4922 2: file doesn't exist
4923 3: can't allocate memory
4924 4: can't free memory
4925 5: non existant struct
4929 A printer and a printer driver are 2 different things.
4930 NT manages them separatelly, Samba does the same.
4931 Why ? Simply because it's easier and it makes sense !
4933 Now explanation: You have 3 printers behind your samba server,
4934 2 of them are the same make and model (laser A and B). But laser B
4935 has an 3000 sheet feeder and laser A doesn't such an option.
4936 Your third printer is an old dot-matrix model for the accounting :-).
4938 If the /usr/local/samba/lib directory (default dir), you will have
4939 5 files to describe all of this.
4941 3 files for the printers (1 by printer):
4944 NTprinter_accounting
4945 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4946 NTdriver_printer model X
4947 NTdriver_printer model Y
4949 jfm: I should use this comment for the text file to explain
4950 same thing for the forms BTW.
4951 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4955 /* Convert generic access rights to printer object specific access rights.
4956 It turns out that NT4 security descriptors use generic access rights and
4957 NT5 the object specific ones. */
4959 void map_printer_permissions(struct security_descriptor *sd)
4963 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4964 se_map_generic(&sd->dacl->aces[i].access_mask,
4965 &printer_generic_mapping);
4969 void map_job_permissions(struct security_descriptor *sd)
4973 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4974 se_map_generic(&sd->dacl->aces[i].access_mask,
4975 &job_generic_mapping);
4980 /****************************************************************************
4981 Check a user has permissions to perform the given operation. We use the
4982 permission constants defined in include/rpc_spoolss.h to check the various
4983 actions we perform when checking printer access.
4985 PRINTER_ACCESS_ADMINISTER:
4986 print_queue_pause, print_queue_resume, update_printer_sec,
4987 update_printer, spoolss_addprinterex_level_2,
4988 _spoolss_setprinterdata
4993 JOB_ACCESS_ADMINISTER:
4994 print_job_delete, print_job_pause, print_job_resume,
4997 Try access control in the following order (for performance reasons):
4998 1) root and SE_PRINT_OPERATOR can do anything (easy check)
4999 2) check security descriptor (bit comparisons in memory)
5000 3) "printer admins" (may result in numerous calls to winbind)
5002 ****************************************************************************/
5003 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5006 struct spoolss_security_descriptor *secdesc = NULL;
5007 uint32 access_granted;
5012 TALLOC_CTX *mem_ctx = NULL;
5013 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5015 /* If user is NULL then use the current_user structure */
5017 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5019 if (server_info->utok.uid == sec_initial_uid()
5020 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5024 /* Get printer name */
5026 pname = lp_printername(snum);
5028 if (!pname || !*pname) {
5033 /* Get printer security descriptor */
5035 if(!(mem_ctx = talloc_init("print_access_check"))) {
5040 result = winreg_get_printer_secdesc(mem_ctx,
5044 if (!W_ERROR_IS_OK(result)) {
5045 talloc_destroy(mem_ctx);
5050 if (access_type == JOB_ACCESS_ADMINISTER) {
5051 struct spoolss_security_descriptor *parent_secdesc = secdesc;
5053 /* Create a child security descriptor to check permissions
5054 against. This is because print jobs are child objects
5055 objects of a printer. */
5056 status = se_create_child_secdesc(mem_ctx,
5060 parent_secdesc->owner_sid,
5061 parent_secdesc->group_sid,
5063 if (!NT_STATUS_IS_OK(status)) {
5064 talloc_destroy(mem_ctx);
5065 errno = map_errno_from_nt_status(status);
5069 map_job_permissions(secdesc);
5071 map_printer_permissions(secdesc);
5075 status = se_access_check(secdesc, server_info->ptok, access_type,
5078 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5080 /* see if we need to try the printer admin list */
5082 if (!NT_STATUS_IS_OK(status) &&
5083 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5084 server_info->info3->base.domain.string,
5085 NULL, server_info->ptok,
5086 lp_printer_admin(snum)))) {
5087 talloc_destroy(mem_ctx);
5091 talloc_destroy(mem_ctx);
5093 if (!NT_STATUS_IS_OK(status)) {
5097 return NT_STATUS_IS_OK(status);
5100 /****************************************************************************
5101 Check the time parameters allow a print operation.
5102 *****************************************************************************/
5104 bool print_time_access_check(struct auth_serversupplied_info *server_info,
5105 const char *servicename)
5107 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5110 time_t now = time(NULL);
5114 result = winreg_get_printer(NULL, server_info,
5115 NULL, servicename, &pinfo2);
5116 if (!W_ERROR_IS_OK(result)) {
5120 if (pinfo2->starttime == 0 && pinfo2->untiltime == 0) {
5125 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5127 if (mins >= pinfo2->starttime && mins <= pinfo2->untiltime) {
5131 TALLOC_FREE(pinfo2);
5140 /****************************************************************************
5141 Fill in the servername sent in the _spoolss_open_printer_ex() call
5142 ****************************************************************************/
5144 char* get_server_name( Printer_entry *printer )
5146 return printer->servername;