diff options
author | Günther Deschner <gd@samba.org> | 2010-08-04 15:31:08 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2010-08-05 00:32:02 +0200 |
commit | 31c484edb95c09b0b400cff9bab6b6cb2c33b120 (patch) | |
tree | c034151dfad4715ea873edf9d287845018db6936 | |
parent | 867626abcad88b84684e9d328abf51d4f410a1cb (diff) | |
download | samba-31c484edb95c09b0b400cff9bab6b6cb2c33b120.tar.gz samba-31c484edb95c09b0b400cff9bab6b6cb2c33b120.tar.bz2 samba-31c484edb95c09b0b400cff9bab6b6cb2c33b120.zip |
s3-printing: move AD related printing components to an own file.
Guenther
-rw-r--r-- | source3/Makefile.in | 10 | ||||
-rw-r--r-- | source3/printing/nt_printing.c | 440 | ||||
-rw-r--r-- | source3/printing/nt_printing_ads.c | 466 | ||||
-rw-r--r-- | source3/wscript_build | 12 |
4 files changed, 481 insertions, 447 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index bf2646dc59..128ff8c4b6 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -863,9 +863,13 @@ PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \ printing/print_iprint.o printing/print_standard.o PRINTBASE_OBJ = printing/notify.o printing/printing_db.o -PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o \ - printing/nt_printing_tdb.o printing/nt_printing_migrate.o \ - librpc/gen_ndr/ndr_ntprinting.o ../librpc/ndr/ndr_ntprinting.o \ +PRINTBACKEND_OBJ = printing/printing.o \ + printing/nt_printing.o \ + printing/nt_printing_tdb.o \ + printing/nt_printing_migrate.o \ + printing/nt_printing_ads.o \ + librpc/gen_ndr/ndr_ntprinting.o \ + ../librpc/ndr/ndr_ntprinting.o \ $(PRINTBASE_OBJ) SMBD_OBJ = $(SMBD_OBJ_BASE) $(SMBD_OBJ_MAIN) diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index f0460f31c2..a831ef220e 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1312,446 +1312,6 @@ WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx, return WERR_OK; } -#ifdef HAVE_ADS -/***************************************************************** - ****************************************************************/ - -static void store_printer_guid(const char *printer, struct GUID guid) -{ - TALLOC_CTX *tmp_ctx; - struct auth_serversupplied_info *server_info = NULL; - 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; - } - - status = make_server_info_system(tmp_ctx, &server_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("store_printer_guid: " - "Could not create system server_info\n")); - goto done; - } - - guid_str = GUID_string(tmp_ctx, &guid); - if (!guid_str) { - DEBUG(0, ("store_printer_guid: Out of memory?!\n")); - goto done; - } - - /* We used to store this as a REG_BINARY but that causes - 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", - guid_str)); - goto done; - } - - result = winreg_set_printer_dataex(tmp_ctx, server_info, printer, - 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)); - } - -done: - talloc_free(tmp_ctx); -} - -static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, - 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; - - /* build the ads mods */ - ctx = talloc_init("nt_printer_publish_ads"); - if (ctx == NULL) { - return WERR_NOMEM; - } - - DEBUG(5, ("publishing printer %s\n", printer)); - - /* figure out where to publish */ - ads_find_machine_acct(ads, &res, global_myname()); - - /* 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); - if (!srv_dn_utf8) { - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - ads_msgfree(ads, res); - 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); - TALLOC_FREE(ctx); - return WERR_SERVER_UNAVAILABLE; - } - - 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) { - SAFE_FREE(prt_dn); - TALLOC_FREE(ctx); - return WERR_NOMEM; - } - - ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer); - - /* publish it */ - ads_rc = ads_mod_printer_entry(ads, prt_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); - } - - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(3, ("error publishing %s: %s\n", - printer, ads_errstr(ads_rc))); - } - - /* retreive the guid and store it locally */ - if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { - ZERO_STRUCT(guid); - ads_pull_guid(ads, res, &guid); - ads_msgfree(ads, res); - store_printer_guid(printer, guid); - } - TALLOC_FREE(ctx); - - return win_rc; -} - -static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, - const char *printer) -{ - ADS_STATUS ads_rc; - LDAPMessage *res = NULL; - char *prt_dn = NULL; - - DEBUG(5, ("unpublishing printer %s\n", printer)); - - /* remove the printer from the directory */ - ads_rc = ads_find_printer_on_server(ads, &res, - printer, global_myname()); - - if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { - prt_dn = ads_get_dn(ads, talloc_tos(), res); - if (!prt_dn) { - ads_msgfree(ads, res); - return WERR_NOMEM; - } - ads_rc = ads_del_dn(ads, prt_dn); - TALLOC_FREE(prt_dn); - } - - if (res) { - ads_msgfree(ads, res); - } - return WERR_OK; -} - -/**************************************************************************** - * Publish a printer in the directory - * - * @param mem_ctx memory context - * @param server_info server_info to access winreg pipe - * @param pinfo2 printer information - * @param action publish/unpublish action - * @return WERROR indicating status of publishing - ***************************************************************************/ - -WERROR nt_printer_publish(TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info *server_info, - struct spoolss_PrinterInfo2 *pinfo2, - int action) -{ - uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES; - struct spoolss_SetPrinterInfo2 *sinfo2; - ADS_STATUS ads_rc; - ADS_STRUCT *ads = NULL; - WERROR win_rc; - - sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2); - if (!sinfo2) { - return WERR_NOMEM; - } - - switch (action) { - case DSPRINT_PUBLISH: - case DSPRINT_UPDATE: - pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; - break; - case DSPRINT_UNPUBLISH: - pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; - break; - default: - win_rc = WERR_NOT_SUPPORTED; - goto done; - } - - sinfo2->attributes = pinfo2->attributes; - - win_rc = winreg_update_printer(mem_ctx, server_info, - pinfo2->sharename, info2_mask, - sinfo2, NULL, NULL); - if (!W_ERROR_IS_OK(win_rc)) { - DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc))); - goto done; - } - - TALLOC_FREE(sinfo2); - - ads = ads_init(lp_realm(), lp_workgroup(), NULL); - if (!ads) { - DEBUG(3, ("ads_init() failed\n")); - win_rc = WERR_SERVER_UNAVAILABLE; - goto done; - } - 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_connect() will find the DC for us */ - ads_rc = ads_connect(ads); - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); - win_rc = WERR_ACCESS_DENIED; - goto done; - } - - switch (action) { - case DSPRINT_PUBLISH: - case DSPRINT_UPDATE: - win_rc = nt_printer_publish_ads(ads, pinfo2); - break; - case DSPRINT_UNPUBLISH: - win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename); - break; - } - -done: - ads_destroy(&ads); - return win_rc; -} - -WERROR check_published_printers(void) -{ - ADS_STATUS ads_rc; - ADS_STRUCT *ads = NULL; - int snum; - int n_services = lp_numservices(); - TALLOC_CTX *tmp_ctx = NULL; - struct auth_serversupplied_info *server_info = NULL; - struct spoolss_PrinterInfo2 *pinfo2; - NTSTATUS status; - WERROR result; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) return WERR_NOMEM; - - ads = ads_init(lp_realm(), lp_workgroup(), NULL); - if (!ads) { - DEBUG(3, ("ads_init() failed\n")); - return WERR_SERVER_UNAVAILABLE; - } - 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_connect() will find the DC for us */ - ads_rc = ads_connect(ads); - if (!ADS_ERR_OK(ads_rc)) { - DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); - result = WERR_ACCESS_DENIED; - goto done; - } - - status = make_server_info_system(tmp_ctx, &server_info); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("check_published_printers: " - "Could not create system server_info\n")); - result = WERR_ACCESS_DENIED; - goto done; - } - - for (snum = 0; snum < n_services; snum++) { - if (!lp_snum_ok(snum) || !lp_print_ok(snum)) { - continue; - } - - result = winreg_get_printer(tmp_ctx, server_info, NULL, - lp_servicename(snum), &pinfo2); - if (!W_ERROR_IS_OK(result)) { - continue; - } - - if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) { - nt_printer_publish_ads(ads, pinfo2); - } - - TALLOC_FREE(pinfo2); - } - - result = WERR_OK; -done: - ads_destroy(&ads); - ads_kdestroy("MEMORY:prtpub_cache"); - talloc_free(tmp_ctx); - return result; -} - -bool is_printer_published(TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info *server_info, - char *servername, char *printer, struct GUID *guid, - struct spoolss_PrinterInfo2 **info2) -{ - struct spoolss_PrinterInfo2 *pinfo2 = NULL; - enum winreg_Type type; - uint8_t *data; - uint32_t data_size; - WERROR result; - NTSTATUS status; - - result = winreg_get_printer(mem_ctx, server_info, - servername, printer, &pinfo2); - if (!W_ERROR_IS_OK(result)) { - return false; - } - - if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) { - TALLOC_FREE(pinfo2); - return false; - } - - if (!guid) { - goto done; - } - - /* fetching printer guids really ought to be a separate function. */ - - result = winreg_get_printer_dataex(mem_ctx, server_info, printer, - SPOOL_DSSPOOLER_KEY, "objectGUID", - &type, &data, &data_size); - if (!W_ERROR_IS_OK(result)) { - TALLOC_FREE(pinfo2); - return false; - } - - /* We used to store the guid as REG_BINARY, then swapped - to REG_SZ for Vista compatibility so check for both */ - - switch (type) { - case REG_SZ: - status = GUID_from_string((char *)data, guid); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(pinfo2); - return false; - } - break; - - case REG_BINARY: - if (data_size != sizeof(struct GUID)) { - TALLOC_FREE(pinfo2); - return false; - } - memcpy(guid, data, sizeof(struct GUID)); - break; - default: - DEBUG(0,("is_printer_published: GUID value stored as " - "invaluid type (%d)\n", type)); - break; - } - -done: - if (info2) { - *info2 = talloc_move(mem_ctx, &pinfo2); - } - talloc_free(pinfo2); - return true; -} -#else -WERROR nt_printer_publish(TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info *server_info, - struct spoolss_PrinterInfo2 *pinfo2, - int action) -{ - return WERR_OK; -} - -WERROR check_published_printers(void) -{ - return WERR_OK; -} - -bool is_printer_published(TALLOC_CTX *mem_ctx, - struct auth_serversupplied_info *server_info, - char *servername, char *printer, struct GUID *guid, - struct spoolss_PrinterInfo2 **info2) -{ - return False; -} -#endif /* HAVE_ADS */ - /**************************************************************************** ***************************************************************************/ diff --git a/source3/printing/nt_printing_ads.c b/source3/printing/nt_printing_ads.c new file mode 100644 index 0000000000..e59f137ed5 --- /dev/null +++ b/source3/printing/nt_printing_ads.c @@ -0,0 +1,466 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Jean François Micouleau 1998-2000. + * Copyright (C) Gerald Carter 2002-2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "../librpc/gen_ndr/spoolss.h" +#include "rpc_server/srv_spoolss_util.h" +#include "nt_printing.h" +#include "ads.h" + +#ifdef HAVE_ADS +/***************************************************************** + ****************************************************************/ + +static void store_printer_guid(const char *printer, struct GUID guid) +{ + TALLOC_CTX *tmp_ctx; + struct auth_serversupplied_info *server_info = NULL; + 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; + } + + status = make_server_info_system(tmp_ctx, &server_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("store_printer_guid: " + "Could not create system server_info\n")); + goto done; + } + + guid_str = GUID_string(tmp_ctx, &guid); + if (!guid_str) { + DEBUG(0, ("store_printer_guid: Out of memory?!\n")); + goto done; + } + + /* We used to store this as a REG_BINARY but that causes + 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", + guid_str)); + goto done; + } + + result = winreg_set_printer_dataex(tmp_ctx, server_info, printer, + 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)); + } + +done: + talloc_free(tmp_ctx); +} + +static WERROR nt_printer_publish_ads(ADS_STRUCT *ads, + 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; + + /* build the ads mods */ + ctx = talloc_init("nt_printer_publish_ads"); + if (ctx == NULL) { + return WERR_NOMEM; + } + + DEBUG(5, ("publishing printer %s\n", printer)); + + /* figure out where to publish */ + ads_find_machine_acct(ads, &res, global_myname()); + + /* 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); + if (!srv_dn_utf8) { + TALLOC_FREE(ctx); + return WERR_SERVER_UNAVAILABLE; + } + ads_msgfree(ads, res); + 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); + TALLOC_FREE(ctx); + return WERR_SERVER_UNAVAILABLE; + } + + 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) { + SAFE_FREE(prt_dn); + TALLOC_FREE(ctx); + return WERR_NOMEM; + } + + ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer); + + /* publish it */ + ads_rc = ads_mod_printer_entry(ads, prt_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); + } + + if (!ADS_ERR_OK(ads_rc)) { + DEBUG(3, ("error publishing %s: %s\n", + printer, ads_errstr(ads_rc))); + } + + /* retreive the guid and store it locally */ + if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { + ZERO_STRUCT(guid); + ads_pull_guid(ads, res, &guid); + ads_msgfree(ads, res); + store_printer_guid(printer, guid); + } + TALLOC_FREE(ctx); + + return win_rc; +} + +static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads, + const char *printer) +{ + ADS_STATUS ads_rc; + LDAPMessage *res = NULL; + char *prt_dn = NULL; + + DEBUG(5, ("unpublishing printer %s\n", printer)); + + /* remove the printer from the directory */ + ads_rc = ads_find_printer_on_server(ads, &res, + printer, global_myname()); + + if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) { + prt_dn = ads_get_dn(ads, talloc_tos(), res); + if (!prt_dn) { + ads_msgfree(ads, res); + return WERR_NOMEM; + } + ads_rc = ads_del_dn(ads, prt_dn); + TALLOC_FREE(prt_dn); + } + + if (res) { + ads_msgfree(ads, res); + } + return WERR_OK; +} + +/**************************************************************************** + * Publish a printer in the directory + * + * @param mem_ctx memory context + * @param server_info server_info to access winreg pipe + * @param pinfo2 printer information + * @param action publish/unpublish action + * @return WERROR indicating status of publishing + ***************************************************************************/ + +WERROR nt_printer_publish(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + struct spoolss_PrinterInfo2 *pinfo2, + int action) +{ + uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES; + struct spoolss_SetPrinterInfo2 *sinfo2; + ADS_STATUS ads_rc; + ADS_STRUCT *ads = NULL; + WERROR win_rc; + + sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2); + if (!sinfo2) { + return WERR_NOMEM; + } + + switch (action) { + case DSPRINT_PUBLISH: + case DSPRINT_UPDATE: + pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; + break; + case DSPRINT_UNPUBLISH: + pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; + break; + default: + win_rc = WERR_NOT_SUPPORTED; + goto done; + } + + sinfo2->attributes = pinfo2->attributes; + + win_rc = winreg_update_printer(mem_ctx, server_info, + pinfo2->sharename, info2_mask, + sinfo2, NULL, NULL); + if (!W_ERROR_IS_OK(win_rc)) { + DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc))); + goto done; + } + + TALLOC_FREE(sinfo2); + + ads = ads_init(lp_realm(), lp_workgroup(), NULL); + if (!ads) { + DEBUG(3, ("ads_init() failed\n")); + win_rc = WERR_SERVER_UNAVAILABLE; + goto done; + } + 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_connect() will find the DC for us */ + ads_rc = ads_connect(ads); + if (!ADS_ERR_OK(ads_rc)) { + DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); + win_rc = WERR_ACCESS_DENIED; + goto done; + } + + switch (action) { + case DSPRINT_PUBLISH: + case DSPRINT_UPDATE: + win_rc = nt_printer_publish_ads(ads, pinfo2); + break; + case DSPRINT_UNPUBLISH: + win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename); + break; + } + +done: + ads_destroy(&ads); + return win_rc; +} + +WERROR check_published_printers(void) +{ + ADS_STATUS ads_rc; + ADS_STRUCT *ads = NULL; + int snum; + int n_services = lp_numservices(); + TALLOC_CTX *tmp_ctx = NULL; + struct auth_serversupplied_info *server_info = NULL; + struct spoolss_PrinterInfo2 *pinfo2; + NTSTATUS status; + WERROR result; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return WERR_NOMEM; + + ads = ads_init(lp_realm(), lp_workgroup(), NULL); + if (!ads) { + DEBUG(3, ("ads_init() failed\n")); + return WERR_SERVER_UNAVAILABLE; + } + 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_connect() will find the DC for us */ + ads_rc = ads_connect(ads); + if (!ADS_ERR_OK(ads_rc)) { + DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); + result = WERR_ACCESS_DENIED; + goto done; + } + + status = make_server_info_system(tmp_ctx, &server_info); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("check_published_printers: " + "Could not create system server_info\n")); + result = WERR_ACCESS_DENIED; + goto done; + } + + for (snum = 0; snum < n_services; snum++) { + if (!lp_snum_ok(snum) || !lp_print_ok(snum)) { + continue; + } + + result = winreg_get_printer(tmp_ctx, server_info, NULL, + lp_servicename(snum), &pinfo2); + if (!W_ERROR_IS_OK(result)) { + continue; + } + + if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) { + nt_printer_publish_ads(ads, pinfo2); + } + + TALLOC_FREE(pinfo2); + } + + result = WERR_OK; +done: + ads_destroy(&ads); + ads_kdestroy("MEMORY:prtpub_cache"); + talloc_free(tmp_ctx); + return result; +} + +bool is_printer_published(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + char *servername, char *printer, struct GUID *guid, + struct spoolss_PrinterInfo2 **info2) +{ + struct spoolss_PrinterInfo2 *pinfo2 = NULL; + enum winreg_Type type; + uint8_t *data; + uint32_t data_size; + WERROR result; + NTSTATUS status; + + result = winreg_get_printer(mem_ctx, server_info, + servername, printer, &pinfo2); + if (!W_ERROR_IS_OK(result)) { + return false; + } + + if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) { + TALLOC_FREE(pinfo2); + return false; + } + + if (!guid) { + goto done; + } + + /* fetching printer guids really ought to be a separate function. */ + + result = winreg_get_printer_dataex(mem_ctx, server_info, printer, + SPOOL_DSSPOOLER_KEY, "objectGUID", + &type, &data, &data_size); + if (!W_ERROR_IS_OK(result)) { + TALLOC_FREE(pinfo2); + return false; + } + + /* We used to store the guid as REG_BINARY, then swapped + to REG_SZ for Vista compatibility so check for both */ + + switch (type) { + case REG_SZ: + status = GUID_from_string((char *)data, guid); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(pinfo2); + return false; + } + break; + + case REG_BINARY: + if (data_size != sizeof(struct GUID)) { + TALLOC_FREE(pinfo2); + return false; + } + memcpy(guid, data, sizeof(struct GUID)); + break; + default: + DEBUG(0,("is_printer_published: GUID value stored as " + "invaluid type (%d)\n", type)); + break; + } + +done: + if (info2) { + *info2 = talloc_move(mem_ctx, &pinfo2); + } + talloc_free(pinfo2); + return true; +} +#else +WERROR nt_printer_publish(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + struct spoolss_PrinterInfo2 *pinfo2, + int action) +{ + return WERR_OK; +} + +WERROR check_published_printers(void) +{ + return WERR_OK; +} + +bool is_printer_published(TALLOC_CTX *mem_ctx, + struct auth_serversupplied_info *server_info, + char *servername, char *printer, struct GUID *guid, + struct spoolss_PrinterInfo2 **info2) +{ + return False; +} +#endif /* HAVE_ADS */ diff --git a/source3/wscript_build b/source3/wscript_build index 75c8b98565..aec350ffce 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -755,10 +755,14 @@ PRINTING_SRC = '''printing/pcap.c printing/print_svid.c printing/print_aix.c printing/print_iprint.c''' PRINTBASE_SRC = '''printing/notify.c printing/printing_db.c''' -PRINTBACKEND_SRC = '''printing/printing.c printing/nt_printing.c - printing/nt_printing_tdb.c printing/nt_printing_migrate.c - librpc/gen_ndr/ndr_ntprinting.c ../librpc/ndr/ndr_ntprinting.c - ${PRINTBASE_SRC}''' +PRINTBACKEND_SRC = '''printing/printing.c + printing/nt_printing.c + printing/nt_printing_tdb.c + printing/nt_printing_migrate.c + printing/nt_printing_ads.c + librpc/gen_ndr/ndr_ntprinting.c + ../librpc/ndr/ndr_ntprinting.c + ${PRINTBASE_SRC}''' SMBD_SRC = '''${SMBD_SRC_BASE} ${SMBD_SRC_MAIN}''' |