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 Create and allocate a default devicemode.
2054 ****************************************************************************/
2056 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
2057 const char *devicename
,
2058 struct spoolss_DeviceMode
**devmode
)
2060 struct spoolss_DeviceMode
*dm
;
2063 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
2068 dname
= talloc_asprintf(dm
, "%s", devicename
);
2069 if (dname
== NULL
) {
2072 if (strlen(dname
) > MAXDEVICENAME
) {
2073 dname
[MAXDEVICENAME
] = '\0';
2075 dm
->devicename
= dname
;
2077 dm
->formname
= talloc_strdup(dm
, "Letter");
2078 if (dm
->formname
== NULL
) {
2082 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2083 dm
->driverversion
= 0x0400;
2085 dm
->__driverextra_length
= 0;
2086 dm
->fields
= DEVMODE_FORMNAME
|
2088 DEVMODE_PRINTQUALITY
|
2089 DEVMODE_DEFAULTSOURCE
|
2093 DEVMODE_ORIENTATION
;
2094 dm
->orientation
= DMORIENT_PORTRAIT
;
2095 dm
->papersize
= DMPAPER_LETTER
;
2096 dm
->paperlength
= 0;
2100 dm
->defaultsource
= DMBIN_FORMSOURCE
;
2101 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
2102 dm
->color
= DMRES_MONOCHROME
;
2103 dm
->duplex
= DMDUP_SIMPLEX
;
2104 dm
->yresolution
= 0;
2105 dm
->ttoption
= DMTT_SUBDEV
;
2106 dm
->collate
= DMCOLLATE_FALSE
;
2116 dm
->displayflags
= 0;
2117 dm
->displayfrequency
= 0;
2120 dm
->panningwidth
= 0;
2121 dm
->panningheight
= 0;
2123 dm
->driverextra_data
.data
= NULL
;
2124 dm
->driverextra_data
.length
= 0;
2130 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
2131 struct spoolss_security_descriptor
**secdesc
)
2133 struct security_ace ace
[7]; /* max number of ace entries */
2136 struct security_acl
*psa
= NULL
;
2137 struct security_descriptor
*psd
= NULL
;
2138 struct dom_sid adm_sid
;
2141 /* Create an ACE where Everyone is allowed to print */
2143 sa
= PRINTER_ACE_PRINT
;
2144 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2145 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2147 /* Add the domain admins group if we are a DC */
2150 struct dom_sid domadmins_sid
;
2152 sid_compose(&domadmins_sid
, get_global_sam_sid(),
2155 sa
= PRINTER_ACE_FULL_CONTROL
;
2156 init_sec_ace(&ace
[i
++], &domadmins_sid
,
2157 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2158 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2159 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2160 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2162 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
2163 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
2165 sa
= PRINTER_ACE_FULL_CONTROL
;
2166 init_sec_ace(&ace
[i
++], &adm_sid
,
2167 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2168 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2169 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2170 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2173 /* add BUILTIN\Administrators as FULL CONTROL */
2175 sa
= PRINTER_ACE_FULL_CONTROL
;
2176 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2177 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2178 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2179 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2180 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2181 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2183 /* add BUILTIN\Print Operators as FULL CONTROL */
2185 sa
= PRINTER_ACE_FULL_CONTROL
;
2186 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
2187 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2188 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2189 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
2190 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2191 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2193 /* Make the security descriptor owned by the BUILTIN\Administrators */
2195 /* The ACL revision number in rpc_secdesc.h differs from the one
2196 created by NT when setting ACE entries in printer
2197 descriptors. NT4 complains about the property being edited by a
2200 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
2201 psd
= make_sec_desc(mem_ctx
,
2203 SEC_DESC_SELF_RELATIVE
,
2204 &global_sid_Builtin_Administrators
,
2205 &global_sid_Builtin_Administrators
,
2212 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2216 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2217 (unsigned int)sd_size
));
2224 /****************************************************************************
2225 Allocate and initialize a new slot.
2226 ***************************************************************************/
2228 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2234 if ( !name
|| !data
)
2237 /* allocate another slot in the NT_PRINTER_KEY array */
2239 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2240 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2246 key_index
= data
->num_keys
;
2248 /* initialze new key */
2250 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2252 werr
= regval_ctr_init(data
, &(data
->keys
[key_index
].values
));
2253 if (!W_ERROR_IS_OK(werr
)) {
2259 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2264 /****************************************************************************
2265 search for a registry key name in the existing printer data
2266 ***************************************************************************/
2268 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2272 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2273 if ( strequal( data
->keys
[i
].name
, name
) ) {
2275 /* cleanup memory */
2277 TALLOC_FREE( data
->keys
[i
].name
);
2278 TALLOC_FREE( data
->keys
[i
].values
);
2280 /* if not the end of the array, move remaining elements down one slot */
2283 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2284 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2291 return data
->num_keys
;
2294 /****************************************************************************
2295 search for a registry key name in the existing printer data
2296 ***************************************************************************/
2298 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2303 if ( !data
|| !name
)
2306 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2308 /* loop over all existing keys */
2310 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2311 if ( strequal(data
->keys
[i
].name
, name
) ) {
2312 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2322 /****************************************************************************
2323 ***************************************************************************/
2325 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2329 int num_subkeys
= 0;
2331 fstring
*subkeys_ptr
= NULL
;
2342 /* special case of asking for the top level printer data registry key names */
2344 if ( strlen(key
) == 0 ) {
2345 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2347 /* found a match, so allocate space and copy the name */
2349 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2350 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2355 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2362 /* asking for the subkeys of some key */
2363 /* subkey paths are stored in the key name using '\' as the delimiter */
2365 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2366 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2368 /* if we found the exact key, then break */
2369 key_len
= strlen( key
);
2370 if ( strlen(data
->keys
[i
].name
) == key_len
)
2373 /* get subkey path */
2375 p
= data
->keys
[i
].name
+ key_len
;
2378 fstrcpy( subkeyname
, p
);
2379 if ( (p
= strchr( subkeyname
, '\\' )) )
2382 /* don't add a key more than once */
2384 for ( j
=0; j
<num_subkeys
; j
++ ) {
2385 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2389 if ( j
!= num_subkeys
)
2392 /* found a match, so allocate space and copy the name */
2394 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2395 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2400 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2406 /* return error if the key was not found */
2408 if ( i
== data
->num_keys
) {
2409 SAFE_FREE(subkeys_ptr
);
2414 /* tag off the end */
2417 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2419 *subkeys
= subkeys_ptr
;
2425 static void map_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2428 regval_ctr_delvalue(ctr
, val_name
);
2429 regval_ctr_addvalue_sz(ctr
, val_name
, sz
);
2432 static void map_dword_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2435 regval_ctr_delvalue(ctr
, val_name
);
2436 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2437 (uint8
*) &dword
, sizeof(dword
));
2440 static void map_bool_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2443 uint8 bin_bool
= (b
? 1 : 0);
2444 regval_ctr_delvalue(ctr
, val_name
);
2445 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2446 (uint8
*) &bin_bool
, sizeof(bin_bool
));
2449 static void map_single_multi_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2450 const char *multi_sz
)
2457 regval_ctr_delvalue(ctr
, val_name
);
2458 regval_ctr_addvalue_multi_sz(ctr
, val_name
, a
);
2461 /****************************************************************************
2462 * Map spoolss_PrinterInfo2 data into DsSpooler keys for publishing.
2464 * @param mem_ctx allocation context
2465 * @param info2 spoolss_PrinterInfo2 describing printer
2466 * @param pdata the talloced printer data
2467 * @return bool indicating success or failure
2468 ***************************************************************************/
2470 static bool map_nt_printer_info2_to_dsspooler(TALLOC_CTX
*mem_ctx
,
2471 struct spoolss_PrinterInfo2
*info2
,
2472 NT_PRINTER_DATA
**pdata
)
2474 NT_PRINTER_DATA
*data
;
2475 struct regval_ctr
*ctr
= NULL
;
2477 const char *dnssuffix
;
2478 char *allocated_string
= NULL
;
2479 const char *ascii_str
;
2482 data
= talloc_zero(mem_ctx
, NT_PRINTER_DATA
);
2483 if (!data
) return false;
2486 i
= add_new_printer_key(data
, SPOOL_DSSPOOLER_KEY
);
2487 ctr
= data
->keys
[i
].values
;
2489 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2490 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2492 /* we make the assumption that the netbios name is the same
2493 as the DNS name sinc ethe former will be what we used to
2496 dnssuffix
= get_mydnsdomname(talloc_tos());
2497 if (dnssuffix
&& *dnssuffix
) {
2498 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2500 fstrcpy( longname
, global_myname() );
2503 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2505 if (asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
) == -1) {
2509 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2510 SAFE_FREE(allocated_string
);
2512 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2513 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2514 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2515 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2516 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2517 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2518 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2519 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2520 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2522 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2523 (info2
->attributes
&
2524 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2526 switch (info2
->attributes
& 0x3) {
2528 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2531 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2534 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2537 ascii_str
= "unknown";
2539 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2545 /*****************************************************************
2546 ****************************************************************/
2548 static void store_printer_guid(const char *printer
, struct GUID guid
)
2550 TALLOC_CTX
*tmp_ctx
;
2551 struct auth_serversupplied_info
*server_info
= NULL
;
2552 const char *guid_str
;
2557 tmp_ctx
= talloc_new(NULL
);
2559 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2563 status
= make_server_info_system(tmp_ctx
, &server_info
);
2564 if (!NT_STATUS_IS_OK(status
)) {
2565 DEBUG(0, ("store_printer_guid: "
2566 "Could not create system server_info\n"));
2570 guid_str
= GUID_string(tmp_ctx
, &guid
);
2572 DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
2576 /* We used to store this as a REG_BINARY but that causes
2579 if (!push_reg_sz(tmp_ctx
, &blob
, guid_str
)) {
2580 DEBUG(0, ("store_printer_guid: "
2581 "Could not marshall string %s for objectGUID\n",
2586 result
= winreg_set_printer_dataex(tmp_ctx
, server_info
, printer
,
2587 SPOOL_DSSPOOLER_KEY
, "objectGUID",
2588 REG_SZ
, blob
.data
, blob
.length
);
2589 if (!W_ERROR_IS_OK(result
)) {
2590 DEBUG(0, ("store_printer_guid: "
2591 "Failed to store GUID for printer %s\n", printer
));
2595 talloc_free(tmp_ctx
);
2598 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2599 struct spoolss_PrinterInfo2
*pinfo2
)
2603 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
, *srv_cn_escaped
, *sharename_escaped
;
2604 char *srv_dn_utf8
, **srv_cn_utf8
;
2607 const char *attrs
[] = {"objectGUID", NULL
};
2609 WERROR win_rc
= WERR_OK
;
2610 size_t converted_size
;
2611 NT_PRINTER_DATA
*pdata
;
2612 const char *printer
= pinfo2
->sharename
;
2614 /* build the ads mods */
2615 ctx
= talloc_init("nt_printer_publish_ads");
2620 DEBUG(5, ("publishing printer %s\n", printer
));
2622 if (!map_nt_printer_info2_to_dsspooler(ctx
, pinfo2
, &pdata
)) {
2624 return WERR_SERVER_UNAVAILABLE
;
2627 /* figure out where to publish */
2628 ads_find_machine_acct(ads
, &res
, global_myname());
2630 /* We use ldap_get_dn here as we need the answer
2631 * in utf8 to call ldap_explode_dn(). JRA. */
2633 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
2636 return WERR_SERVER_UNAVAILABLE
;
2638 ads_msgfree(ads
, res
);
2639 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2642 ldap_memfree(srv_dn_utf8
);
2643 return WERR_SERVER_UNAVAILABLE
;
2645 /* Now convert to CH_UNIX. */
2646 if (!pull_utf8_talloc(ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
)) {
2648 ldap_memfree(srv_dn_utf8
);
2649 ldap_memfree(srv_cn_utf8
);
2650 return WERR_SERVER_UNAVAILABLE
;
2652 if (!pull_utf8_talloc(ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
)) {
2654 ldap_memfree(srv_dn_utf8
);
2655 ldap_memfree(srv_cn_utf8
);
2656 TALLOC_FREE(srv_dn
);
2657 return WERR_SERVER_UNAVAILABLE
;
2660 ldap_memfree(srv_dn_utf8
);
2661 ldap_memfree(srv_cn_utf8
);
2663 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
2664 if (!srv_cn_escaped
) {
2666 return WERR_SERVER_UNAVAILABLE
;
2668 sharename_escaped
= escape_rdn_val_string_alloc(printer
);
2669 if (!sharename_escaped
) {
2670 SAFE_FREE(srv_cn_escaped
);
2672 return WERR_SERVER_UNAVAILABLE
;
2675 prt_dn
= talloc_asprintf(ctx
, "cn=%s-%s,%s", srv_cn_escaped
, sharename_escaped
, srv_dn
);
2677 SAFE_FREE(srv_cn_escaped
);
2678 SAFE_FREE(sharename_escaped
);
2680 mods
= ads_init_mods(ctx
);
2688 get_local_printer_publishing_data(ctx
, &mods
, pdata
);
2689 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
, printer
);
2692 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2693 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
2695 for (i
=0; mods
[i
] != 0; i
++)
2697 mods
[i
] = (LDAPMod
*)-1;
2698 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
2701 if (!ADS_ERR_OK(ads_rc
)) {
2702 DEBUG(3, ("error publishing %s: %s\n",
2703 printer
, ads_errstr(ads_rc
)));
2706 /* retreive the guid and store it locally */
2707 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
2709 ads_pull_guid(ads
, res
, &guid
);
2710 ads_msgfree(ads
, res
);
2711 store_printer_guid(printer
, guid
);
2718 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
2719 const char *printer
)
2722 LDAPMessage
*res
= NULL
;
2723 char *prt_dn
= NULL
;
2725 DEBUG(5, ("unpublishing printer %s\n", printer
));
2727 /* remove the printer from the directory */
2728 ads_rc
= ads_find_printer_on_server(ads
, &res
,
2729 printer
, global_myname());
2731 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
2732 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
2734 ads_msgfree(ads
, res
);
2737 ads_rc
= ads_del_dn(ads
, prt_dn
);
2738 TALLOC_FREE(prt_dn
);
2742 ads_msgfree(ads
, res
);
2747 /****************************************************************************
2748 * Publish a printer in the directory
2750 * @param mem_ctx memory context
2751 * @param server_info server_info to access winreg pipe
2752 * @param pinfo2 printer information
2753 * @param action publish/unpublish action
2754 * @return WERROR indicating status of publishing
2755 ***************************************************************************/
2757 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
2758 struct auth_serversupplied_info
*server_info
,
2759 struct spoolss_PrinterInfo2
*pinfo2
,
2762 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ATTRIBUTES
;
2763 struct spoolss_SetPrinterInfo2
*sinfo2
;
2765 ADS_STRUCT
*ads
= NULL
;
2768 sinfo2
= talloc_zero(mem_ctx
, struct spoolss_SetPrinterInfo2
);
2774 case DSPRINT_PUBLISH
:
2775 case DSPRINT_UPDATE
:
2776 pinfo2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
2778 case DSPRINT_UNPUBLISH
:
2779 pinfo2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
2782 win_rc
= WERR_NOT_SUPPORTED
;
2786 sinfo2
->attributes
= pinfo2
->attributes
;
2788 win_rc
= winreg_update_printer(mem_ctx
, server_info
,
2789 pinfo2
->sharename
, info2_mask
,
2790 sinfo2
, NULL
, NULL
);
2791 if (!W_ERROR_IS_OK(win_rc
)) {
2792 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
2796 TALLOC_FREE(sinfo2
);
2798 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
2800 DEBUG(3, ("ads_init() failed\n"));
2801 win_rc
= WERR_SERVER_UNAVAILABLE
;
2804 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2805 SAFE_FREE(ads
->auth
.password
);
2806 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2809 /* ads_connect() will find the DC for us */
2810 ads_rc
= ads_connect(ads
);
2811 if (!ADS_ERR_OK(ads_rc
)) {
2812 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2813 win_rc
= WERR_ACCESS_DENIED
;
2818 case DSPRINT_PUBLISH
:
2819 case DSPRINT_UPDATE
:
2820 win_rc
= nt_printer_publish_ads(ads
, pinfo2
);
2822 case DSPRINT_UNPUBLISH
:
2823 win_rc
= nt_printer_unpublish_ads(ads
, pinfo2
->sharename
);
2832 WERROR
check_published_printers(void)
2835 ADS_STRUCT
*ads
= NULL
;
2837 int n_services
= lp_numservices();
2838 TALLOC_CTX
*tmp_ctx
= NULL
;
2839 struct auth_serversupplied_info
*server_info
= NULL
;
2840 struct spoolss_PrinterInfo2
*pinfo2
;
2844 tmp_ctx
= talloc_new(NULL
);
2845 if (!tmp_ctx
) return WERR_NOMEM
;
2847 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
2849 DEBUG(3, ("ads_init() failed\n"));
2850 return WERR_SERVER_UNAVAILABLE
;
2852 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
2853 SAFE_FREE(ads
->auth
.password
);
2854 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
2857 /* ads_connect() will find the DC for us */
2858 ads_rc
= ads_connect(ads
);
2859 if (!ADS_ERR_OK(ads_rc
)) {
2860 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
2861 result
= WERR_ACCESS_DENIED
;
2865 status
= make_server_info_system(tmp_ctx
, &server_info
);
2866 if (!NT_STATUS_IS_OK(status
)) {
2867 DEBUG(0, ("check_published_printers: "
2868 "Could not create system server_info\n"));
2869 result
= WERR_ACCESS_DENIED
;
2873 for (snum
= 0; snum
< n_services
; snum
++) {
2874 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
2878 result
= winreg_get_printer(tmp_ctx
, server_info
, NULL
,
2879 lp_servicename(snum
), &pinfo2
);
2880 if (!W_ERROR_IS_OK(result
)) {
2884 if (pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
2885 nt_printer_publish_ads(ads
, pinfo2
);
2888 TALLOC_FREE(pinfo2
);
2894 ads_kdestroy("MEMORY:prtpub_cache");
2895 talloc_free(tmp_ctx
);
2899 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
2900 struct auth_serversupplied_info
*server_info
,
2901 char *servername
, char *printer
, struct GUID
*guid
,
2902 struct spoolss_PrinterInfo2
**info2
)
2904 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
2905 enum winreg_Type type
;
2911 result
= winreg_get_printer(mem_ctx
, server_info
,
2912 servername
, printer
, &pinfo2
);
2913 if (!W_ERROR_IS_OK(result
)) {
2917 if (!(pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
)) {
2918 TALLOC_FREE(pinfo2
);
2926 /* fetching printer guids really ought to be a separate function. */
2928 result
= winreg_get_printer_dataex(mem_ctx
, server_info
, printer
,
2929 SPOOL_DSSPOOLER_KEY
, "objectGUID",
2930 &type
, &data
, &data_size
);
2931 if (!W_ERROR_IS_OK(result
)) {
2932 TALLOC_FREE(pinfo2
);
2936 /* We used to store the guid as REG_BINARY, then swapped
2937 to REG_SZ for Vista compatibility so check for both */
2941 status
= GUID_from_string((char *)data
, guid
);
2942 if (!NT_STATUS_IS_OK(status
)) {
2943 TALLOC_FREE(pinfo2
);
2949 if (data_size
!= sizeof(struct GUID
)) {
2950 TALLOC_FREE(pinfo2
);
2953 memcpy(guid
, data
, sizeof(struct GUID
));
2956 DEBUG(0,("is_printer_published: GUID value stored as "
2957 "invaluid type (%d)\n", type
));
2963 *info2
= talloc_move(mem_ctx
, &pinfo2
);
2965 talloc_free(pinfo2
);
2969 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
2970 struct auth_serversupplied_info
*server_info
,
2971 struct spoolss_PrinterInfo2
*pinfo2
,
2977 WERROR
check_published_printers(void)
2982 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
2983 struct auth_serversupplied_info
*server_info
,
2984 char *servername
, char *printer
, struct GUID
*guid
,
2985 struct spoolss_PrinterInfo2
**info2
)
2989 #endif /* HAVE_ADS */
2991 /****************************************************************************
2992 ***************************************************************************/
2994 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
2996 NT_PRINTER_DATA
*data
;
2998 int removed_keys
= 0;
3002 empty_slot
= data
->num_keys
;
3005 return WERR_INVALID_PARAM
;
3007 /* remove all keys */
3009 if ( !strlen(key
) ) {
3011 TALLOC_FREE( data
);
3015 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3021 /* remove a specific key (and all subkeys) */
3023 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3024 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3025 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3026 data
->keys
[i
].name
));
3028 TALLOC_FREE( data
->keys
[i
].name
);
3029 TALLOC_FREE( data
->keys
[i
].values
);
3031 /* mark the slot as empty */
3033 ZERO_STRUCTP( &data
->keys
[i
] );
3037 /* find the first empty slot */
3039 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3040 if ( !data
->keys
[i
].name
) {
3047 if ( i
== data
->num_keys
)
3048 /* nothing was removed */
3049 return WERR_INVALID_PARAM
;
3051 /* move everything down */
3053 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3054 if ( data
->keys
[i
].name
) {
3055 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3056 ZERO_STRUCTP( &data
->keys
[i
] );
3064 data
->num_keys
-= removed_keys
;
3066 /* sanity check to see if anything is left */
3068 if ( !data
->num_keys
) {
3069 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3071 SAFE_FREE( data
->keys
);
3072 ZERO_STRUCTP( data
);
3078 /****************************************************************************
3079 ***************************************************************************/
3081 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3083 WERROR result
= WERR_OK
;
3086 /* we must have names on non-zero length */
3088 if ( !key
|| !*key
|| !value
|| !*value
)
3089 return WERR_INVALID_NAME
;
3091 /* find the printer key first */
3093 key_index
= lookup_printerkey( p2
->data
, key
);
3094 if ( key_index
== -1 )
3097 /* make sure the value exists so we can return the correct error code */
3099 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3100 return WERR_BADFILE
;
3102 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3104 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3110 /****************************************************************************
3111 ***************************************************************************/
3113 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3114 uint32 type
, uint8
*data
, int real_len
)
3116 WERROR result
= WERR_OK
;
3119 /* we must have names on non-zero length */
3121 if ( !key
|| !*key
|| !value
|| !*value
)
3122 return WERR_INVALID_NAME
;
3124 /* find the printer key first */
3126 key_index
= lookup_printerkey( p2
->data
, key
);
3127 if ( key_index
== -1 )
3128 key_index
= add_new_printer_key( p2
->data
, key
);
3130 if ( key_index
== -1 )
3133 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3134 type
, data
, real_len
);
3136 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3137 key
, value
, type
, real_len
));
3142 /****************************************************************************
3143 ***************************************************************************/
3145 struct regval_blob
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3149 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3152 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3155 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3158 /****************************************************************************
3159 ***************************************************************************/
3161 static char *win_driver
;
3162 static char *os2_driver
;
3164 static const char *get_win_driver(void)
3166 if (win_driver
== NULL
) {
3172 static const char *get_os2_driver(void)
3174 if (os2_driver
== NULL
) {
3180 static bool set_driver_mapping(const char *from
, const char *to
)
3182 SAFE_FREE(win_driver
);
3183 SAFE_FREE(os2_driver
);
3185 win_driver
= SMB_STRDUP(from
);
3186 os2_driver
= SMB_STRDUP(to
);
3188 if (win_driver
== NULL
|| os2_driver
== NULL
) {
3189 SAFE_FREE(win_driver
);
3190 SAFE_FREE(os2_driver
);
3199 * @brief Map a Windows driver to a OS/2 driver.
3201 * @param[in] mem_ctx The memory context to use.
3203 * @param[in,out] pdrivername The drivername of Windows to remap.
3205 * @return WERR_OK on success, a corresponding WERROR on failure.
3207 WERROR
spoolss_map_to_os2_driver(TALLOC_CTX
*mem_ctx
, const char **pdrivername
)
3209 const char *mapfile
= lp_os2_driver_map();
3210 char **lines
= NULL
;
3211 const char *drivername
;
3215 if (pdrivername
== NULL
|| *pdrivername
== NULL
|| *pdrivername
[0] == '\0') {
3216 return WERR_INVALID_PARAMETER
;
3219 drivername
= *pdrivername
;
3221 if (mapfile
[0] == '\0') {
3222 return WERR_BADFILE
;
3225 if (strequal(drivername
, get_win_driver())) {
3226 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3227 drivername
, get_os2_driver()));
3228 drivername
= talloc_strdup(mem_ctx
, get_os2_driver());
3229 if (drivername
== NULL
) {
3232 *pdrivername
= drivername
;
3236 lines
= file_lines_load(mapfile
, &numlines
, 0, NULL
);
3237 if (numlines
== 0 || lines
== NULL
) {
3238 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile
));
3243 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3245 for( i
= 0; i
< numlines
; i
++) {
3246 char *nt_name
= lines
[i
];
3247 char *os2_name
= strchr(nt_name
, '=');
3249 if (os2_name
== NULL
) {
3255 while (isspace(*nt_name
)) {
3259 if (*nt_name
== '\0' || strchr("#;", *nt_name
)) {
3264 int l
= strlen(nt_name
);
3265 while (l
&& isspace(nt_name
[l
- 1])) {
3271 while (isspace(*os2_name
)) {
3276 int l
= strlen(os2_name
);
3277 while (l
&& isspace(os2_name
[l
-1])) {
3283 if (strequal(nt_name
, drivername
)) {
3284 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,os2_name
));
3285 set_driver_mapping(drivername
, os2_name
);
3286 drivername
= talloc_strdup(mem_ctx
, os2_name
);
3288 if (drivername
== NULL
) {
3291 *pdrivername
= drivername
;
3300 /****************************************************************************
3301 Deletes a NT_PRINTER_INFO_LEVEL struct.
3302 ****************************************************************************/
3304 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
3306 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
3313 TALLOC_FREE(printer
->info_2
);
3317 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
3321 TALLOC_FREE(*pp_printer
);
3326 /****************************************************************************
3327 ****************************************************************************/
3329 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
3330 struct spoolss_DriverInfo8
*_info8
)
3332 struct spoolss_DriverInfo8 info8
;
3338 info8
.version
= r
->info
.info3
->version
;
3339 info8
.driver_name
= r
->info
.info3
->driver_name
;
3340 info8
.architecture
= r
->info
.info3
->architecture
;
3341 info8
.driver_path
= r
->info
.info3
->driver_path
;
3342 info8
.data_file
= r
->info
.info3
->data_file
;
3343 info8
.config_file
= r
->info
.info3
->config_file
;
3344 info8
.help_file
= r
->info
.info3
->help_file
;
3345 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
3346 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
3347 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
3348 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
3352 info8
.version
= r
->info
.info6
->version
;
3353 info8
.driver_name
= r
->info
.info6
->driver_name
;
3354 info8
.architecture
= r
->info
.info6
->architecture
;
3355 info8
.driver_path
= r
->info
.info6
->driver_path
;
3356 info8
.data_file
= r
->info
.info6
->data_file
;
3357 info8
.config_file
= r
->info
.info6
->config_file
;
3358 info8
.help_file
= r
->info
.info6
->help_file
;
3359 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
3360 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
3361 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
3362 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
3364 info8
.driver_date
= r
->info
.info6
->driver_date
;
3365 info8
.driver_version
= r
->info
.info6
->driver_version
;
3366 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
3367 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
3368 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
3369 info8
.provider
= r
->info
.info6
->provider
;
3372 info8
.version
= r
->info
.info8
->version
;
3373 info8
.driver_name
= r
->info
.info8
->driver_name
;
3374 info8
.architecture
= r
->info
.info8
->architecture
;
3375 info8
.driver_path
= r
->info
.info8
->driver_path
;
3376 info8
.data_file
= r
->info
.info8
->data_file
;
3377 info8
.config_file
= r
->info
.info8
->config_file
;
3378 info8
.help_file
= r
->info
.info8
->help_file
;
3379 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
3380 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
3381 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
3382 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
3384 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
3385 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
3387 info8
.driver_date
= r
->info
.info8
->driver_date
;
3388 info8
.driver_version
= r
->info
.info8
->driver_version
;
3389 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
3390 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
3391 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
3392 info8
.provider
= r
->info
.info8
->provider
;
3393 info8
.print_processor
= r
->info
.info8
->print_processor
;
3394 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
3395 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
3396 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
3398 info8
.inf_path
= r
->info
.info8
->inf_path
;
3399 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
3400 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
3401 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
3403 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
3404 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
3416 /****************************************************************************
3417 Determine whether or not a particular driver is currently assigned
3419 ****************************************************************************/
3421 bool printer_driver_in_use(TALLOC_CTX
*mem_ctx
,
3422 struct auth_serversupplied_info
*server_info
,
3423 const struct spoolss_DriverInfo8
*r
)
3426 int n_services
= lp_numservices();
3427 bool in_use
= False
;
3428 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3435 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3437 /* loop through the printers.tdb and check for the drivername */
3439 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
3440 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
3444 result
= winreg_get_printer(mem_ctx
, server_info
, NULL
,
3445 lp_servicename(snum
), &pinfo2
);
3446 if (!W_ERROR_IS_OK(result
)) {
3447 continue; /* skip */
3450 if (strequal(r
->driver_name
, pinfo2
->drivername
)) {
3454 TALLOC_FREE(pinfo2
);
3457 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3460 struct spoolss_DriverInfo8
*driver
;
3463 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
3465 /* we can still remove the driver if there is one of
3466 "Windows NT x86" version 2 or 3 left */
3468 if (!strequal("Windows NT x86", r
->architecture
)) {
3469 werr
= winreg_get_driver(mem_ctx
, server_info
,
3474 } else if (r
->version
== 2) {
3475 werr
= winreg_get_driver(mem_ctx
, server_info
,
3479 } else if (r
->version
== 3) {
3480 werr
= winreg_get_driver(mem_ctx
, server_info
,
3485 DEBUG(0, ("printer_driver_in_use: ERROR!"
3486 " unknown driver version (%d)\n",
3488 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
3491 /* now check the error code */
3493 if ( W_ERROR_IS_OK(werr
) ) {
3494 /* it's ok to remove the driver, we have other architctures left */
3496 talloc_free(driver
);
3500 /* report that the driver is not in use by default */
3506 /**********************************************************************
3507 Check to see if a ogiven file is in use by *info
3508 *********************************************************************/
3510 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
3517 /* mz: skip files that are in the list but already deleted */
3518 if (!file
|| !file
[0]) {
3522 if (strequal(file
, info
->driver_path
))
3525 if (strequal(file
, info
->data_file
))
3528 if (strequal(file
, info
->config_file
))
3531 if (strequal(file
, info
->help_file
))
3534 /* see of there are any dependent files to examine */
3536 if (!info
->dependent_files
)
3539 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
3540 if (strequal(file
, info
->dependent_files
[i
]))
3549 /**********************************************************************
3550 Utility function to remove the dependent file pointed to by the
3551 input parameter from the list
3552 *********************************************************************/
3554 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
3557 /* bump everything down a slot */
3559 while (files
&& files
[idx
+1]) {
3560 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
3569 /**********************************************************************
3570 Check if any of the files used by src are also used by drv
3571 *********************************************************************/
3573 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
3574 struct spoolss_DriverInfo8
*src
,
3575 const struct spoolss_DriverInfo8
*drv
)
3577 bool in_use
= False
;
3583 /* check each file. Remove it from the src structure if it overlaps */
3585 if (drv_file_in_use(src
->driver_path
, drv
)) {
3587 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
3588 src
->driver_path
= talloc_strdup(mem_ctx
, "");
3589 if (!src
->driver_path
) { return false; }
3592 if (drv_file_in_use(src
->data_file
, drv
)) {
3594 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
3595 src
->data_file
= talloc_strdup(mem_ctx
, "");
3596 if (!src
->data_file
) { return false; }
3599 if (drv_file_in_use(src
->config_file
, drv
)) {
3601 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
3602 src
->config_file
= talloc_strdup(mem_ctx
, "");
3603 if (!src
->config_file
) { return false; }
3606 if (drv_file_in_use(src
->help_file
, drv
)) {
3608 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
3609 src
->help_file
= talloc_strdup(mem_ctx
, "");
3610 if (!src
->help_file
) { return false; }
3613 /* are there any dependentfiles to examine? */
3615 if (!src
->dependent_files
)
3618 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
3619 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
3621 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
3622 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
3630 /****************************************************************************
3631 Determine whether or not a particular driver files are currently being
3632 used by any other driver.
3634 Return value is True if any files were in use by other drivers
3635 and False otherwise.
3637 Upon return, *info has been modified to only contain the driver files
3638 which are not in use
3642 This needs to check all drivers to ensure that all files in use
3643 have been removed from *info, not just the ones in the first
3645 ****************************************************************************/
3647 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
3648 struct auth_serversupplied_info
*server_info
,
3649 struct spoolss_DriverInfo8
*info
)
3653 struct spoolss_DriverInfo8
*driver
;
3654 bool in_use
= false;
3655 uint32_t num_drivers
;
3656 const char **drivers
;
3662 version
= info
->version
;
3664 /* loop over all driver versions */
3666 DEBUG(5,("printer_driver_files_in_use: Beginning search of drivers...\n"));
3668 /* get the list of drivers */
3670 result
= winreg_get_driver_list(mem_ctx
, server_info
,
3671 info
->architecture
, version
,
3672 &num_drivers
, &drivers
);
3673 if (!W_ERROR_IS_OK(result
)) {
3677 DEBUGADD(4, ("we have:[%d] drivers in environment [%s] and version [%d]\n",
3678 num_drivers
, info
->architecture
, version
));
3680 /* check each driver for overlap in files */
3682 for (i
= 0; i
< num_drivers
; i
++) {
3683 DEBUGADD(5,("\tdriver: [%s]\n", drivers
[i
]));
3687 result
= winreg_get_driver(mem_ctx
, server_info
,
3688 info
->architecture
, drivers
[i
],
3690 if (!W_ERROR_IS_OK(result
)) {
3691 talloc_free(drivers
);
3695 /* check if d2 uses any files from d1 */
3696 /* only if this is a different driver than the one being deleted */
3698 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
3699 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
3700 /* mz: Do not instantly return -
3701 * we need to ensure this file isn't
3702 * also in use by other drivers. */
3707 talloc_free(driver
);
3710 talloc_free(drivers
);
3712 DEBUG(5,("printer_driver_files_in_use: Completed search of drivers...\n"));
3717 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
3720 struct smb_filename
*smb_fname
= NULL
;
3723 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
3725 if (!NT_STATUS_IS_OK(status
)) {
3729 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
3731 TALLOC_FREE(smb_fname
);
3735 /****************************************************************************
3736 Actually delete the driver files. Make sure that
3737 printer_driver_files_in_use() return False before calling
3739 ****************************************************************************/
3741 bool delete_driver_files(struct auth_serversupplied_info
*server_info
,
3742 const struct spoolss_DriverInfo8
*r
)
3747 connection_struct
*conn
;
3750 fstring printdollar
;
3751 int printdollar_snum
;
3758 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
3759 r
->driver_name
, r
->version
));
3761 fstrcpy(printdollar
, "print$");
3763 printdollar_snum
= find_service(printdollar
);
3764 if (printdollar_snum
== -1) {
3768 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
3769 lp_pathname(printdollar_snum
),
3770 server_info
, &oldcwd
);
3771 if (!NT_STATUS_IS_OK(nt_status
)) {
3772 DEBUG(0,("delete_driver_files: create_conn_struct "
3773 "returned %s\n", nt_errstr(nt_status
)));
3777 if ( !CAN_WRITE(conn
) ) {
3778 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
3782 /* now delete the files; must strip the '\print$' string from
3785 if (r
->driver_path
&& r
->driver_path
[0]) {
3786 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
3788 DEBUG(10,("deleting driverfile [%s]\n", s
));
3789 driver_unlink_internals(conn
, file
);
3793 if (r
->config_file
&& r
->config_file
[0]) {
3794 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
3796 DEBUG(10,("deleting configfile [%s]\n", s
));
3797 driver_unlink_internals(conn
, file
);
3801 if (r
->data_file
&& r
->data_file
[0]) {
3802 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
3804 DEBUG(10,("deleting datafile [%s]\n", s
));
3805 driver_unlink_internals(conn
, file
);
3809 if (r
->help_file
&& r
->help_file
[0]) {
3810 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
3812 DEBUG(10,("deleting helpfile [%s]\n", s
));
3813 driver_unlink_internals(conn
, file
);
3817 /* check if we are done removing files */
3819 if (r
->dependent_files
) {
3820 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
3823 /* bypass the "\print$" portion of the path */
3825 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
3827 DEBUG(10,("deleting dependent file [%s]\n", file
));
3828 driver_unlink_internals(conn
, file
);
3840 vfs_ChDir(conn
, oldcwd
);
3846 /****************************************************************************
3847 Store a security desc for a printer.
3848 ****************************************************************************/
3850 WERROR
nt_printing_setsec(const char *sharename
, struct sec_desc_buf
*secdesc_ctr
)
3852 struct sec_desc_buf
*new_secdesc_ctr
= NULL
;
3853 struct sec_desc_buf
*old_secdesc_ctr
= NULL
;
3854 TALLOC_CTX
*mem_ctx
= NULL
;
3861 mem_ctx
= talloc_init("nt_printing_setsec");
3862 if (mem_ctx
== NULL
)
3865 /* The old owner and group sids of the security descriptor are not
3866 present when new ACEs are added or removed by changing printer
3867 permissions through NT. If they are NULL in the new security
3868 descriptor then copy them over from the old one. */
3870 if (!secdesc_ctr
->sd
->owner_sid
|| !secdesc_ctr
->sd
->group_sid
) {
3871 struct dom_sid
*owner_sid
, *group_sid
;
3872 struct security_acl
*dacl
, *sacl
;
3873 struct security_descriptor
*psd
= NULL
;
3876 if (!nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
)) {
3877 status
= WERR_NOMEM
;
3881 /* Pick out correct owner and group sids */
3883 owner_sid
= secdesc_ctr
->sd
->owner_sid
?
3884 secdesc_ctr
->sd
->owner_sid
:
3885 old_secdesc_ctr
->sd
->owner_sid
;
3887 group_sid
= secdesc_ctr
->sd
->group_sid
?
3888 secdesc_ctr
->sd
->group_sid
:
3889 old_secdesc_ctr
->sd
->group_sid
;
3891 dacl
= secdesc_ctr
->sd
->dacl
?
3892 secdesc_ctr
->sd
->dacl
:
3893 old_secdesc_ctr
->sd
->dacl
;
3895 sacl
= secdesc_ctr
->sd
->sacl
?
3896 secdesc_ctr
->sd
->sacl
:
3897 old_secdesc_ctr
->sd
->sacl
;
3899 /* Make a deep copy of the security descriptor */
3901 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sd
->revision
, secdesc_ctr
->sd
->type
,
3902 owner_sid
, group_sid
,
3908 status
= WERR_NOMEM
;
3912 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
3915 if (!new_secdesc_ctr
) {
3916 new_secdesc_ctr
= secdesc_ctr
;
3919 /* Store the security descriptor in a tdb */
3921 nt_status
= marshall_sec_desc_buf(mem_ctx
, new_secdesc_ctr
,
3922 &blob
.data
, &blob
.length
);
3923 if (!NT_STATUS_IS_OK(nt_status
)) {
3924 status
= ntstatus_to_werror(nt_status
);
3928 kbuf
= make_printers_secdesc_tdbkey(mem_ctx
, sharename
);
3930 dbuf
.dptr
= (unsigned char *)blob
.data
;
3931 dbuf
.dsize
= blob
.length
;
3933 if (tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
)==0) {
3936 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
3937 status
= WERR_BADFUNC
;
3940 /* Free malloc'ed memory */
3941 talloc_free(blob
.data
);
3946 talloc_destroy(mem_ctx
);
3950 /****************************************************************************
3951 Construct a default security descriptor buffer for a printer.
3952 ****************************************************************************/
3954 static struct sec_desc_buf
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
3956 struct security_ace ace
[7]; /* max number of ace entries */
3959 struct security_acl
*psa
= NULL
;
3960 struct sec_desc_buf
*sdb
= NULL
;
3961 struct security_descriptor
*psd
= NULL
;
3962 struct dom_sid adm_sid
;
3965 /* Create an ACE where Everyone is allowed to print */
3967 sa
= PRINTER_ACE_PRINT
;
3968 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
3969 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
3971 /* Add the domain admins group if we are a DC */
3974 struct dom_sid domadmins_sid
;
3976 sid_compose(&domadmins_sid
, get_global_sam_sid(),
3979 sa
= PRINTER_ACE_FULL_CONTROL
;
3980 init_sec_ace(&ace
[i
++], &domadmins_sid
,
3981 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
3982 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
3983 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
3984 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
3986 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
3987 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
3989 sa
= PRINTER_ACE_FULL_CONTROL
;
3990 init_sec_ace(&ace
[i
++], &adm_sid
,
3991 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
3992 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
3993 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
3994 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
3997 /* add BUILTIN\Administrators as FULL CONTROL */
3999 sa
= PRINTER_ACE_FULL_CONTROL
;
4000 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
4001 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
4002 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
4003 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
4004 SEC_ACE_TYPE_ACCESS_ALLOWED
,
4005 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4007 /* add BUILTIN\Print Operators as FULL CONTROL */
4009 sa
= PRINTER_ACE_FULL_CONTROL
;
4010 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
4011 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
4012 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
4013 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Print_Operators
,
4014 SEC_ACE_TYPE_ACCESS_ALLOWED
,
4015 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
4017 /* Make the security descriptor owned by the BUILTIN\Administrators */
4019 /* The ACL revision number in rpc_secdesc.h differs from the one
4020 created by NT when setting ACE entries in printer
4021 descriptors. NT4 complains about the property being edited by a
4024 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
4025 psd
= make_sec_desc(ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
4026 &global_sid_Builtin_Administrators
,
4027 &global_sid_Builtin_Administrators
,
4028 NULL
, psa
, &sd_size
);
4032 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4036 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
4038 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4039 (unsigned int)sd_size
));
4044 /****************************************************************************
4045 Get a security desc for a printer.
4046 ****************************************************************************/
4048 bool nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, struct sec_desc_buf
**secdesc_ctr
)
4056 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
4057 sharename
= temp
+ 1;
4060 /* Fetch security descriptor from tdb */
4062 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
4064 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
4067 status
= unmarshall_sec_desc_buf(ctx
, dbuf
.dptr
, dbuf
.dsize
,
4069 SAFE_FREE(dbuf
.dptr
);
4071 if (NT_STATUS_IS_OK(status
)) {
4076 *secdesc_ctr
= construct_default_printer_sdb(ctx
);
4077 if (!*secdesc_ctr
) {
4081 status
= marshall_sec_desc_buf(ctx
, *secdesc_ctr
,
4082 &blob
.data
, &blob
.length
);
4083 if (NT_STATUS_IS_OK(status
)) {
4084 dbuf
.dptr
= (unsigned char *)blob
.data
;
4085 dbuf
.dsize
= blob
.length
;
4086 tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
);
4087 talloc_free(blob
.data
);
4090 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4091 this security descriptor has been created when winbindd was
4092 down. Take ownership of security descriptor. */
4094 if (sid_equal((*secdesc_ctr
)->sd
->owner_sid
, &global_sid_World
)) {
4095 struct dom_sid owner_sid
;
4097 /* Change sd owner to workgroup administrator */
4099 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
4100 struct sec_desc_buf
*new_secdesc_ctr
= NULL
;
4101 struct security_descriptor
*psd
= NULL
;
4106 sid_append_rid(&owner_sid
, DOMAIN_RID_ADMINISTRATOR
);
4108 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sd
->revision
, (*secdesc_ctr
)->sd
->type
,
4110 (*secdesc_ctr
)->sd
->group_sid
,
4111 (*secdesc_ctr
)->sd
->sacl
,
4112 (*secdesc_ctr
)->sd
->dacl
,
4119 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
4120 if (!new_secdesc_ctr
) {
4124 /* Swap with other one */
4126 *secdesc_ctr
= new_secdesc_ctr
;
4130 nt_printing_setsec(sharename
, *secdesc_ctr
);
4134 if (DEBUGLEVEL
>= 10) {
4135 struct security_acl
*the_acl
= (*secdesc_ctr
)->sd
->dacl
;
4138 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4139 sharename
, the_acl
->num_aces
));
4141 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4142 DEBUG(10, ("%s %d %d 0x%08x\n",
4143 sid_string_dbg(&the_acl
->aces
[i
].trustee
),
4144 the_acl
->aces
[i
].type
, the_acl
->aces
[i
].flags
,
4145 the_acl
->aces
[i
].access_mask
));
4154 1: level not implemented
4155 2: file doesn't exist
4156 3: can't allocate memory
4157 4: can't free memory
4158 5: non existant struct
4162 A printer and a printer driver are 2 different things.
4163 NT manages them separatelly, Samba does the same.
4164 Why ? Simply because it's easier and it makes sense !
4166 Now explanation: You have 3 printers behind your samba server,
4167 2 of them are the same make and model (laser A and B). But laser B
4168 has an 3000 sheet feeder and laser A doesn't such an option.
4169 Your third printer is an old dot-matrix model for the accounting :-).
4171 If the /usr/local/samba/lib directory (default dir), you will have
4172 5 files to describe all of this.
4174 3 files for the printers (1 by printer):
4177 NTprinter_accounting
4178 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4179 NTdriver_printer model X
4180 NTdriver_printer model Y
4182 jfm: I should use this comment for the text file to explain
4183 same thing for the forms BTW.
4184 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4188 /* Convert generic access rights to printer object specific access rights.
4189 It turns out that NT4 security descriptors use generic access rights and
4190 NT5 the object specific ones. */
4192 void map_printer_permissions(struct security_descriptor
*sd
)
4196 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4197 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
4198 &printer_generic_mapping
);
4202 void map_job_permissions(struct security_descriptor
*sd
)
4206 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
4207 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
4208 &job_generic_mapping
);
4213 /****************************************************************************
4214 Check a user has permissions to perform the given operation. We use the
4215 permission constants defined in include/rpc_spoolss.h to check the various
4216 actions we perform when checking printer access.
4218 PRINTER_ACCESS_ADMINISTER:
4219 print_queue_pause, print_queue_resume, update_printer_sec,
4220 update_printer, spoolss_addprinterex_level_2,
4221 _spoolss_setprinterdata
4226 JOB_ACCESS_ADMINISTER:
4227 print_job_delete, print_job_pause, print_job_resume,
4230 Try access control in the following order (for performance reasons):
4231 1) root and SE_PRINT_OPERATOR can do anything (easy check)
4232 2) check security descriptor (bit comparisons in memory)
4233 3) "printer admins" (may result in numerous calls to winbind)
4235 ****************************************************************************/
4236 bool print_access_check(struct auth_serversupplied_info
*server_info
, int snum
,
4239 struct spoolss_security_descriptor
*secdesc
= NULL
;
4240 uint32 access_granted
;
4245 TALLOC_CTX
*mem_ctx
= NULL
;
4246 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
4248 /* If user is NULL then use the current_user structure */
4250 /* Always allow root or SE_PRINT_OPERATROR to do anything */
4252 if (server_info
->utok
.uid
== sec_initial_uid()
4253 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
4257 /* Get printer name */
4259 pname
= lp_printername(snum
);
4261 if (!pname
|| !*pname
) {
4266 /* Get printer security descriptor */
4268 if(!(mem_ctx
= talloc_init("print_access_check"))) {
4273 result
= winreg_get_printer_secdesc(mem_ctx
,
4277 if (!W_ERROR_IS_OK(result
)) {
4278 talloc_destroy(mem_ctx
);
4283 if (access_type
== JOB_ACCESS_ADMINISTER
) {
4284 struct spoolss_security_descriptor
*parent_secdesc
= secdesc
;
4286 /* Create a child security descriptor to check permissions
4287 against. This is because print jobs are child objects
4288 objects of a printer. */
4289 status
= se_create_child_secdesc(mem_ctx
,
4293 parent_secdesc
->owner_sid
,
4294 parent_secdesc
->group_sid
,
4296 if (!NT_STATUS_IS_OK(status
)) {
4297 talloc_destroy(mem_ctx
);
4298 errno
= map_errno_from_nt_status(status
);
4302 map_job_permissions(secdesc
);
4304 map_printer_permissions(secdesc
);
4308 status
= se_access_check(secdesc
, server_info
->ptok
, access_type
,
4311 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
4313 /* see if we need to try the printer admin list */
4315 if (!NT_STATUS_IS_OK(status
) &&
4316 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
4317 server_info
->info3
->base
.domain
.string
,
4318 NULL
, server_info
->ptok
,
4319 lp_printer_admin(snum
)))) {
4320 talloc_destroy(mem_ctx
);
4324 talloc_destroy(mem_ctx
);
4326 if (!NT_STATUS_IS_OK(status
)) {
4330 return NT_STATUS_IS_OK(status
);
4333 /****************************************************************************
4334 Check the time parameters allow a print operation.
4335 *****************************************************************************/
4337 bool print_time_access_check(struct auth_serversupplied_info
*server_info
,
4338 const char *servicename
)
4340 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
4343 time_t now
= time(NULL
);
4347 result
= winreg_get_printer(NULL
, server_info
,
4348 NULL
, servicename
, &pinfo2
);
4349 if (!W_ERROR_IS_OK(result
)) {
4353 if (pinfo2
->starttime
== 0 && pinfo2
->untiltime
== 0) {
4358 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
4360 if (mins
>= pinfo2
->starttime
&& mins
<= pinfo2
->untiltime
) {
4364 TALLOC_FREE(pinfo2
);
4373 void nt_printer_remove(TALLOC_CTX
*mem_ctx
,
4374 struct auth_serversupplied_info
*server_info
,
4375 const char *printer
)
4379 result
= winreg_delete_printer_key(mem_ctx
, server_info
, printer
, "");
4380 if (!W_ERROR_IS_OK(result
)) {
4381 DEBUG(0, ("nt_printer_remove: failed to remove rpinter %s",