s3-printing: move AD related printing components to an own file.
authorGünther Deschner <gd@samba.org>
Wed, 4 Aug 2010 13:31:08 +0000 (15:31 +0200)
committerGünther Deschner <gd@samba.org>
Wed, 4 Aug 2010 22:32:02 +0000 (00:32 +0200)
Guenther

source3/Makefile.in
source3/printing/nt_printing.c
source3/printing/nt_printing_ads.c [new file with mode: 0644]
source3/wscript_build

index bf2646dc59ac75dbda572188db4423f1a0f3aaa4..128ff8c4b6b393c3bc68782d306b12573759c4d0 100644 (file)
@@ -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)
index f0460f31c2f9ae106640800a1339f38a0aae0167..a831ef220ee707628d1b11a565bb68333f629936 100644 (file)
@@ -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 (file)
index 0000000..e59f137
--- /dev/null
@@ -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 */
index 75c8b9856564c2fc4dcbee2261dffc106ce9fd10..aec350ffce4eda0e71c69106baeeb53a3456b3bf 100644 (file)
@@ -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}'''