Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : * Copyright (C) Andrew Tridgell 1992-2000,
5 : * Copyright (C) Jean François Micouleau 1998-2000.
6 : * Copyright (C) Gerald Carter 2002-2005.
7 : *
8 : * This program is free software; you can redistribute it and/or modify
9 : * it under the terms of the GNU General Public License as published by
10 : * the Free Software Foundation; either version 3 of the License, or
11 : * (at your option) any later version.
12 : *
13 : * This program is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : * GNU General Public License for more details.
17 : *
18 : * You should have received a copy of the GNU General Public License
19 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "../librpc/gen_ndr/spoolss.h"
24 : #include "rpc_server/spoolss/srv_spoolss_util.h"
25 : #include "nt_printing.h"
26 : #include "ads.h"
27 : #include "secrets.h"
28 : #include "../libcli/registry/util_reg.h"
29 : #include "auth.h"
30 : #include "../librpc/ndr/libndr.h"
31 : #include "rpc_client/cli_winreg_spoolss.h"
32 :
33 : #ifdef HAVE_ADS
34 : /*****************************************************************
35 : ****************************************************************/
36 :
37 0 : WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
38 : const char *printer, struct GUID guid)
39 : {
40 0 : TALLOC_CTX *tmp_ctx;
41 0 : const struct auth_session_info *session_info;
42 0 : const char *guid_str;
43 0 : DATA_BLOB blob;
44 0 : WERROR result;
45 :
46 0 : tmp_ctx = talloc_new(NULL);
47 0 : if (!tmp_ctx) {
48 0 : DEBUG(0, ("Out of memory?!\n"));
49 0 : return WERR_NOT_ENOUGH_MEMORY;
50 : }
51 :
52 0 : session_info = get_session_info_system();
53 0 : if (session_info == NULL) {
54 0 : DEBUG(0, ("Could not get system session_info\n"));
55 0 : result = WERR_NOT_ENOUGH_MEMORY;
56 0 : goto done;
57 : }
58 :
59 0 : guid_str = GUID_string(tmp_ctx, &guid);
60 0 : if (!guid_str) {
61 0 : DEBUG(0, ("Out of memory?!\n"));
62 0 : result = WERR_NOT_ENOUGH_MEMORY;
63 0 : goto done;
64 : }
65 :
66 : /* We used to store this as a REG_BINARY but that causes
67 : Vista to whine */
68 :
69 0 : if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
70 0 : DEBUG(0, ("Could not marshall string %s for objectGUID\n",
71 : guid_str));
72 0 : result = WERR_NOT_ENOUGH_MEMORY;
73 0 : goto done;
74 : }
75 :
76 0 : result = winreg_set_printer_dataex_internal(tmp_ctx, session_info, msg_ctx,
77 : printer,
78 : SPOOL_DSSPOOLER_KEY, "objectGUID",
79 0 : REG_SZ, blob.data, blob.length);
80 0 : if (!W_ERROR_IS_OK(result)) {
81 0 : DEBUG(0, ("Failed to store GUID for printer %s\n", printer));
82 0 : goto done;
83 : }
84 :
85 0 : result = WERR_OK;
86 0 : done:
87 0 : talloc_free(tmp_ctx);
88 :
89 0 : return result;
90 : }
91 :
92 0 : static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx,
93 : ADS_STRUCT *ads,
94 : const char *printer,
95 : char **pprinter_dn)
96 : {
97 0 : char *printer_dn = NULL;
98 0 : char *srv_dn = NULL;
99 0 : char *srv_cn_0 = NULL;
100 0 : char *srv_cn_escaped = NULL;
101 0 : char *sharename_escaped = NULL;
102 0 : char *srv_dn_utf8 = NULL;
103 0 : char **srv_cn_utf8 = NULL;
104 0 : size_t converted_size;
105 0 : ADS_STATUS ads_status;
106 0 : LDAPMessage *res;
107 0 : WERROR result;
108 0 : bool ok;
109 :
110 0 : ads_status = ads_find_machine_acct(ads, &res, lp_netbios_name());
111 0 : if (!ADS_ERR_OK(ads_status)) {
112 0 : DEBUG(2, ("Failed to find machine account for %s\n",
113 : lp_netbios_name()));
114 0 : result = WERR_NOT_FOUND;
115 0 : goto err_out;
116 : }
117 :
118 : /*
119 : * We use ldap_get_dn here as we need the answer in utf8 to call
120 : * ldap_explode_dn(). JRA.
121 : */
122 0 : srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
123 0 : ads_msgfree(ads, res);
124 0 : if (srv_dn_utf8 == NULL) {
125 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
126 0 : goto err_out;
127 : }
128 :
129 0 : srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
130 0 : if (srv_cn_utf8 == NULL) {
131 0 : ldap_memfree(srv_dn_utf8);
132 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
133 0 : goto err_out;
134 : }
135 :
136 : /* Now convert to CH_UNIX. */
137 0 : ok = pull_utf8_talloc(mem_ctx, &srv_dn, srv_dn_utf8, &converted_size);
138 0 : ldap_memfree(srv_dn_utf8);
139 0 : if (!ok) {
140 0 : ldap_memfree(srv_cn_utf8);
141 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
142 0 : goto err_out;
143 : }
144 :
145 0 : ok = pull_utf8_talloc(mem_ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size);
146 0 : ldap_memfree(srv_cn_utf8);
147 0 : if (!ok) {
148 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
149 0 : goto err_out;
150 : }
151 :
152 0 : srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
153 0 : if (srv_cn_escaped == NULL) {
154 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
155 0 : goto err_out;
156 : }
157 :
158 0 : sharename_escaped = escape_rdn_val_string_alloc(printer);
159 0 : if (sharename_escaped == NULL) {
160 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
161 0 : goto err_out;
162 : }
163 :
164 0 : printer_dn = talloc_asprintf(mem_ctx,
165 : "cn=%s-%s,%s",
166 : srv_cn_escaped,
167 : sharename_escaped,
168 : srv_dn);
169 0 : if (printer_dn == NULL) {
170 0 : result = WERR_NOT_ENOUGH_MEMORY;
171 0 : goto err_out;
172 : }
173 :
174 0 : *pprinter_dn = printer_dn;
175 :
176 0 : result = WERR_OK;
177 0 : err_out:
178 0 : SAFE_FREE(sharename_escaped);
179 0 : SAFE_FREE(srv_cn_escaped);
180 0 : TALLOC_FREE(srv_cn_0);
181 0 : TALLOC_FREE(srv_dn);
182 0 : return result;
183 : }
184 :
185 0 : static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads,
186 : const char *printer_dn,
187 : struct GUID *pguid)
188 : {
189 0 : ADS_STATUS ads_status;
190 0 : LDAPMessage *res;
191 0 : const char *attrs[] = {"objectGUID", NULL};
192 0 : struct GUID guid;
193 0 : bool ok;
194 :
195 0 : ads_status = ads_search_dn(ads, &res, printer_dn, attrs);
196 0 : if (!ADS_ERR_OK(ads_status)) {
197 0 : DEBUG(2, ("Failed to retrieve GUID from DC - %s\n",
198 : ads_errstr(ads_status)));
199 0 : return WERR_FILE_NOT_FOUND;
200 : }
201 :
202 0 : ZERO_STRUCT(guid);
203 0 : ok = ads_pull_guid(ads, res, &guid);
204 0 : ads_msgfree(ads, res);
205 0 : if (!ok) {
206 0 : return WERR_NOT_ENOUGH_MEMORY;
207 : }
208 :
209 0 : *pguid = guid;
210 :
211 0 : return WERR_OK;
212 : }
213 :
214 0 : WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
215 : struct GUID *pguid)
216 : {
217 0 : ADS_STRUCT *ads = NULL;
218 0 : char *printer_dn;
219 0 : WERROR result;
220 0 : ADS_STATUS ads_status;
221 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
222 :
223 0 : ads = ads_init(tmp_ctx,
224 : lp_realm(),
225 : lp_workgroup(),
226 : NULL,
227 : ADS_SASL_PLAIN);
228 0 : if (ads == NULL) {
229 0 : result = WERR_RPC_S_SERVER_UNAVAILABLE;
230 0 : goto out;
231 : }
232 :
233 0 : ads_status = ads_connect_machine(ads);
234 0 : if (!ADS_ERR_OK(ads_status)) {
235 0 : DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_status)));
236 0 : result = WERR_ACCESS_DENIED;
237 0 : goto out;
238 : }
239 :
240 0 : result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn);
241 0 : if (!W_ERROR_IS_OK(result)) {
242 0 : goto out;
243 : }
244 :
245 0 : result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid);
246 0 : out:
247 0 : TALLOC_FREE(tmp_ctx);
248 :
249 0 : return result;
250 : }
251 :
252 0 : WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
253 : const struct auth_session_info *session_info,
254 : struct messaging_context *msg_ctx,
255 : const char *printer, struct GUID *guid)
256 : {
257 0 : TALLOC_CTX *tmp_ctx;
258 0 : enum winreg_Type type;
259 0 : DATA_BLOB blob;
260 0 : uint32_t len;
261 0 : NTSTATUS status;
262 0 : WERROR result;
263 :
264 0 : tmp_ctx = talloc_new(mem_ctx);
265 0 : if (tmp_ctx == NULL) {
266 0 : DEBUG(0, ("out of memory?!\n"));
267 0 : return WERR_NOT_ENOUGH_MEMORY;
268 : }
269 :
270 0 : result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
271 : msg_ctx, printer,
272 : SPOOL_DSSPOOLER_KEY,
273 : "objectGUID",
274 : &type,
275 : &blob.data,
276 : &len);
277 0 : if (!W_ERROR_IS_OK(result)) {
278 0 : DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
279 0 : goto out_ctx_free;
280 : }
281 0 : blob.length = (size_t)len;
282 :
283 : /* We used to store the guid as REG_BINARY, then swapped
284 : to REG_SZ for Vista compatibility so check for both */
285 :
286 0 : switch (type) {
287 0 : case REG_SZ: {
288 0 : bool ok;
289 0 : const char *guid_str;
290 0 : ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
291 0 : if (!ok) {
292 0 : DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
293 : printer));
294 0 : result = WERR_REGISTRY_CORRUPT;
295 0 : goto out_ctx_free;
296 : }
297 0 : status = GUID_from_string(guid_str, guid);
298 0 : if (!NT_STATUS_IS_OK(status)) {
299 0 : DEBUG(0, ("bad GUID for printer %s\n", printer));
300 0 : result = ntstatus_to_werror(status);
301 0 : goto out_ctx_free;
302 : }
303 0 : break;
304 : }
305 0 : case REG_BINARY:
306 0 : if (blob.length != sizeof(struct GUID)) {
307 0 : DEBUG(0, ("bad GUID for printer %s\n", printer));
308 0 : result = WERR_REGISTRY_CORRUPT;
309 0 : goto out_ctx_free;
310 : }
311 0 : memcpy(guid, blob.data, sizeof(struct GUID));
312 0 : break;
313 0 : default:
314 0 : DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
315 0 : result = WERR_REGISTRY_CORRUPT;
316 0 : goto out_ctx_free;
317 : break;
318 : }
319 0 : result = WERR_OK;
320 :
321 0 : out_ctx_free:
322 0 : talloc_free(tmp_ctx);
323 0 : return result;
324 : }
325 :
326 0 : static WERROR nt_printer_devmode_to_mods(TALLOC_CTX *ctx,
327 : struct spoolss_DeviceMode *devmode,
328 : ADS_MODLIST *mods)
329 : {
330 0 : char *str = NULL;
331 0 : ADS_STATUS status;
332 :
333 : /*
334 : the device mode fields bits allow us to make an educated guess if a
335 : printer feature is supported. For sure a feature must be unsupported if
336 : the fields bit is not set. Device Mode Extra Data and FeatureOptionPairs
337 : might help to figure out more information here. Common attributes, that
338 : we can't handle yet:
339 : SPOOL_REG_PRINTBINNAMES - printBinNames
340 : SPOOL_REG_PRINTMAXXEXTENT - printMaxXExtent
341 : SPOOL_REG_PRINTMAXYEXTENT - printMaxYExtent
342 : SPOOL_REG_PRINTMINXEXTENT - printMinXExtent
343 : SPOOL_REG_PRINTMINYEXTENT - printMinYExtent
344 : SPOOL_REG_PRINTSTAPLINGSUPPORTED - printStaplingSupported
345 : SPOOL_REG_PRINTPAGESPERMINUTE - printPagesPerMinute
346 : SPOOL_REG_PRINTRATE - printRate
347 : SPOOL_REG_PRINTRATEUNIT - printRateUnit
348 : SPOOL_REG_PRINTMEDIAREADY - printMediaReady
349 : SPOOL_REG_PRINTMEDIASUPPORTED - printMediaSupported
350 : SPOOL_REG_PRINTNUMBERUP - printNumberUp
351 : SPOOL_REG_PRINTMAXCOPIES - printMaxCopies
352 : */
353 0 : if (devmode->fields & DEVMODE_COLOR) {
354 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "TRUE");
355 : } else {
356 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "FALSE");
357 : }
358 0 : if (!ADS_ERR_OK(status)) {
359 0 : return WERR_NOT_ENOUGH_MEMORY;
360 : }
361 :
362 0 : if (devmode->fields & DEVMODE_DUPLEX) {
363 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "TRUE");
364 : } else {
365 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "FALSE");
366 : }
367 0 : if (!ADS_ERR_OK(status)) {
368 0 : return WERR_NOT_ENOUGH_MEMORY;
369 : }
370 :
371 0 : if (devmode->fields & DEVMODE_COLLATE) {
372 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "TRUE");
373 : } else {
374 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "FALSE");
375 : }
376 0 : if (!ADS_ERR_OK(status)) {
377 0 : return WERR_NOT_ENOUGH_MEMORY;
378 : }
379 :
380 : /* portrait mode is always supported, LANDSCAPE is optional */
381 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "PORTRAIT");
382 0 : if (!ADS_ERR_OK(status)) {
383 0 : return WERR_NOT_ENOUGH_MEMORY;
384 : }
385 0 : if (devmode->fields & DEVMODE_ORIENTATION) {
386 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "LANDSCAPE");
387 0 : if (!ADS_ERR_OK(status)) {
388 0 : return WERR_NOT_ENOUGH_MEMORY;
389 : }
390 : }
391 :
392 : /* the driverVersion attribute in AD contains actually specversion */
393 0 : str = talloc_asprintf(ctx, "%u", devmode->specversion);
394 0 : if (str == NULL) {
395 0 : return WERR_NOT_ENOUGH_MEMORY;
396 : }
397 0 : if (strlen(str) != 0) {
398 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_DRIVERVERSION, str);
399 0 : if (!ADS_ERR_OK(status)) {
400 0 : return WERR_NOT_ENOUGH_MEMORY;
401 : }
402 : }
403 :
404 : /* devmode->yresolution is a good candidate for printMaxResolutionSupported */
405 0 : str = talloc_asprintf(ctx, "%u", devmode->yresolution);
406 0 : if (str == NULL) {
407 0 : return WERR_NOT_ENOUGH_MEMORY;
408 : }
409 0 : if (strlen(str) != 0) {
410 0 : status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, str);
411 0 : if (!ADS_ERR_OK(status)) {
412 0 : return WERR_NOT_ENOUGH_MEMORY;
413 : }
414 : }
415 :
416 0 : return WERR_OK;
417 : }
418 :
419 :
420 :
421 0 : static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx,
422 : struct spoolss_PrinterInfo2 *info2,
423 : ADS_MODLIST *mods)
424 : {
425 0 : char *info_str;
426 :
427 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTERNAME, info2->sharename);
428 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSHARENAME, info2->sharename);
429 0 : ads_mod_str(ctx, mods, SPOOL_REG_SHORTSERVERNAME, lp_netbios_name());
430 0 : ads_mod_str(ctx, mods, SPOOL_REG_SERVERNAME, get_mydnsfullname());
431 :
432 0 : info_str = talloc_asprintf(ctx, "\\\\%s\\%s",
433 : get_mydnsfullname(), info2->sharename);
434 0 : if (info_str == NULL) {
435 0 : return WERR_NOT_ENOUGH_MEMORY;
436 : }
437 0 : ads_mod_str(ctx, mods, SPOOL_REG_UNCNAME, info_str);
438 :
439 0 : info_str = talloc_asprintf(ctx, "%d", 4);
440 0 : if (info_str == NULL) {
441 0 : return WERR_NOT_ENOUGH_MEMORY;
442 : }
443 0 : ads_mod_str(ctx, mods, SPOOL_REG_VERSIONNUMBER, info_str);
444 :
445 : /* empty strings in the mods list result in an attribute error */
446 0 : if (strlen(info2->drivername) != 0)
447 0 : ads_mod_str(ctx, mods, SPOOL_REG_DRIVERNAME, info2->drivername);
448 0 : if (strlen(info2->location) != 0)
449 0 : ads_mod_str(ctx, mods, SPOOL_REG_LOCATION, info2->location);
450 0 : if (strlen(info2->comment) != 0)
451 0 : ads_mod_str(ctx, mods, SPOOL_REG_DESCRIPTION, info2->comment);
452 0 : if (strlen(info2->portname) != 0)
453 0 : ads_mod_str(ctx, mods, SPOOL_REG_PORTNAME, info2->portname);
454 0 : if (strlen(info2->sepfile) != 0)
455 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
456 :
457 0 : info_str = talloc_asprintf(ctx, "%u", info2->starttime);
458 0 : if (info_str == NULL) {
459 0 : return WERR_NOT_ENOUGH_MEMORY;
460 : }
461 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSTARTTIME, info_str);
462 :
463 0 : info_str = talloc_asprintf(ctx, "%u", info2->untiltime);
464 0 : if (info_str == NULL) {
465 0 : return WERR_NOT_ENOUGH_MEMORY;
466 : }
467 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTENDTIME, info_str);
468 :
469 0 : info_str = talloc_asprintf(ctx, "%u", info2->priority);
470 0 : if (info_str == NULL) {
471 0 : return WERR_NOT_ENOUGH_MEMORY;
472 : }
473 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRIORITY, info_str);
474 :
475 0 : if (info2->attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) {
476 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "TRUE");
477 : } else {
478 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "FALSE");
479 : }
480 :
481 0 : switch (info2->attributes & 0x3) {
482 0 : case 0:
483 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
484 : SPOOL_REGVAL_PRINTWHILESPOOLING);
485 0 : break;
486 0 : case 1:
487 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
488 : SPOOL_REGVAL_PRINTAFTERSPOOLED);
489 0 : break;
490 0 : case 2:
491 0 : ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
492 : SPOOL_REGVAL_PRINTDIRECT);
493 0 : break;
494 0 : default:
495 0 : DEBUG(3, ("unsupported printer attributes %x\n",
496 : info2->attributes));
497 : }
498 :
499 0 : if (info2->devmode != NULL) {
500 0 : WERROR werr;
501 0 : werr = nt_printer_devmode_to_mods(ctx, info2->devmode, mods);
502 0 : if (!W_ERROR_IS_OK(werr)) {
503 0 : return werr;
504 : }
505 : }
506 :
507 0 : return WERR_OK;
508 : }
509 :
510 0 : static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
511 : ADS_STRUCT *ads,
512 : struct spoolss_PrinterInfo2 *pinfo2)
513 : {
514 0 : ADS_STATUS ads_rc;
515 0 : TALLOC_CTX *ctx = talloc_stackframe();
516 0 : ADS_MODLIST mods;
517 0 : struct GUID guid;
518 0 : WERROR win_rc = WERR_OK;
519 0 : const char *printer = pinfo2->sharename;
520 0 : char *printer_dn = NULL;
521 :
522 : /* build the ads mods */
523 0 : DEBUG(5, ("publishing printer %s\n", printer));
524 :
525 0 : win_rc = nt_printer_dn_lookup(ctx, ads, printer, &printer_dn);
526 0 : if (!W_ERROR_IS_OK(win_rc)) {
527 0 : DEBUG(2, ("Failed to create printer dn\n"));
528 0 : TALLOC_FREE(ctx);
529 0 : return win_rc;
530 : }
531 :
532 0 : mods = ads_init_mods(ctx);
533 :
534 0 : if (mods == NULL) {
535 0 : TALLOC_FREE(ctx);
536 0 : return WERR_NOT_ENOUGH_MEMORY;
537 : }
538 :
539 0 : win_rc = nt_printer_info_to_mods(ctx, pinfo2, &mods);
540 0 : if (!W_ERROR_IS_OK(win_rc)) {
541 0 : TALLOC_FREE(ctx);
542 0 : return win_rc;
543 : }
544 :
545 : /* publish it */
546 0 : ads_rc = ads_mod_printer_entry(ads, printer_dn, ctx, &mods);
547 0 : if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
548 : int i;
549 0 : for (i=0; mods[i] != 0; i++)
550 : ;
551 0 : mods[i] = (LDAPMod *)-1;
552 0 : ads_rc = ads_add_printer_entry(ads, printer_dn, ctx, &mods);
553 : }
554 :
555 0 : if (!ADS_ERR_OK(ads_rc)) {
556 0 : DEBUG(3, ("error publishing %s: %s\n",
557 : printer, ads_errstr(ads_rc)));
558 : /* XXX failed to publish, so no guid to retrieve */
559 : }
560 :
561 0 : win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid);
562 0 : if (!W_ERROR_IS_OK(win_rc)) {
563 0 : TALLOC_FREE(ctx);
564 0 : return win_rc;
565 : }
566 :
567 0 : win_rc = nt_printer_guid_store(msg_ctx, printer, guid);
568 0 : if (!W_ERROR_IS_OK(win_rc)) {
569 0 : DEBUG(3, ("failed to store printer %s guid\n",
570 : printer));
571 : /* not catastrophic, retrieve on next use */
572 0 : win_rc = WERR_OK;
573 : }
574 :
575 0 : TALLOC_FREE(ctx);
576 :
577 0 : return win_rc;
578 : }
579 :
580 0 : static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
581 : const char *printer)
582 : {
583 0 : ADS_STATUS ads_rc;
584 0 : LDAPMessage *res = NULL;
585 0 : char *prt_dn = NULL;
586 :
587 0 : DEBUG(5, ("unpublishing printer %s\n", printer));
588 :
589 : /* remove the printer from the directory */
590 0 : ads_rc = ads_find_printer_on_server(ads, &res,
591 : printer, lp_netbios_name());
592 :
593 0 : if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
594 0 : prt_dn = ads_get_dn(ads, talloc_tos(), res);
595 0 : if (!prt_dn) {
596 0 : ads_msgfree(ads, res);
597 0 : return WERR_NOT_ENOUGH_MEMORY;
598 : }
599 0 : ads_rc = ads_del_dn(ads, prt_dn);
600 0 : TALLOC_FREE(prt_dn);
601 : }
602 :
603 0 : if (res) {
604 0 : ads_msgfree(ads, res);
605 : }
606 0 : return WERR_OK;
607 : }
608 :
609 : /****************************************************************************
610 : * Publish a printer in the directory
611 : *
612 : * @param mem_ctx memory context
613 : * @param session_info session_info to access winreg pipe
614 : * @param pinfo2 printer information
615 : * @param action publish/unpublish action
616 : * @return WERROR indicating status of publishing
617 : ***************************************************************************/
618 :
619 0 : WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
620 : const struct auth_session_info *session_info,
621 : struct messaging_context *msg_ctx,
622 : struct spoolss_PrinterInfo2 *pinfo2,
623 : int action)
624 : {
625 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
626 0 : uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
627 0 : struct spoolss_SetPrinterInfo2 *sinfo2;
628 0 : ADS_STATUS ads_rc;
629 0 : ADS_STRUCT *ads = NULL;
630 0 : WERROR win_rc;
631 :
632 0 : sinfo2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
633 0 : if (!sinfo2) {
634 0 : win_rc = WERR_NOT_ENOUGH_MEMORY;
635 0 : goto done;
636 : }
637 :
638 0 : switch (action) {
639 0 : case DSPRINT_PUBLISH:
640 : case DSPRINT_UPDATE:
641 0 : pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
642 0 : break;
643 0 : case DSPRINT_UNPUBLISH:
644 0 : pinfo2->attributes &= (~PRINTER_ATTRIBUTE_PUBLISHED);
645 0 : break;
646 0 : default:
647 0 : win_rc = WERR_NOT_SUPPORTED;
648 0 : goto done;
649 : }
650 :
651 0 : sinfo2->attributes = pinfo2->attributes;
652 :
653 0 : win_rc = winreg_update_printer_internal(tmp_ctx, session_info, msg_ctx,
654 : pinfo2->sharename, info2_mask,
655 : sinfo2, NULL, NULL);
656 0 : if (!W_ERROR_IS_OK(win_rc)) {
657 0 : DBG_NOTICE("Failed to update data for printer [%s] - %s\n",
658 : pinfo2->sharename,
659 : win_errstr(win_rc));
660 0 : goto done;
661 : }
662 :
663 0 : TALLOC_FREE(sinfo2);
664 :
665 0 : ads = ads_init(tmp_ctx,
666 : lp_realm(),
667 : lp_workgroup(),
668 : NULL,
669 : ADS_SASL_PLAIN);
670 0 : if (!ads) {
671 0 : DEBUG(3, ("ads_init() failed\n"));
672 0 : win_rc = WERR_RPC_S_SERVER_UNAVAILABLE;
673 0 : goto done;
674 : }
675 :
676 : /* ads_connect_machine() will find the DC for us */
677 0 : ads_rc = ads_connect_machine(ads);
678 0 : if (!ADS_ERR_OK(ads_rc)) {
679 0 : DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_rc)));
680 0 : win_rc = WERR_ACCESS_DENIED;
681 0 : goto done;
682 : }
683 :
684 0 : switch (action) {
685 0 : case DSPRINT_PUBLISH:
686 : case DSPRINT_UPDATE:
687 0 : win_rc = nt_printer_publish_ads(msg_ctx, ads, pinfo2);
688 0 : break;
689 0 : case DSPRINT_UNPUBLISH:
690 0 : win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
691 0 : break;
692 : }
693 :
694 0 : done:
695 0 : TALLOC_FREE(tmp_ctx);
696 :
697 0 : return win_rc;
698 : }
699 :
700 2 : WERROR check_published_printers(struct messaging_context *msg_ctx)
701 : {
702 0 : const struct loadparm_substitution *lp_sub =
703 2 : loadparm_s3_global_substitution();
704 0 : ADS_STATUS ads_rc;
705 2 : ADS_STRUCT *ads = NULL;
706 0 : int snum;
707 2 : int n_services = lp_numservices();
708 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
709 2 : struct auth_session_info *session_info = NULL;
710 0 : struct spoolss_PrinterInfo2 *pinfo2;
711 0 : NTSTATUS status;
712 0 : WERROR result;
713 :
714 2 : ads = ads_init(tmp_ctx,
715 : lp_realm(),
716 : lp_workgroup(),
717 : NULL,
718 : ADS_SASL_PLAIN);
719 2 : if (!ads) {
720 0 : DEBUG(3, ("ads_init() failed\n"));
721 0 : TALLOC_FREE(tmp_ctx);
722 0 : return WERR_RPC_S_SERVER_UNAVAILABLE;
723 : }
724 :
725 : /* ads_connect_machine() will find the DC for us */
726 2 : ads_rc = ads_connect_machine(ads);
727 2 : if (!ADS_ERR_OK(ads_rc)) {
728 0 : DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_rc)));
729 0 : result = WERR_ACCESS_DENIED;
730 0 : goto done;
731 : }
732 :
733 2 : status = make_session_info_system(tmp_ctx, &session_info);
734 2 : if (!NT_STATUS_IS_OK(status)) {
735 0 : DEBUG(0, ("check_published_printers: "
736 : "Could not create system session_info\n"));
737 0 : result = WERR_ACCESS_DENIED;
738 0 : goto done;
739 : }
740 :
741 246 : for (snum = 0; snum < n_services; snum++) {
742 244 : if (!lp_snum_ok(snum) || !lp_printable(snum)) {
743 234 : continue;
744 : }
745 :
746 10 : result = winreg_get_printer_internal(tmp_ctx, session_info, msg_ctx,
747 10 : lp_servicename(talloc_tos(), lp_sub, snum),
748 : &pinfo2);
749 10 : if (!W_ERROR_IS_OK(result)) {
750 10 : continue;
751 : }
752 :
753 0 : if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
754 0 : nt_printer_publish_ads(msg_ctx, ads, pinfo2);
755 : }
756 :
757 0 : TALLOC_FREE(pinfo2);
758 : }
759 :
760 2 : result = WERR_OK;
761 2 : done:
762 2 : talloc_free(tmp_ctx);
763 2 : return result;
764 : }
765 :
766 84 : bool is_printer_published(TALLOC_CTX *mem_ctx,
767 : const struct auth_session_info *session_info,
768 : struct messaging_context *msg_ctx,
769 : const char *servername,
770 : const char *printer,
771 : struct spoolss_PrinterInfo2 **info2)
772 : {
773 84 : struct spoolss_PrinterInfo2 *pinfo2 = NULL;
774 0 : WERROR result;
775 0 : struct dcerpc_binding_handle *b;
776 :
777 84 : result = winreg_printer_binding_handle(mem_ctx,
778 : session_info,
779 : msg_ctx,
780 : &b);
781 84 : if (!W_ERROR_IS_OK(result)) {
782 0 : return false;
783 : }
784 :
785 84 : result = winreg_get_printer(mem_ctx, b,
786 : printer, &pinfo2);
787 84 : if (!W_ERROR_IS_OK(result)) {
788 0 : return false;
789 : }
790 :
791 84 : if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
792 84 : TALLOC_FREE(pinfo2);
793 84 : return false;
794 : }
795 :
796 0 : if (info2) {
797 0 : *info2 = talloc_move(mem_ctx, &pinfo2);
798 : }
799 0 : talloc_free(pinfo2);
800 0 : return true;
801 : }
802 : #else
803 0 : WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
804 : const char *printer, struct GUID guid)
805 : {
806 0 : return WERR_NOT_SUPPORTED;
807 : }
808 :
809 0 : WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
810 : struct GUID *pguid)
811 : {
812 0 : return WERR_NOT_SUPPORTED;
813 : }
814 :
815 0 : WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
816 : const struct auth_session_info *session_info,
817 : struct messaging_context *msg_ctx,
818 : const char *printer, struct GUID *guid)
819 : {
820 0 : return WERR_NOT_SUPPORTED;
821 : }
822 :
823 0 : WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
824 : const struct auth_session_info *session_info,
825 : struct messaging_context *msg_ctx,
826 : struct spoolss_PrinterInfo2 *pinfo2,
827 : int action)
828 : {
829 0 : return WERR_OK;
830 : }
831 :
832 0 : WERROR check_published_printers(struct messaging_context *msg_ctx)
833 : {
834 0 : return WERR_OK;
835 : }
836 :
837 28 : bool is_printer_published(TALLOC_CTX *mem_ctx,
838 : const struct auth_session_info *session_info,
839 : struct messaging_context *msg_ctx,
840 : const char *servername,
841 : const char *printer,
842 : struct spoolss_PrinterInfo2 **info2)
843 : {
844 28 : return False;
845 : }
846 : #endif /* HAVE_ADS */
|