The branch, master has been updated via a4157e7 spoolss: retrieve published printer GUID if not in registry via 6595ced printing: rework nt_printer_guid_store to return errors via 38dbd05 printing: add nt_printer_guid_retrieve() helper via 7cabd89 printing: split out printer DN and GUID retrieval from dc32f11 ctdb-scripts: Improve messages about invalid tunables during "setup"
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit a4157e7c5d75be7003ad0b72fdfe9856a9e5ba8f Author: Andreas Schneider <a...@samba.org> Date: Thu Dec 18 15:14:36 2014 +0000 spoolss: retrieve published printer GUID if not in registry When a printer is published, the GUID for the published DN is retrieved from the domain controller and stored in the registry. When handling a spoolss GetPrinter(level=7) request, the same GUID is obtained from the registry and returned to the client. This change sees the spoolss server query the DC for the published printer GUID if it is not present in the registry when handling a spoolss GetPrinter(level=7) request. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018 Pair-Programmed-With: David Disseldorp <dd...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Guenther Deschner <g...@samba.org> Autobuild-User(master): Günther Deschner <g...@samba.org> Autobuild-Date(master): Wed Feb 18 12:43:44 CET 2015 on sn-devel-104 commit 6595ced146a53dcef9bbd5d2deb82a44c8ce1a1a Author: Andreas Schneider <a...@samba.org> Date: Thu Dec 18 15:13:27 2014 +0000 printing: rework nt_printer_guid_store to return errors Callers can now choose whether or not to ignore errors. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018 Pair-programmed-with: David Disseldorp <dd...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Guenther Deschner <g...@samba.org> commit 38dbd054dc331a441b10fdebbdb4bd0fc51cfc0a Author: David Disseldorp <dd...@samba.org> Date: Thu Dec 18 18:23:11 2014 +0100 printing: add nt_printer_guid_retrieve() helper This function connects to the domain controller and retrieves the GUID for the corresponding printer DN. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018 Pair-programmed-with: Andreas Schneider <a...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Guenther Deschner <g...@samba.org> commit 7cabd89789a50d37fc32735968c493092a37e69f Author: David Disseldorp <dd...@samba.org> Date: Thu Dec 18 18:18:21 2014 +0100 printing: split out printer DN and GUID retrieval This functions are used for printer publishing. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11018 Pair-programmed-with: Andreas Schneider <a...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Guenther Deschner <g...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/include/nt_printing.h | 6 + source3/printing/nt_printing_ads.c | 312 ++++++++++++++++++++-------- source3/rpc_server/spoolss/srv_spoolss_nt.c | 24 ++- 3 files changed, 253 insertions(+), 89 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/include/nt_printing.h b/source3/include/nt_printing.h index 4af44d7..bfb6f8e 100644 --- a/source3/include/nt_printing.h +++ b/source3/include/nt_printing.h @@ -132,6 +132,12 @@ WERROR print_access_check(const struct auth_session_info *server_info, struct messaging_context *msg_ctx, int snum, int access_type); +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer, + struct GUID *pguid); + +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx, + const char *printer, struct GUID guid); + WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx, const struct auth_session_info *session_info, struct messaging_context *msg_ctx, diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c index 5a5a177..679b950 100644 --- a/source3/printing/nt_printing_ads.c +++ b/source3/printing/nt_printing_ads.c @@ -35,32 +35,32 @@ /***************************************************************** ****************************************************************/ -static void store_printer_guid(struct messaging_context *msg_ctx, - const char *printer, struct GUID guid) +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx, + const char *printer, struct GUID guid) { TALLOC_CTX *tmp_ctx; - struct auth_session_info *session_info = NULL; + const struct auth_session_info *session_info; const char *guid_str; DATA_BLOB blob; - NTSTATUS status; WERROR result; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { - DEBUG(0, ("store_printer_guid: Out of memory?!\n")); - return; + DEBUG(0, ("Out of memory?!\n")); + return WERR_NOMEM; } - status = make_session_info_system(tmp_ctx, &session_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("store_printer_guid: " - "Could not create system session_info\n")); + session_info = get_session_info_system(); + if (session_info == NULL) { + DEBUG(0, ("Could not get system session_info\n")); + result = WERR_NOMEM; goto done; } guid_str = GUID_string(tmp_ctx, &guid); if (!guid_str) { - DEBUG(0, ("store_printer_guid: Out of memory?!\n")); + DEBUG(0, ("Out of memory?!\n")); + result = WERR_NOMEM; goto done; } @@ -68,9 +68,9 @@ static void store_printer_guid(struct messaging_context *msg_ctx, Vista to whine */ if (!push_reg_sz(tmp_ctx, &blob, guid_str)) { - DEBUG(0, ("store_printer_guid: " - "Could not marshall string %s for objectGUID\n", + DEBUG(0, ("Could not marshall string %s for objectGUID\n", guid_str)); + result = WERR_NOMEM; goto done; } @@ -79,12 +79,189 @@ static void store_printer_guid(struct messaging_context *msg_ctx, SPOOL_DSSPOOLER_KEY, "objectGUID", REG_SZ, blob.data, blob.length); if (!W_ERROR_IS_OK(result)) { - DEBUG(0, ("store_printer_guid: " - "Failed to store GUID for printer %s\n", printer)); + DEBUG(0, ("Failed to store GUID for printer %s\n", printer)); + goto done; } + result = WERR_OK; done: talloc_free(tmp_ctx); + + return result; +} + +static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx, + ADS_STRUCT *ads, + const char *printer, + char **pprinter_dn) +{ + char *printer_dn = NULL; + char *srv_dn = NULL; + char *srv_cn_0 = NULL; + char *srv_cn_escaped = NULL; + char *sharename_escaped = NULL; + char *srv_dn_utf8 = NULL; + char **srv_cn_utf8 = NULL; + size_t converted_size; + ADS_STATUS ads_status; + LDAPMessage *res; + WERROR result; + bool ok; + + ads_status = ads_find_machine_acct(ads, &res, lp_netbios_name()); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(2, ("Failed to find machine account for %s\n", + lp_netbios_name())); + result = WERR_NOT_FOUND; + goto err_out; + } + + /* + * We use ldap_get_dn here as we need the answer in utf8 to call + * ldap_explode_dn(). JRA. + */ + srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); + ads_msgfree(ads, res); + if (srv_dn_utf8 == NULL) { + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); + if (srv_cn_utf8 == NULL) { + ldap_memfree(srv_dn_utf8); + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + /* Now convert to CH_UNIX. */ + ok = pull_utf8_talloc(mem_ctx, &srv_dn, srv_dn_utf8, &converted_size); + ldap_memfree(srv_dn_utf8); + if (!ok) { + ldap_memfree(srv_cn_utf8); + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + ok = pull_utf8_talloc(mem_ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size); + ldap_memfree(srv_cn_utf8); + if (!ok) { + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); + if (srv_cn_escaped == NULL) { + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + sharename_escaped = escape_rdn_val_string_alloc(printer); + if (sharename_escaped == NULL) { + result = WERR_SERVER_UNAVAILABLE; + goto err_out; + } + + printer_dn = talloc_asprintf(mem_ctx, + "cn=%s-%s,%s", + srv_cn_escaped, + sharename_escaped, + srv_dn); + if (printer_dn == NULL) { + result = WERR_NOMEM; + goto err_out; + } + + *pprinter_dn = printer_dn; + + result = WERR_OK; +err_out: + SAFE_FREE(sharename_escaped); + SAFE_FREE(srv_cn_escaped); + TALLOC_FREE(srv_cn_0); + TALLOC_FREE(srv_dn); + return result; +} + +static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads, + const char *printer_dn, + struct GUID *pguid) +{ + ADS_STATUS ads_status; + LDAPMessage *res; + const char *attrs[] = {"objectGUID", NULL}; + struct GUID guid; + bool ok; + + ads_status = ads_search_dn(ads, &res, printer_dn, attrs); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(2, ("Failed to retrieve GUID from DC - %s\n", + ads_errstr(ads_status))); + return WERR_BADFILE; + } + + ZERO_STRUCT(guid); + ok = ads_pull_guid(ads, res, &guid); + ads_msgfree(ads, res); + if (!ok) { + return WERR_NOMEM; + } + + *pguid = guid; + + return WERR_OK; +} + +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer, + struct GUID *pguid) +{ + ADS_STRUCT *ads = NULL; + char *old_krb5ccname = NULL; + char *printer_dn; + WERROR result; + ADS_STATUS ads_status; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return WERR_NOMEM; + } + + ads = ads_init(lp_realm(), lp_workgroup(), NULL); + if (ads == NULL) { + result = WERR_SERVER_UNAVAILABLE; + goto out; + } + + old_krb5ccname = getenv(KRB5_ENV_CCNAME); + setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); + SAFE_FREE(ads->auth.password); + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), + NULL, NULL); + + ads_status = ads_connect(ads); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_status))); + result = WERR_ACCESS_DENIED; + goto out; + } + + result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn); + if (!W_ERROR_IS_OK(result)) { + goto out; + } + + result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid); +out: + TALLOC_FREE(tmp_ctx); + ads_destroy(&ads); + ads_kdestroy("MEMORY:prtpub_cache"); + unsetenv(KRB5_ENV_CCNAME); + if (old_krb5ccname != NULL) { + setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0); + } + + return result; } WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx, @@ -246,16 +423,12 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx, struct spoolss_PrinterInfo2 *pinfo2) { ADS_STATUS ads_rc; - LDAPMessage *res; - char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped; - char *srv_dn_utf8, **srv_cn_utf8; TALLOC_CTX *ctx; ADS_MODLIST mods; - const char *attrs[] = {"objectGUID", NULL}; struct GUID guid; WERROR win_rc = WERR_OK; - size_t converted_size; const char *printer = pinfo2->sharename; + char *printer_dn = NULL; /* build the ads mods */ ctx = talloc_init("nt_printer_publish_ads"); @@ -265,65 +438,13 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx, DEBUG(5, ("publishing printer %s\n", printer)); - /* figure out where to publish */ - ads_rc = ads_find_machine_acct(ads, &res, lp_netbios_name()); - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(0, ("failed to find machine account for %s\n", - lp_netbios_name())); - TALLOC_FREE(ctx); - return WERR_NOT_FOUND; - } - - /* We use ldap_get_dn here as we need the answer - * in utf8 to call ldap_explode_dn(). JRA. */ - - srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res); - ads_msgfree(ads, res); - if (!srv_dn_utf8) { - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); - if (!srv_cn_utf8) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - return WERR_SERVER_UNAVAILABLE; - } - /* Now convert to CH_UNIX. */ - if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - return WERR_SERVER_UNAVAILABLE; - } - if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) { - TALLOC_FREE(ctx); - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - TALLOC_FREE(srv_dn); - return WERR_SERVER_UNAVAILABLE; - } - - ldap_memfree(srv_dn_utf8); - ldap_memfree(srv_cn_utf8); - - srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0); - if (!srv_cn_escaped) { - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - sharename_escaped = escape_rdn_val_string_alloc(printer); - if (!sharename_escaped) { - SAFE_FREE(srv_cn_escaped); + win_rc = nt_printer_dn_lookup(ctx, ads, printer, &printer_dn); + if (!W_ERROR_IS_OK(win_rc)) { + DEBUG(2, ("Failed to create printer dn\n")); TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; + return win_rc; } - prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn); - - SAFE_FREE(srv_cn_escaped); - SAFE_FREE(sharename_escaped); - mods = ads_init_mods(ctx); if (mods == NULL) { @@ -338,30 +459,35 @@ static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx, } /* publish it */ - ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods); + ads_rc = ads_mod_printer_entry(ads, printer_dn, ctx, &mods); if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) { int i; for (i=0; mods[i] != 0; i++) ; mods[i] = (LDAPMod *)-1; - ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); + ads_rc = ads_add_printer_entry(ads, printer_dn, ctx, &mods); } if (!ADS_ERR_OK(ads_rc)) { DEBUG(3, ("error publishing %s: %s\n", printer, ads_errstr(ads_rc))); + /* XXX failed to publish, so no guid to retrieve */ } - /* retreive the guid and store it locally */ - if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { - bool guid_ok; - ZERO_STRUCT(guid); - guid_ok = ads_pull_guid(ads, res, &guid); - ads_msgfree(ads, res); - if (guid_ok) { - store_printer_guid(msg_ctx, printer, guid); - } + win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid); + if (!W_ERROR_IS_OK(win_rc)) { + TALLOC_FREE(ctx); + return win_rc; + } + + win_rc = nt_printer_guid_store(msg_ctx, printer, guid); + if (!W_ERROR_IS_OK(win_rc)) { + DEBUG(3, ("failed to store printer %s guid\n", + printer)); + /* not catastrophic, retrieve on next use */ + win_rc = WERR_OK; } + TALLOC_FREE(ctx); return win_rc; @@ -600,6 +726,18 @@ bool is_printer_published(TALLOC_CTX *mem_ctx, return true; } #else +WERROR nt_printer_guid_store(struct messaging_context *msg_ctx, + const char *printer, struct GUID guid) +{ + return WERR_NOT_SUPPORTED; +} + +WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer, + struct GUID *pguid) +{ + return WERR_NOT_SUPPORTED; +} + WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx, const struct auth_session_info *session_info, struct messaging_context *msg_ctx, diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c index 115af2d..a195eb6 100644 --- a/source3/rpc_server/spoolss/srv_spoolss_nt.c +++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c @@ -4234,12 +4234,32 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx, if (is_printer_published(tmp_ctx, session_info, msg_ctx, servername, printer, NULL)) { struct GUID guid; + struct GUID_txt_buf guid_txt; werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx, printer, &guid); if (!W_ERROR_IS_OK(werr)) { - goto out_tmp_free; + /* + * If we do not have a GUID entry in the registry, then + * try to retrieve it from AD and store it now. + */ + werr = nt_printer_guid_retrieve(tmp_ctx, printer, + &guid); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(1, ("Failed to retrieve GUID for " + "printer [%s] from AD - " + "Is the the printer still " + "published ?\n", printer)); + goto out_tmp_free; + } + + werr = nt_printer_guid_store(msg_ctx, printer, guid); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(3, ("failed to store printer %s guid\n", + printer)); + } } - r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid)); + r->guid = talloc_strdup_upper(mem_ctx, + GUID_buf_string(&guid, &guid_txt)); r->action = DSPRINT_PUBLISH; } else { r->guid = talloc_strdup(mem_ctx, ""); -- Samba Shared Repository