1 From 892d163635563a3505fcde2d3439a2f6b1af92a7 Mon Sep 17 00:00:00 2001
2 From: David Disseldorp <ddiss@samba.org>
3 Date: Thu, 18 Dec 2014 18:18:21 +0100
4 Subject: [PATCH 1/4] PATCHSET16: printing: split out printer DN and GUID
7 This functions are used for printer publishing.
9 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018
11 Pair-programmed-with: Andreas Schneider <asn@samba.org>
12 Signed-off-by: David Disseldorp <ddiss@samba.org>
13 Signed-off-by: Andreas Schneider <asn@samba.org>
14 Reviewed-by: Guenther Deschner <gd@samba.org>
15 (cherry picked from commit 7cabd89789a50d37fc32735968c493092a37e69f)
17 source3/printing/nt_printing_ads.c | 209 ++++++++++++++++++++++++-------------
18 1 file changed, 137 insertions(+), 72 deletions(-)
20 diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c
21 index bf309b0..25e1ab6 100644
22 --- a/source3/printing/nt_printing_ads.c
23 +++ b/source3/printing/nt_printing_ads.c
24 @@ -87,6 +87,128 @@ done:
28 +static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx,
30 + const char *printer,
33 + char *printer_dn = NULL;
34 + char *srv_dn = NULL;
35 + char *srv_cn_0 = NULL;
36 + char *srv_cn_escaped = NULL;
37 + char *sharename_escaped = NULL;
38 + char *srv_dn_utf8 = NULL;
39 + char **srv_cn_utf8 = NULL;
40 + size_t converted_size;
41 + ADS_STATUS ads_status;
46 + ads_status = ads_find_machine_acct(ads, &res, global_myname());
47 + if (!ADS_ERR_OK(ads_status)) {
48 + DEBUG(2, ("Failed to find machine account for %s\n",
50 + result = WERR_NOT_FOUND;
55 + * We use ldap_get_dn here as we need the answer in utf8 to call
56 + * ldap_explode_dn(). JRA.
58 + srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
59 + ads_msgfree(ads, res);
60 + if (srv_dn_utf8 == NULL) {
61 + result = WERR_SERVER_UNAVAILABLE;
65 + srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
66 + if (srv_cn_utf8 == NULL) {
67 + ldap_memfree(srv_dn_utf8);
68 + result = WERR_SERVER_UNAVAILABLE;
72 + /* Now convert to CH_UNIX. */
73 + ok = pull_utf8_talloc(mem_ctx, &srv_dn, srv_dn_utf8, &converted_size);
74 + ldap_memfree(srv_dn_utf8);
76 + ldap_memfree(srv_cn_utf8);
77 + result = WERR_SERVER_UNAVAILABLE;
81 + ok = pull_utf8_talloc(mem_ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size);
82 + ldap_memfree(srv_cn_utf8);
84 + result = WERR_SERVER_UNAVAILABLE;
88 + srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
89 + if (srv_cn_escaped == NULL) {
90 + result = WERR_SERVER_UNAVAILABLE;
94 + sharename_escaped = escape_rdn_val_string_alloc(printer);
95 + if (sharename_escaped == NULL) {
96 + result = WERR_SERVER_UNAVAILABLE;
100 + printer_dn = talloc_asprintf(mem_ctx,
105 + if (printer_dn == NULL) {
106 + result = WERR_NOMEM;
110 + *pprinter_dn = printer_dn;
114 + SAFE_FREE(sharename_escaped);
115 + SAFE_FREE(srv_cn_escaped);
116 + TALLOC_FREE(srv_cn_0);
117 + TALLOC_FREE(srv_dn);
121 +static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads,
122 + const char *printer_dn,
123 + struct GUID *pguid)
125 + ADS_STATUS ads_status;
127 + const char *attrs[] = {"objectGUID", NULL};
131 + ads_status = ads_search_dn(ads, &res, printer_dn, attrs);
132 + if (!ADS_ERR_OK(ads_status)) {
133 + DEBUG(2, ("Failed to retrieve GUID from DC - %s\n",
134 + ads_errstr(ads_status)));
135 + return WERR_BADFILE;
139 + ok = ads_pull_guid(ads, res, &guid);
140 + ads_msgfree(ads, res);
150 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
151 const struct auth_serversupplied_info *session_info,
152 struct messaging_context *msg_ctx,
153 @@ -246,16 +368,12 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
154 struct spoolss_PrinterInfo2 *pinfo2)
158 - char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
159 - char *srv_dn_utf8, **srv_cn_utf8;
162 - const char *attrs[] = {"objectGUID", NULL};
164 WERROR win_rc = WERR_OK;
165 - size_t converted_size;
166 const char *printer = pinfo2->sharename;
167 + char *printer_dn = NULL;
169 /* build the ads mods */
170 ctx = talloc_init("nt_printer_publish_ads");
171 @@ -265,65 +383,13 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
173 DEBUG(5, ("publishing printer %s\n", printer));
175 - /* figure out where to publish */
176 - ads_rc = ads_find_machine_acct(ads, &res, global_myname());
177 - if (!ADS_ERR_OK(ads_rc)) {
178 - DEBUG(0, ("failed to find machine account for %s\n",
181 - return WERR_NOT_FOUND;
184 - /* We use ldap_get_dn here as we need the answer
185 - * in utf8 to call ldap_explode_dn(). JRA. */
187 - srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
188 - ads_msgfree(ads, res);
189 - if (!srv_dn_utf8) {
191 - return WERR_SERVER_UNAVAILABLE;
193 - srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
194 - if (!srv_cn_utf8) {
196 - ldap_memfree(srv_dn_utf8);
197 - return WERR_SERVER_UNAVAILABLE;
199 - /* Now convert to CH_UNIX. */
200 - if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
202 - ldap_memfree(srv_dn_utf8);
203 - ldap_memfree(srv_cn_utf8);
204 - return WERR_SERVER_UNAVAILABLE;
206 - if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
208 - ldap_memfree(srv_dn_utf8);
209 - ldap_memfree(srv_cn_utf8);
210 - TALLOC_FREE(srv_dn);
211 - return WERR_SERVER_UNAVAILABLE;
214 - ldap_memfree(srv_dn_utf8);
215 - ldap_memfree(srv_cn_utf8);
217 - srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
218 - if (!srv_cn_escaped) {
220 - return WERR_SERVER_UNAVAILABLE;
222 - sharename_escaped = escape_rdn_val_string_alloc(printer);
223 - if (!sharename_escaped) {
224 - SAFE_FREE(srv_cn_escaped);
225 + win_rc = nt_printer_dn_lookup(ctx, ads, printer, &printer_dn);
226 + if (!W_ERROR_IS_OK(win_rc)) {
227 + DEBUG(2, ("Failed to create printer dn\n"));
229 - return WERR_SERVER_UNAVAILABLE;
233 - prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
235 - SAFE_FREE(srv_cn_escaped);
236 - SAFE_FREE(sharename_escaped);
238 mods = ads_init_mods(ctx);
241 @@ -338,13 +404,13 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
245 - ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
246 + ads_rc = ads_mod_printer_entry(ads, printer_dn, ctx, &mods);
247 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
249 for (i=0; mods[i] != 0; i++)
251 mods[i] = (LDAPMod *)-1;
252 - ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
253 + ads_rc = ads_add_printer_entry(ads, printer_dn, ctx, &mods);
256 if (!ADS_ERR_OK(ads_rc)) {
257 @@ -352,16 +418,15 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
258 printer, ads_errstr(ads_rc)));
261 - /* retreive the guid and store it locally */
262 - if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
265 - guid_ok = ads_pull_guid(ads, res, &guid);
266 - ads_msgfree(ads, res);
268 - store_printer_guid(msg_ctx, printer, guid);
270 + win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid);
271 + if (!W_ERROR_IS_OK(win_rc)) {
276 + /* TODO add a return value */
277 + store_printer_guid(msg_ctx, printer, guid);
286 From 45bb946d93deaf4926754cf57454f79869e8bfaf Mon Sep 17 00:00:00 2001
287 From: David Disseldorp <ddiss@samba.org>
288 Date: Thu, 18 Dec 2014 18:23:11 +0100
289 Subject: [PATCH 2/4] PATCHSET16: printing: add nt_printer_guid_retrieve()
292 This function connects to the domain controller and retrieves the
293 GUID for the corresponding printer DN.
295 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018
297 Pair-programmed-with: Andreas Schneider <asn@samba.org>
298 Signed-off-by: David Disseldorp <ddiss@samba.org>
299 Signed-off-by: Andreas Schneider <asn@samba.org>
300 Reviewed-by: Guenther Deschner <gd@samba.org>
301 (cherry picked from commit 38dbd054dc331a441b10fdebbdb4bd0fc51cfc0a)
303 source3/include/nt_printing.h | 3 ++
304 source3/printing/nt_printing_ads.c | 58 ++++++++++++++++++++++++++++++++++++++
305 2 files changed, 61 insertions(+)
307 diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h
308 index cdbad87..67a0522 100644
309 --- a/source3/include/nt_printing.h
310 +++ b/source3/include/nt_printing.h
311 @@ -132,6 +132,9 @@ bool print_access_check(const struct auth_serversupplied_info *server_info,
312 struct messaging_context *msg_ctx, int snum,
315 +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
316 + struct GUID *pguid);
318 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
319 const struct auth_serversupplied_info *server_info,
320 struct messaging_context *msg_ctx,
321 diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c
322 index 25e1ab6..6fa4bfc 100644
323 --- a/source3/printing/nt_printing_ads.c
324 +++ b/source3/printing/nt_printing_ads.c
325 @@ -209,6 +209,58 @@ static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads,
329 +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
330 + struct GUID *pguid)
332 + ADS_STRUCT *ads = NULL;
333 + char *old_krb5ccname = NULL;
336 + ADS_STATUS ads_status;
337 + TALLOC_CTX *tmp_ctx;
339 + tmp_ctx = talloc_new(mem_ctx);
340 + if (tmp_ctx == NULL) {
344 + ads = ads_init(lp_realm(), lp_workgroup(), NULL);
346 + result = WERR_SERVER_UNAVAILABLE;
350 + old_krb5ccname = getenv(KRB5_ENV_CCNAME);
351 + setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
352 + SAFE_FREE(ads->auth.password);
353 + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
356 + ads_status = ads_connect(ads);
357 + if (!ADS_ERR_OK(ads_status)) {
358 + DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_status)));
359 + result = WERR_ACCESS_DENIED;
363 + result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn);
364 + if (!W_ERROR_IS_OK(result)) {
368 + result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid);
370 + TALLOC_FREE(tmp_ctx);
372 + ads_kdestroy("MEMORY:prtpub_cache");
373 + unsetenv(KRB5_ENV_CCNAME);
374 + if (old_krb5ccname != NULL) {
375 + setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
381 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
382 const struct auth_serversupplied_info *session_info,
383 struct messaging_context *msg_ctx,
384 @@ -652,6 +704,12 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
388 +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
389 + struct GUID *pguid)
391 + return WERR_NOT_SUPPORTED;
394 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
395 const struct auth_serversupplied_info *session_info,
396 struct messaging_context *msg_ctx,
401 From 228323b1c846d6dfcd39e23c8ce850c79f339de9 Mon Sep 17 00:00:00 2001
402 From: Andreas Schneider <asn@samba.org>
403 Date: Thu, 18 Dec 2014 15:13:27 +0000
404 Subject: [PATCH 3/4] PATCHSET16: printing: rework nt_printer_guid_store to
407 Callers can now choose whether or not to ignore errors.
409 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018
411 Pair-programmed-with: David Disseldorp <ddiss@samba.org>
412 Signed-off-by: Andreas Schneider <asn@samba.org>
413 Signed-off-by: David Disseldorp <ddiss@samba.org>
414 Reviewed-by: Guenther Deschner <gd@samba.org>
415 (cherry picked from commit 6595ced146a53dcef9bbd5d2deb82a44c8ce1a1a)
417 source3/include/nt_printing.h | 3 +++
418 source3/printing/nt_printing_ads.c | 49 +++++++++++++++++++++++++-------------
419 2 files changed, 35 insertions(+), 17 deletions(-)
421 diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h
422 index 67a0522..493f4ce 100644
423 --- a/source3/include/nt_printing.h
424 +++ b/source3/include/nt_printing.h
425 @@ -135,6 +135,9 @@ bool print_access_check(const struct auth_serversupplied_info *server_info,
426 WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
429 +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
430 + const char *printer, struct GUID guid);
432 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
433 const struct auth_serversupplied_info *server_info,
434 struct messaging_context *msg_ctx,
435 diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c
436 index 6fa4bfc..540a8a3 100644
437 --- a/source3/printing/nt_printing_ads.c
438 +++ b/source3/printing/nt_printing_ads.c
440 /*****************************************************************
441 ****************************************************************/
443 -static void store_printer_guid(struct messaging_context *msg_ctx,
444 - const char *printer, struct GUID guid)
445 +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
446 + const char *printer, struct GUID guid)
449 - struct auth_serversupplied_info *session_info = NULL;
450 + const struct auth_serversupplied_info *session_info;
451 const char *guid_str;
456 tmp_ctx = talloc_new(NULL);
458 - DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
460 + DEBUG(0, ("Out of memory?!\n"));
464 - status = make_session_info_system(tmp_ctx, &session_info);
465 - if (!NT_STATUS_IS_OK(status)) {
466 - DEBUG(0, ("store_printer_guid: "
467 - "Could not create system session_info\n"));
468 + session_info = get_session_info_system();
469 + if (session_info == NULL) {
470 + DEBUG(0, ("Could not get system session_info\n"));
471 + result = WERR_NOMEM;
475 guid_str = GUID_string(tmp_ctx, &guid);
477 - DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
478 + DEBUG(0, ("Out of memory?!\n"));
479 + result = WERR_NOMEM;
483 @@ -68,9 +68,9 @@ static void store_printer_guid(struct messaging_context *msg_ctx,
486 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
487 - DEBUG(0, ("store_printer_guid: "
488 - "Could not marshall string %s for objectGUID\n",
489 + DEBUG(0, ("Could not marshall string %s for objectGUID\n",
491 + result = WERR_NOMEM;
495 @@ -79,12 +79,15 @@ static void store_printer_guid(struct messaging_context *msg_ctx,
496 SPOOL_DSSPOOLER_KEY, "objectGUID",
497 REG_SZ, blob.data, blob.length);
498 if (!W_ERROR_IS_OK(result)) {
499 - DEBUG(0, ("store_printer_guid: "
500 - "Failed to store GUID for printer %s\n", printer));
501 + DEBUG(0, ("Failed to store GUID for printer %s\n", printer));
507 talloc_free(tmp_ctx);
512 static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx,
513 @@ -468,6 +471,7 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
514 if (!ADS_ERR_OK(ads_rc)) {
515 DEBUG(3, ("error publishing %s: %s\n",
516 printer, ads_errstr(ads_rc)));
517 + /* XXX failed to publish, so no guid to retrieve */
520 win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid);
521 @@ -476,8 +480,13 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
525 - /* TODO add a return value */
526 - store_printer_guid(msg_ctx, printer, guid);
527 + win_rc = nt_printer_guid_store(msg_ctx, printer, guid);
528 + if (!W_ERROR_IS_OK(win_rc)) {
529 + DEBUG(3, ("failed to store printer %s guid\n",
531 + /* not catastrophic, retrieve on next use */
537 @@ -704,6 +713,12 @@ bool is_printer_published(TALLOC_CTX *mem_ctx,
541 +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
542 + const char *printer, struct GUID guid)
544 + return WERR_NOT_SUPPORTED;
547 WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
554 From d4847deadc4cd6f4f8071fae16d05bc8ec4ed566 Mon Sep 17 00:00:00 2001
555 From: Andreas Schneider <asn@samba.org>
556 Date: Thu, 18 Dec 2014 15:14:36 +0000
557 Subject: [PATCH 4/4] PATCHSET16: spoolss: retrieve published printer GUID if
560 Content-Type: text/plain; charset=UTF-8
561 Content-Transfer-Encoding: 8bit
563 When a printer is published, the GUID for the published DN is retrieved
564 from the domain controller and stored in the registry.
565 When handling a spoolss GetPrinter(level=7) request, the same GUID is
566 obtained from the registry and returned to the client.
568 This change sees the spoolss server query the DC for the published
569 printer GUID if it is not present in the registry when handling a
570 spoolss GetPrinter(level=7) request.
572 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018
574 Pair-Programmed-With: David Disseldorp <ddiss@samba.org>
575 Signed-off-by: Andreas Schneider <asn@samba.org>
576 Signed-off-by: David Disseldorp <ddiss@samba.org>
577 Reviewed-by: Guenther Deschner <gd@samba.org>
579 Autobuild-User(master): Günther Deschner <gd@samba.org>
580 Autobuild-Date(master): Wed Feb 18 12:43:44 CET 2015 on sn-devel-104
582 (cherry picked from commit a4157e7c5d75be7003ad0b72fdfe9856a9e5ba8f)
584 source3/rpc_server/spoolss/srv_spoolss_nt.c | 20 +++++++++++++++++++-
585 1 file changed, 19 insertions(+), 1 deletion(-)
587 diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
588 index 0c4b582..516b7dc 100644
589 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
590 +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
591 @@ -4213,7 +4213,25 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
592 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
594 if (!W_ERROR_IS_OK(werr)) {
597 + * If we do not have a GUID entry in the registry, then
598 + * try to retrieve it from AD and store it now.
600 + werr = nt_printer_guid_retrieve(tmp_ctx, printer,
602 + if (!W_ERROR_IS_OK(werr)) {
603 + DEBUG(1, ("Failed to retrieve GUID for "
604 + "printer [%s] from AD - "
605 + "Is the the printer still "
606 + "published ?\n", printer));
610 + werr = nt_printer_guid_store(msg_ctx, printer, guid);
611 + if (!W_ERROR_IS_OK(werr)) {
612 + DEBUG(3, ("failed to store printer %s guid\n",
616 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
617 r->action = DSPRINT_PUBLISH;