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/spoolss.h"
24 #include "rpc_server/spoolss/srv_spoolss_util.h"
25 #include "nt_printing.h"
29 #include "../libcli/registry/util_reg.h"
31 #include "../librpc/ndr/libndr.h"
32 #include "rpc_client/cli_winreg_spoolss.h"
35 /*****************************************************************
36 ****************************************************************/
38 WERROR
nt_printer_guid_store(struct messaging_context
*msg_ctx
,
39 const char *printer
, struct GUID guid
)
42 const struct auth_session_info
*session_info
;
47 tmp_ctx
= talloc_new(NULL
);
49 DEBUG(0, ("Out of memory?!\n"));
50 return WERR_NOT_ENOUGH_MEMORY
;
53 session_info
= get_session_info_system();
54 if (session_info
== NULL
) {
55 DEBUG(0, ("Could not get system session_info\n"));
56 result
= WERR_NOT_ENOUGH_MEMORY
;
60 guid_str
= GUID_string(tmp_ctx
, &guid
);
62 DEBUG(0, ("Out of memory?!\n"));
63 result
= WERR_NOT_ENOUGH_MEMORY
;
67 /* We used to store this as a REG_BINARY but that causes
70 if (!push_reg_sz(tmp_ctx
, &blob
, guid_str
)) {
71 DEBUG(0, ("Could not marshall string %s for objectGUID\n",
73 result
= WERR_NOT_ENOUGH_MEMORY
;
77 result
= winreg_set_printer_dataex_internal(tmp_ctx
, session_info
, msg_ctx
,
79 SPOOL_DSSPOOLER_KEY
, "objectGUID",
80 REG_SZ
, blob
.data
, blob
.length
);
81 if (!W_ERROR_IS_OK(result
)) {
82 DEBUG(0, ("Failed to store GUID for printer %s\n", printer
));
93 static WERROR
nt_printer_dn_lookup(TALLOC_CTX
*mem_ctx
,
98 char *printer_dn
= NULL
;
100 char *srv_cn_0
= NULL
;
101 char *srv_cn_escaped
= NULL
;
102 char *sharename_escaped
= NULL
;
103 char *srv_dn_utf8
= NULL
;
104 char **srv_cn_utf8
= NULL
;
105 size_t converted_size
;
106 ADS_STATUS ads_status
;
111 ads_status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
112 if (!ADS_ERR_OK(ads_status
)) {
113 DEBUG(2, ("Failed to find machine account for %s\n",
115 result
= WERR_NOT_FOUND
;
120 * We use ldap_get_dn here as we need the answer in utf8 to call
121 * ldap_explode_dn(). JRA.
123 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
124 ads_msgfree(ads
, res
);
125 if (srv_dn_utf8
== NULL
) {
126 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
130 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
131 if (srv_cn_utf8
== NULL
) {
132 ldap_memfree(srv_dn_utf8
);
133 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
137 /* Now convert to CH_UNIX. */
138 ok
= pull_utf8_talloc(mem_ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
);
139 ldap_memfree(srv_dn_utf8
);
141 ldap_memfree(srv_cn_utf8
);
142 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
146 ok
= pull_utf8_talloc(mem_ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
);
147 ldap_memfree(srv_cn_utf8
);
149 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
153 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
154 if (srv_cn_escaped
== NULL
) {
155 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
159 sharename_escaped
= escape_rdn_val_string_alloc(printer
);
160 if (sharename_escaped
== NULL
) {
161 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
165 printer_dn
= talloc_asprintf(mem_ctx
,
170 if (printer_dn
== NULL
) {
171 result
= WERR_NOT_ENOUGH_MEMORY
;
175 *pprinter_dn
= printer_dn
;
179 SAFE_FREE(sharename_escaped
);
180 SAFE_FREE(srv_cn_escaped
);
181 TALLOC_FREE(srv_cn_0
);
186 static WERROR
nt_printer_guid_retrieve_internal(ADS_STRUCT
*ads
,
187 const char *printer_dn
,
190 ADS_STATUS ads_status
;
192 const char *attrs
[] = {"objectGUID", NULL
};
196 ads_status
= ads_search_dn(ads
, &res
, printer_dn
, attrs
);
197 if (!ADS_ERR_OK(ads_status
)) {
198 DEBUG(2, ("Failed to retrieve GUID from DC - %s\n",
199 ads_errstr(ads_status
)));
200 return WERR_FILE_NOT_FOUND
;
204 ok
= ads_pull_guid(ads
, res
, &guid
);
205 ads_msgfree(ads
, res
);
207 return WERR_NOT_ENOUGH_MEMORY
;
215 WERROR
nt_printer_guid_retrieve(TALLOC_CTX
*mem_ctx
, const char *printer
,
218 ADS_STRUCT
*ads
= NULL
;
219 char *old_krb5ccname
= NULL
;
222 ADS_STATUS ads_status
;
225 tmp_ctx
= talloc_new(mem_ctx
);
226 if (tmp_ctx
== NULL
) {
227 return WERR_NOT_ENOUGH_MEMORY
;
230 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
, ADS_SASL_PLAIN
);
232 result
= WERR_RPC_S_SERVER_UNAVAILABLE
;
236 old_krb5ccname
= getenv(KRB5_ENV_CCNAME
);
237 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
238 SAFE_FREE(ads
->auth
.password
);
239 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
242 ads_status
= ads_connect(ads
);
243 if (!ADS_ERR_OK(ads_status
)) {
244 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_status
)));
245 result
= WERR_ACCESS_DENIED
;
249 result
= nt_printer_dn_lookup(tmp_ctx
, ads
, printer
, &printer_dn
);
250 if (!W_ERROR_IS_OK(result
)) {
254 result
= nt_printer_guid_retrieve_internal(ads
, printer_dn
, pguid
);
256 TALLOC_FREE(tmp_ctx
);
258 ads_kdestroy("MEMORY:prtpub_cache");
259 unsetenv(KRB5_ENV_CCNAME
);
260 if (old_krb5ccname
!= NULL
) {
261 setenv(KRB5_ENV_CCNAME
, old_krb5ccname
, 0);
267 WERROR
nt_printer_guid_get(TALLOC_CTX
*mem_ctx
,
268 const struct auth_session_info
*session_info
,
269 struct messaging_context
*msg_ctx
,
270 const char *printer
, struct GUID
*guid
)
273 enum winreg_Type type
;
279 tmp_ctx
= talloc_new(mem_ctx
);
280 if (tmp_ctx
== NULL
) {
281 DEBUG(0, ("out of memory?!\n"));
282 return WERR_NOT_ENOUGH_MEMORY
;
285 result
= winreg_get_printer_dataex_internal(tmp_ctx
, session_info
,
292 if (!W_ERROR_IS_OK(result
)) {
293 DEBUG(0, ("Failed to get GUID for printer %s\n", printer
));
296 blob
.length
= (size_t)len
;
298 /* We used to store the guid as REG_BINARY, then swapped
299 to REG_SZ for Vista compatibility so check for both */
304 const char *guid_str
;
305 ok
= pull_reg_sz(tmp_ctx
, &blob
, &guid_str
);
307 DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
309 result
= WERR_REGISTRY_CORRUPT
;
312 status
= GUID_from_string(guid_str
, guid
);
313 if (!NT_STATUS_IS_OK(status
)) {
314 DEBUG(0, ("bad GUID for printer %s\n", printer
));
315 result
= ntstatus_to_werror(status
);
321 if (blob
.length
!= sizeof(struct GUID
)) {
322 DEBUG(0, ("bad GUID for printer %s\n", printer
));
323 result
= WERR_REGISTRY_CORRUPT
;
326 memcpy(guid
, blob
.data
, sizeof(struct GUID
));
329 DEBUG(0,("GUID value stored as invalid type (%d)\n", type
));
330 result
= WERR_REGISTRY_CORRUPT
;
337 talloc_free(tmp_ctx
);
341 static WERROR
nt_printer_devmode_to_mods(TALLOC_CTX
*ctx
,
342 struct spoolss_DeviceMode
*devmode
,
349 the device mode fields bits allow us to make an educated guess if a
350 printer feature is supported. For sure a feature must be unsupported if
351 the fields bit is not set. Device Mode Extra Data and FeatureOptionPairs
352 might help to figure out more information here. Common attributes, that
354 SPOOL_REG_PRINTBINNAMES - printBinNames
355 SPOOL_REG_PRINTMAXXEXTENT - printMaxXExtent
356 SPOOL_REG_PRINTMAXYEXTENT - printMaxYExtent
357 SPOOL_REG_PRINTMINXEXTENT - printMinXExtent
358 SPOOL_REG_PRINTMINYEXTENT - printMinYExtent
359 SPOOL_REG_PRINTSTAPLINGSUPPORTED - printStaplingSupported
360 SPOOL_REG_PRINTPAGESPERMINUTE - printPagesPerMinute
361 SPOOL_REG_PRINTRATE - printRate
362 SPOOL_REG_PRINTRATEUNIT - printRateUnit
363 SPOOL_REG_PRINTMEDIAREADY - printMediaReady
364 SPOOL_REG_PRINTMEDIASUPPORTED - printMediaSupported
365 SPOOL_REG_PRINTNUMBERUP - printNumberUp
366 SPOOL_REG_PRINTMAXCOPIES - printMaxCopies
368 if (devmode
->fields
& DEVMODE_COLOR
) {
369 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTCOLOR
, "TRUE");
371 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTCOLOR
, "FALSE");
373 if (!ADS_ERR_OK(status
)) {
374 return WERR_NOT_ENOUGH_MEMORY
;
377 if (devmode
->fields
& DEVMODE_DUPLEX
) {
378 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTDUPLEXSUPPORTED
, "TRUE");
380 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTDUPLEXSUPPORTED
, "FALSE");
382 if (!ADS_ERR_OK(status
)) {
383 return WERR_NOT_ENOUGH_MEMORY
;
386 if (devmode
->fields
& DEVMODE_COLLATE
) {
387 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTCOLLATE
, "TRUE");
389 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTCOLLATE
, "FALSE");
391 if (!ADS_ERR_OK(status
)) {
392 return WERR_NOT_ENOUGH_MEMORY
;
395 /* portrait mode is always supported, LANDSCAPE is optional */
396 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, "PORTRAIT");
397 if (!ADS_ERR_OK(status
)) {
398 return WERR_NOT_ENOUGH_MEMORY
;
400 if (devmode
->fields
& DEVMODE_ORIENTATION
) {
401 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, "LANDSCAPE");
402 if (!ADS_ERR_OK(status
)) {
403 return WERR_NOT_ENOUGH_MEMORY
;
407 /* the driverVersion attribute in AD contains actually specversion */
408 str
= talloc_asprintf(ctx
, "%u", devmode
->specversion
);
410 return WERR_NOT_ENOUGH_MEMORY
;
412 if (strlen(str
) != 0) {
413 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_DRIVERVERSION
, str
);
414 if (!ADS_ERR_OK(status
)) {
415 return WERR_NOT_ENOUGH_MEMORY
;
419 /* devmode->yresolution is a good candidate for printMaxResolutionSupported */
420 str
= talloc_asprintf(ctx
, "%u", devmode
->yresolution
);
422 return WERR_NOT_ENOUGH_MEMORY
;
424 if (strlen(str
) != 0) {
425 status
= ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, str
);
426 if (!ADS_ERR_OK(status
)) {
427 return WERR_NOT_ENOUGH_MEMORY
;
436 static WERROR
nt_printer_info_to_mods(TALLOC_CTX
*ctx
,
437 struct spoolss_PrinterInfo2
*info2
,
442 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
443 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSHARENAME
, info2
->sharename
);
444 ads_mod_str(ctx
, mods
, SPOOL_REG_SHORTSERVERNAME
, lp_netbios_name());
445 ads_mod_str(ctx
, mods
, SPOOL_REG_SERVERNAME
, get_mydnsfullname());
447 info_str
= talloc_asprintf(ctx
, "\\\\%s\\%s",
448 get_mydnsfullname(), info2
->sharename
);
449 if (info_str
== NULL
) {
450 return WERR_NOT_ENOUGH_MEMORY
;
452 ads_mod_str(ctx
, mods
, SPOOL_REG_UNCNAME
, info_str
);
454 info_str
= talloc_asprintf(ctx
, "%d", 4);
455 if (info_str
== NULL
) {
456 return WERR_NOT_ENOUGH_MEMORY
;
458 ads_mod_str(ctx
, mods
, SPOOL_REG_VERSIONNUMBER
, info_str
);
460 /* empty strings in the mods list result in an attrubute error */
461 if (strlen(info2
->drivername
) != 0)
462 ads_mod_str(ctx
, mods
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
463 if (strlen(info2
->location
) != 0)
464 ads_mod_str(ctx
, mods
, SPOOL_REG_LOCATION
, info2
->location
);
465 if (strlen(info2
->comment
) != 0)
466 ads_mod_str(ctx
, mods
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
467 if (strlen(info2
->portname
) != 0)
468 ads_mod_str(ctx
, mods
, SPOOL_REG_PORTNAME
, info2
->portname
);
469 if (strlen(info2
->sepfile
) != 0)
470 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
472 info_str
= talloc_asprintf(ctx
, "%u", info2
->starttime
);
473 if (info_str
== NULL
) {
474 return WERR_NOT_ENOUGH_MEMORY
;
476 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSTARTTIME
, info_str
);
478 info_str
= talloc_asprintf(ctx
, "%u", info2
->untiltime
);
479 if (info_str
== NULL
) {
480 return WERR_NOT_ENOUGH_MEMORY
;
482 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTENDTIME
, info_str
);
484 info_str
= talloc_asprintf(ctx
, "%u", info2
->priority
);
485 if (info_str
== NULL
) {
486 return WERR_NOT_ENOUGH_MEMORY
;
488 ads_mod_str(ctx
, mods
, SPOOL_REG_PRIORITY
, info_str
);
490 if (info2
->attributes
& PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
) {
491 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
, "TRUE");
493 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
, "FALSE");
496 switch (info2
->attributes
& 0x3) {
498 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSPOOLING
,
499 SPOOL_REGVAL_PRINTWHILESPOOLING
);
502 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSPOOLING
,
503 SPOOL_REGVAL_PRINTAFTERSPOOLED
);
506 ads_mod_str(ctx
, mods
, SPOOL_REG_PRINTSPOOLING
,
507 SPOOL_REGVAL_PRINTDIRECT
);
510 DEBUG(3, ("unsupported printer attributes %x\n",
514 if (info2
->devmode
!= NULL
) {
516 werr
= nt_printer_devmode_to_mods(ctx
, info2
->devmode
, mods
);
517 if (!W_ERROR_IS_OK(werr
)) {
525 static WERROR
nt_printer_publish_ads(struct messaging_context
*msg_ctx
,
527 struct spoolss_PrinterInfo2
*pinfo2
)
533 WERROR win_rc
= WERR_OK
;
534 const char *printer
= pinfo2
->sharename
;
535 char *printer_dn
= NULL
;
537 /* build the ads mods */
538 ctx
= talloc_init("nt_printer_publish_ads");
540 return WERR_NOT_ENOUGH_MEMORY
;
543 DEBUG(5, ("publishing printer %s\n", printer
));
545 win_rc
= nt_printer_dn_lookup(ctx
, ads
, printer
, &printer_dn
);
546 if (!W_ERROR_IS_OK(win_rc
)) {
547 DEBUG(2, ("Failed to create printer dn\n"));
552 mods
= ads_init_mods(ctx
);
556 return WERR_NOT_ENOUGH_MEMORY
;
559 win_rc
= nt_printer_info_to_mods(ctx
, pinfo2
, &mods
);
560 if (!W_ERROR_IS_OK(win_rc
)) {
566 ads_rc
= ads_mod_printer_entry(ads
, printer_dn
, ctx
, &mods
);
567 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
569 for (i
=0; mods
[i
] != 0; i
++)
571 mods
[i
] = (LDAPMod
*)-1;
572 ads_rc
= ads_add_printer_entry(ads
, printer_dn
, ctx
, &mods
);
575 if (!ADS_ERR_OK(ads_rc
)) {
576 DEBUG(3, ("error publishing %s: %s\n",
577 printer
, ads_errstr(ads_rc
)));
578 /* XXX failed to publish, so no guid to retrieve */
581 win_rc
= nt_printer_guid_retrieve_internal(ads
, printer_dn
, &guid
);
582 if (!W_ERROR_IS_OK(win_rc
)) {
587 win_rc
= nt_printer_guid_store(msg_ctx
, printer
, guid
);
588 if (!W_ERROR_IS_OK(win_rc
)) {
589 DEBUG(3, ("failed to store printer %s guid\n",
591 /* not catastrophic, retrieve on next use */
600 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
604 LDAPMessage
*res
= NULL
;
607 DEBUG(5, ("unpublishing printer %s\n", printer
));
609 /* remove the printer from the directory */
610 ads_rc
= ads_find_printer_on_server(ads
, &res
,
611 printer
, lp_netbios_name());
613 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
614 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
616 ads_msgfree(ads
, res
);
617 return WERR_NOT_ENOUGH_MEMORY
;
619 ads_rc
= ads_del_dn(ads
, prt_dn
);
624 ads_msgfree(ads
, res
);
629 /****************************************************************************
630 * Publish a printer in the directory
632 * @param mem_ctx memory context
633 * @param session_info session_info to access winreg pipe
634 * @param pinfo2 printer information
635 * @param action publish/unpublish action
636 * @return WERROR indicating status of publishing
637 ***************************************************************************/
639 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
640 const struct auth_session_info
*session_info
,
641 struct messaging_context
*msg_ctx
,
642 struct spoolss_PrinterInfo2
*pinfo2
,
645 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ATTRIBUTES
;
646 struct spoolss_SetPrinterInfo2
*sinfo2
;
648 ADS_STRUCT
*ads
= NULL
;
650 char *old_krb5ccname
= NULL
;
652 sinfo2
= talloc_zero(mem_ctx
, struct spoolss_SetPrinterInfo2
);
654 return WERR_NOT_ENOUGH_MEMORY
;
658 case DSPRINT_PUBLISH
:
660 pinfo2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
662 case DSPRINT_UNPUBLISH
:
663 pinfo2
->attributes
&= (~PRINTER_ATTRIBUTE_PUBLISHED
);
666 win_rc
= WERR_NOT_SUPPORTED
;
670 sinfo2
->attributes
= pinfo2
->attributes
;
672 win_rc
= winreg_update_printer_internal(mem_ctx
, session_info
, msg_ctx
,
673 pinfo2
->sharename
, info2_mask
,
675 if (!W_ERROR_IS_OK(win_rc
)) {
676 DBG_NOTICE("Failed to update data for printer [%s] - %s\n",
684 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
, ADS_SASL_PLAIN
);
686 DEBUG(3, ("ads_init() failed\n"));
687 win_rc
= WERR_RPC_S_SERVER_UNAVAILABLE
;
690 old_krb5ccname
= getenv(KRB5_ENV_CCNAME
);
691 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
692 SAFE_FREE(ads
->auth
.password
);
693 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
696 /* ads_connect() will find the DC for us */
697 ads_rc
= ads_connect(ads
);
698 if (!ADS_ERR_OK(ads_rc
)) {
699 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
700 win_rc
= WERR_ACCESS_DENIED
;
705 case DSPRINT_PUBLISH
:
707 win_rc
= nt_printer_publish_ads(msg_ctx
, ads
, pinfo2
);
709 case DSPRINT_UNPUBLISH
:
710 win_rc
= nt_printer_unpublish_ads(ads
, pinfo2
->sharename
);
716 ads_kdestroy("MEMORY:prtpub_cache");
717 unsetenv(KRB5_ENV_CCNAME
);
718 if (old_krb5ccname
) {
719 setenv(KRB5_ENV_CCNAME
, old_krb5ccname
, 0);
724 WERROR
check_published_printers(struct messaging_context
*msg_ctx
)
726 const struct loadparm_substitution
*lp_sub
=
727 loadparm_s3_global_substitution();
729 ADS_STRUCT
*ads
= NULL
;
731 int n_services
= lp_numservices();
732 TALLOC_CTX
*tmp_ctx
= NULL
;
733 struct auth_session_info
*session_info
= NULL
;
734 struct spoolss_PrinterInfo2
*pinfo2
;
737 char *old_krb5ccname
= NULL
;
739 tmp_ctx
= talloc_new(NULL
);
740 if (!tmp_ctx
) return WERR_NOT_ENOUGH_MEMORY
;
742 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
, ADS_SASL_PLAIN
);
744 DEBUG(3, ("ads_init() failed\n"));
745 return WERR_RPC_S_SERVER_UNAVAILABLE
;
747 old_krb5ccname
= getenv(KRB5_ENV_CCNAME
);
748 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
749 SAFE_FREE(ads
->auth
.password
);
750 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
753 /* ads_connect() will find the DC for us */
754 ads_rc
= ads_connect(ads
);
755 if (!ADS_ERR_OK(ads_rc
)) {
756 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
757 result
= WERR_ACCESS_DENIED
;
761 status
= make_session_info_system(tmp_ctx
, &session_info
);
762 if (!NT_STATUS_IS_OK(status
)) {
763 DEBUG(0, ("check_published_printers: "
764 "Could not create system session_info\n"));
765 result
= WERR_ACCESS_DENIED
;
769 for (snum
= 0; snum
< n_services
; snum
++) {
770 if (!lp_snum_ok(snum
) || !lp_printable(snum
)) {
774 result
= winreg_get_printer_internal(tmp_ctx
, session_info
, msg_ctx
,
775 lp_servicename(talloc_tos(), lp_sub
, snum
),
777 if (!W_ERROR_IS_OK(result
)) {
781 if (pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
782 nt_printer_publish_ads(msg_ctx
, ads
, pinfo2
);
791 ads_kdestroy("MEMORY:prtpub_cache");
792 unsetenv(KRB5_ENV_CCNAME
);
793 if (old_krb5ccname
) {
794 setenv(KRB5_ENV_CCNAME
, old_krb5ccname
, 0);
796 talloc_free(tmp_ctx
);
800 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
801 const struct auth_session_info
*session_info
,
802 struct messaging_context
*msg_ctx
,
803 const char *servername
,
805 struct spoolss_PrinterInfo2
**info2
)
807 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
809 struct dcerpc_binding_handle
*b
;
811 result
= winreg_printer_binding_handle(mem_ctx
,
815 if (!W_ERROR_IS_OK(result
)) {
819 result
= winreg_get_printer(mem_ctx
, b
,
821 if (!W_ERROR_IS_OK(result
)) {
825 if (!(pinfo2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
)) {
831 *info2
= talloc_move(mem_ctx
, &pinfo2
);
837 WERROR
nt_printer_guid_store(struct messaging_context
*msg_ctx
,
838 const char *printer
, struct GUID guid
)
840 return WERR_NOT_SUPPORTED
;
843 WERROR
nt_printer_guid_retrieve(TALLOC_CTX
*mem_ctx
, const char *printer
,
846 return WERR_NOT_SUPPORTED
;
849 WERROR
nt_printer_guid_get(TALLOC_CTX
*mem_ctx
,
850 const struct auth_session_info
*session_info
,
851 struct messaging_context
*msg_ctx
,
852 const char *printer
, struct GUID
*guid
)
854 return WERR_NOT_SUPPORTED
;
857 WERROR
nt_printer_publish(TALLOC_CTX
*mem_ctx
,
858 const struct auth_session_info
*session_info
,
859 struct messaging_context
*msg_ctx
,
860 struct spoolss_PrinterInfo2
*pinfo2
,
866 WERROR
check_published_printers(struct messaging_context
*msg_ctx
)
871 bool is_printer_published(TALLOC_CTX
*mem_ctx
,
872 const struct auth_session_info
*session_info
,
873 struct messaging_context
*msg_ctx
,
874 const char *servername
,
876 struct spoolss_PrinterInfo2
**info2
)
880 #endif /* HAVE_ADS */