LCOV - code coverage report
Current view: top level - source3/printing - nt_printing_ads.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 48 494 9.7 %
Date: 2024-01-11 09:59:51 Functions: 2 12 16.7 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client / server routines
       4             :  *  Copyright (C) Andrew Tridgell              1992-2000,
       5             :  *  Copyright (C) Jean François Micouleau      1998-2000.
       6             :  *  Copyright (C) Gerald Carter                2002-2005.
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "../librpc/gen_ndr/spoolss.h"
      24             : #include "rpc_server/spoolss/srv_spoolss_util.h"
      25             : #include "nt_printing.h"
      26             : #include "ads.h"
      27             : #include "secrets.h"
      28             : #include "krb5_env.h"
      29             : #include "../libcli/registry/util_reg.h"
      30             : #include "auth.h"
      31             : #include "../librpc/ndr/libndr.h"
      32             : #include "rpc_client/cli_winreg_spoolss.h"
      33             : 
      34             : #ifdef HAVE_ADS
      35             : /*****************************************************************
      36             :  ****************************************************************/
      37             : 
      38           0 : WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
      39             :                              const char *printer, struct GUID guid)
      40             : {
      41           0 :         TALLOC_CTX *tmp_ctx;
      42           0 :         const struct auth_session_info *session_info;
      43           0 :         const char *guid_str;
      44           0 :         DATA_BLOB blob;
      45           0 :         WERROR result;
      46             : 
      47           0 :         tmp_ctx = talloc_new(NULL);
      48           0 :         if (!tmp_ctx) {
      49           0 :                 DEBUG(0, ("Out of memory?!\n"));
      50           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      51             :         }
      52             : 
      53           0 :         session_info = get_session_info_system();
      54           0 :         if (session_info == NULL) {
      55           0 :                 DEBUG(0, ("Could not get system session_info\n"));
      56           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
      57           0 :                 goto done;
      58             :         }
      59             : 
      60           0 :         guid_str = GUID_string(tmp_ctx, &guid);
      61           0 :         if (!guid_str) {
      62           0 :                 DEBUG(0, ("Out of memory?!\n"));
      63           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
      64           0 :                 goto done;
      65             :         }
      66             : 
      67             :         /* We used to store this as a REG_BINARY but that causes
      68             :            Vista to whine */
      69             : 
      70           0 :         if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
      71           0 :                 DEBUG(0, ("Could not marshall string %s for objectGUID\n",
      72             :                           guid_str));
      73           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
      74           0 :                 goto done;
      75             :         }
      76             : 
      77           0 :         result = winreg_set_printer_dataex_internal(tmp_ctx, session_info, msg_ctx,
      78             :                                            printer,
      79             :                                            SPOOL_DSSPOOLER_KEY, "objectGUID",
      80           0 :                                            REG_SZ, blob.data, blob.length);
      81           0 :         if (!W_ERROR_IS_OK(result)) {
      82           0 :                 DEBUG(0, ("Failed to store GUID for printer %s\n", printer));
      83           0 :                 goto done;
      84             :         }
      85             : 
      86           0 :         result = WERR_OK;
      87           0 : done:
      88           0 :         talloc_free(tmp_ctx);
      89             : 
      90           0 :         return result;
      91             : }
      92             : 
      93           0 : static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx,
      94             :                                    ADS_STRUCT *ads,
      95             :                                    const char *printer,
      96             :                                    char **pprinter_dn)
      97             : {
      98           0 :         char *printer_dn = NULL;
      99           0 :         char *srv_dn = NULL;
     100           0 :         char *srv_cn_0 = NULL;
     101           0 :         char *srv_cn_escaped = NULL;
     102           0 :         char *sharename_escaped = NULL;
     103           0 :         char *srv_dn_utf8 = NULL;
     104           0 :         char **srv_cn_utf8 = NULL;
     105           0 :         size_t converted_size;
     106           0 :         ADS_STATUS ads_status;
     107           0 :         LDAPMessage *res;
     108           0 :         WERROR result;
     109           0 :         bool ok;
     110             : 
     111           0 :         ads_status = ads_find_machine_acct(ads, &res, lp_netbios_name());
     112           0 :         if (!ADS_ERR_OK(ads_status)) {
     113           0 :                 DEBUG(2, ("Failed to find machine account for %s\n",
     114             :                           lp_netbios_name()));
     115           0 :                 result = WERR_NOT_FOUND;
     116           0 :                 goto err_out;
     117             :         }
     118             : 
     119             :         /*
     120             :          * We use ldap_get_dn here as we need the answer in utf8 to call
     121             :          * ldap_explode_dn(). JRA.
     122             :          */
     123           0 :         srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
     124           0 :         ads_msgfree(ads, res);
     125           0 :         if (srv_dn_utf8 == NULL) {
     126           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     127           0 :                 goto err_out;
     128             :         }
     129             : 
     130           0 :         srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
     131           0 :         if (srv_cn_utf8 == NULL) {
     132           0 :                 ldap_memfree(srv_dn_utf8);
     133           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     134           0 :                 goto err_out;
     135             :         }
     136             : 
     137             :         /* Now convert to CH_UNIX. */
     138           0 :         ok = pull_utf8_talloc(mem_ctx, &srv_dn, srv_dn_utf8, &converted_size);
     139           0 :         ldap_memfree(srv_dn_utf8);
     140           0 :         if (!ok) {
     141           0 :                 ldap_memfree(srv_cn_utf8);
     142           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     143           0 :                 goto err_out;
     144             :         }
     145             : 
     146           0 :         ok = pull_utf8_talloc(mem_ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size);
     147           0 :         ldap_memfree(srv_cn_utf8);
     148           0 :         if (!ok) {
     149           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     150           0 :                 goto err_out;
     151             :         }
     152             : 
     153           0 :         srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
     154           0 :         if (srv_cn_escaped == NULL) {
     155           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     156           0 :                 goto err_out;
     157             :         }
     158             : 
     159           0 :         sharename_escaped = escape_rdn_val_string_alloc(printer);
     160           0 :         if (sharename_escaped == NULL) {
     161           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     162           0 :                 goto err_out;
     163             :         }
     164             : 
     165           0 :         printer_dn = talloc_asprintf(mem_ctx,
     166             :                                      "cn=%s-%s,%s",
     167             :                                      srv_cn_escaped,
     168             :                                      sharename_escaped,
     169             :                                      srv_dn);
     170           0 :         if (printer_dn == NULL) {
     171           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
     172           0 :                 goto err_out;
     173             :         }
     174             : 
     175           0 :         *pprinter_dn = printer_dn;
     176             : 
     177           0 :         result = WERR_OK;
     178           0 : err_out:
     179           0 :         SAFE_FREE(sharename_escaped);
     180           0 :         SAFE_FREE(srv_cn_escaped);
     181           0 :         TALLOC_FREE(srv_cn_0);
     182           0 :         TALLOC_FREE(srv_dn);
     183           0 :         return result;
     184             : }
     185             : 
     186           0 : static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads,
     187             :                                                 const char *printer_dn,
     188             :                                                 struct GUID *pguid)
     189             : {
     190           0 :         ADS_STATUS ads_status;
     191           0 :         LDAPMessage *res;
     192           0 :         const char *attrs[] = {"objectGUID", NULL};
     193           0 :         struct GUID guid;
     194           0 :         bool ok;
     195             : 
     196           0 :         ads_status = ads_search_dn(ads, &res, printer_dn, attrs);
     197           0 :         if (!ADS_ERR_OK(ads_status)) {
     198           0 :                 DEBUG(2, ("Failed to retrieve GUID from DC - %s\n",
     199             :                           ads_errstr(ads_status)));
     200           0 :                 return WERR_FILE_NOT_FOUND;
     201             :         }
     202             : 
     203           0 :         ZERO_STRUCT(guid);
     204           0 :         ok = ads_pull_guid(ads, res, &guid);
     205           0 :         ads_msgfree(ads, res);
     206           0 :         if (!ok) {
     207           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     208             :         }
     209             : 
     210           0 :         *pguid = guid;
     211             : 
     212           0 :         return WERR_OK;
     213             : }
     214             : 
     215           0 : WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
     216             :                                 struct GUID *pguid)
     217             : {
     218           0 :         ADS_STRUCT *ads = NULL;
     219           0 :         char *old_krb5ccname = NULL;
     220           0 :         char *printer_dn;
     221           0 :         WERROR result;
     222           0 :         ADS_STATUS ads_status;
     223           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     224           0 :         char *machine_password = NULL;
     225             : 
     226           0 :         ads = ads_init(tmp_ctx,
     227             :                        lp_realm(),
     228             :                        lp_workgroup(),
     229             :                        NULL,
     230             :                        ADS_SASL_PLAIN);
     231           0 :         if (ads == NULL) {
     232           0 :                 result = WERR_RPC_S_SERVER_UNAVAILABLE;
     233           0 :                 goto out;
     234             :         }
     235             : 
     236           0 :         old_krb5ccname = getenv(KRB5_ENV_CCNAME);
     237           0 :         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
     238           0 :         ADS_TALLOC_CONST_FREE(ads->auth.password);
     239           0 :         machine_password = secrets_fetch_machine_password(lp_workgroup(),
     240             :                                                             NULL, NULL);
     241           0 :         if (machine_password != NULL) {
     242           0 :                 ads->auth.password = talloc_strdup(ads, machine_password);
     243           0 :                 SAFE_FREE(machine_password);
     244           0 :                 if (ads->auth.password == NULL) {
     245           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
     246           0 :                         goto out;
     247             :                 }
     248             :         }
     249             : 
     250           0 :         ads_status = ads_connect(ads);
     251           0 :         if (!ADS_ERR_OK(ads_status)) {
     252           0 :                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_status)));
     253           0 :                 result = WERR_ACCESS_DENIED;
     254           0 :                 goto out;
     255             :         }
     256             : 
     257           0 :         result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn);
     258           0 :         if (!W_ERROR_IS_OK(result)) {
     259           0 :                 goto out;
     260             :         }
     261             : 
     262           0 :         result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid);
     263           0 : out:
     264           0 :         TALLOC_FREE(tmp_ctx);
     265           0 :         ads_kdestroy("MEMORY:prtpub_cache");
     266           0 :         unsetenv(KRB5_ENV_CCNAME);
     267           0 :         if (old_krb5ccname != NULL) {
     268           0 :                 setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
     269             :         }
     270             : 
     271           0 :         return result;
     272             : }
     273             : 
     274           0 : WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
     275             :                            const struct auth_session_info *session_info,
     276             :                            struct messaging_context *msg_ctx,
     277             :                            const char *printer, struct GUID *guid)
     278             : {
     279           0 :         TALLOC_CTX *tmp_ctx;
     280           0 :         enum winreg_Type type;
     281           0 :         DATA_BLOB blob;
     282           0 :         uint32_t len;
     283           0 :         NTSTATUS status;
     284           0 :         WERROR result;
     285             : 
     286           0 :         tmp_ctx = talloc_new(mem_ctx);
     287           0 :         if (tmp_ctx == NULL) {
     288           0 :                 DEBUG(0, ("out of memory?!\n"));
     289           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     290             :         }
     291             : 
     292           0 :         result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
     293             :                                                     msg_ctx, printer,
     294             :                                                     SPOOL_DSSPOOLER_KEY,
     295             :                                                     "objectGUID",
     296             :                                                     &type,
     297             :                                                     &blob.data,
     298             :                                                     &len);
     299           0 :         if (!W_ERROR_IS_OK(result)) {
     300           0 :                 DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
     301           0 :                 goto out_ctx_free;
     302             :         }
     303           0 :         blob.length = (size_t)len;
     304             : 
     305             :         /* We used to store the guid as REG_BINARY, then swapped
     306             :            to REG_SZ for Vista compatibility so check for both */
     307             : 
     308           0 :         switch (type) {
     309           0 :         case REG_SZ: {
     310           0 :                 bool ok;
     311           0 :                 const char *guid_str;
     312           0 :                 ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
     313           0 :                 if (!ok) {
     314           0 :                         DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
     315             :                                   printer));
     316           0 :                         result = WERR_REGISTRY_CORRUPT;
     317           0 :                         goto out_ctx_free;
     318             :                 }
     319           0 :                 status = GUID_from_string(guid_str, guid);
     320           0 :                 if (!NT_STATUS_IS_OK(status)) {
     321           0 :                         DEBUG(0, ("bad GUID for printer %s\n", printer));
     322           0 :                         result = ntstatus_to_werror(status);
     323           0 :                         goto out_ctx_free;
     324             :                 }
     325           0 :                 break;
     326             :         }
     327           0 :         case REG_BINARY:
     328           0 :                 if (blob.length != sizeof(struct GUID)) {
     329           0 :                         DEBUG(0, ("bad GUID for printer %s\n", printer));
     330           0 :                         result = WERR_REGISTRY_CORRUPT;
     331           0 :                         goto out_ctx_free;
     332             :                 }
     333           0 :                 memcpy(guid, blob.data, sizeof(struct GUID));
     334           0 :                 break;
     335           0 :         default:
     336           0 :                 DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
     337           0 :                 result = WERR_REGISTRY_CORRUPT;
     338           0 :                 goto out_ctx_free;
     339             :                 break;
     340             :         }
     341           0 :         result = WERR_OK;
     342             : 
     343           0 : out_ctx_free:
     344           0 :         talloc_free(tmp_ctx);
     345           0 :         return result;
     346             : }
     347             : 
     348           0 : static WERROR nt_printer_devmode_to_mods(TALLOC_CTX *ctx,
     349             :                                         struct spoolss_DeviceMode *devmode,
     350             :                                         ADS_MODLIST *mods)
     351             : {
     352           0 :         char *str = NULL;
     353           0 :         ADS_STATUS status;
     354             : 
     355             :         /*
     356             :            the device mode fields bits allow us to make an educated guess if a
     357             :            printer feature is supported. For sure a feature must be unsupported if
     358             :            the fields bit is not set. Device Mode Extra Data and FeatureOptionPairs
     359             :            might help to figure out more information here. Common attributes, that
     360             :            we can't handle yet:
     361             :                 SPOOL_REG_PRINTBINNAMES - printBinNames
     362             :                 SPOOL_REG_PRINTMAXXEXTENT - printMaxXExtent
     363             :                 SPOOL_REG_PRINTMAXYEXTENT - printMaxYExtent
     364             :                 SPOOL_REG_PRINTMINXEXTENT - printMinXExtent
     365             :                 SPOOL_REG_PRINTMINYEXTENT - printMinYExtent
     366             :                 SPOOL_REG_PRINTSTAPLINGSUPPORTED - printStaplingSupported
     367             :                 SPOOL_REG_PRINTPAGESPERMINUTE - printPagesPerMinute
     368             :                 SPOOL_REG_PRINTRATE - printRate
     369             :                 SPOOL_REG_PRINTRATEUNIT - printRateUnit
     370             :                 SPOOL_REG_PRINTMEDIAREADY - printMediaReady
     371             :                 SPOOL_REG_PRINTMEDIASUPPORTED - printMediaSupported
     372             :                 SPOOL_REG_PRINTNUMBERUP - printNumberUp
     373             :                 SPOOL_REG_PRINTMAXCOPIES - printMaxCopies
     374             :         */
     375           0 :         if (devmode->fields & DEVMODE_COLOR) {
     376           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "TRUE");
     377             :         } else {
     378           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "FALSE");
     379             :         }
     380           0 :         if (!ADS_ERR_OK(status)) {
     381           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     382             :         }
     383             : 
     384           0 :         if (devmode->fields & DEVMODE_DUPLEX) {
     385           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "TRUE");
     386             :         } else {
     387           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "FALSE");
     388             :         }
     389           0 :         if (!ADS_ERR_OK(status)) {
     390           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     391             :         }
     392             : 
     393           0 :         if (devmode->fields & DEVMODE_COLLATE) {
     394           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "TRUE");
     395             :         } else {
     396           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "FALSE");
     397             :         }
     398           0 :         if (!ADS_ERR_OK(status)) {
     399           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     400             :         }
     401             : 
     402             :         /* portrait mode is always supported, LANDSCAPE is optional */
     403           0 :         status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "PORTRAIT");
     404           0 :         if (!ADS_ERR_OK(status)) {
     405           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     406             :         }
     407           0 :         if (devmode->fields & DEVMODE_ORIENTATION) {
     408           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "LANDSCAPE");
     409           0 :                 if (!ADS_ERR_OK(status)) {
     410           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     411             :                 }
     412             :         }
     413             : 
     414             :         /* the driverVersion attribute in AD contains actually specversion */
     415           0 :         str = talloc_asprintf(ctx, "%u", devmode->specversion);
     416           0 :         if (str == NULL) {
     417           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     418             :         }
     419           0 :         if (strlen(str) != 0) {
     420           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_DRIVERVERSION, str);
     421           0 :                 if (!ADS_ERR_OK(status)) {
     422           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     423             :                 }
     424             :         }
     425             : 
     426             :         /* devmode->yresolution is a good candidate for printMaxResolutionSupported */
     427           0 :         str = talloc_asprintf(ctx, "%u", devmode->yresolution);
     428           0 :         if (str == NULL) {
     429           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     430             :         }
     431           0 :         if (strlen(str) != 0) {
     432           0 :                 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, str);
     433           0 :                 if (!ADS_ERR_OK(status)) {
     434           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     435             :                 }
     436             :         }
     437             : 
     438           0 :         return WERR_OK;
     439             : }
     440             : 
     441             : 
     442             : 
     443           0 : static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx,
     444             :                                       struct spoolss_PrinterInfo2 *info2,
     445             :                                       ADS_MODLIST *mods)
     446             : {
     447           0 :         char *info_str;
     448             : 
     449           0 :         ads_mod_str(ctx, mods, SPOOL_REG_PRINTERNAME, info2->sharename);
     450           0 :         ads_mod_str(ctx, mods, SPOOL_REG_PRINTSHARENAME, info2->sharename);
     451           0 :         ads_mod_str(ctx, mods, SPOOL_REG_SHORTSERVERNAME, lp_netbios_name());
     452           0 :         ads_mod_str(ctx, mods, SPOOL_REG_SERVERNAME, get_mydnsfullname());
     453             : 
     454           0 :         info_str = talloc_asprintf(ctx, "\\\\%s\\%s",
     455             :                                    get_mydnsfullname(), info2->sharename);
     456           0 :         if (info_str == NULL) {
     457           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     458             :         }
     459           0 :         ads_mod_str(ctx, mods, SPOOL_REG_UNCNAME, info_str);
     460             : 
     461           0 :         info_str = talloc_asprintf(ctx, "%d", 4);
     462           0 :         if (info_str == NULL) {
     463           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     464             :         }
     465           0 :         ads_mod_str(ctx, mods, SPOOL_REG_VERSIONNUMBER, info_str);
     466             : 
     467             :         /* empty strings in the mods list result in an attribute error */
     468           0 :         if (strlen(info2->drivername) != 0)
     469           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_DRIVERNAME, info2->drivername);
     470           0 :         if (strlen(info2->location) != 0)
     471           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_LOCATION, info2->location);
     472           0 :         if (strlen(info2->comment) != 0)
     473           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_DESCRIPTION, info2->comment);
     474           0 :         if (strlen(info2->portname) != 0)
     475           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PORTNAME, info2->portname);
     476           0 :         if (strlen(info2->sepfile) != 0)
     477           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
     478             : 
     479           0 :         info_str = talloc_asprintf(ctx, "%u", info2->starttime);
     480           0 :         if (info_str == NULL) {
     481           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     482             :         }
     483           0 :         ads_mod_str(ctx, mods, SPOOL_REG_PRINTSTARTTIME, info_str);
     484             : 
     485           0 :         info_str = talloc_asprintf(ctx, "%u", info2->untiltime);
     486           0 :         if (info_str == NULL) {
     487           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     488             :         }
     489           0 :         ads_mod_str(ctx, mods, SPOOL_REG_PRINTENDTIME, info_str);
     490             : 
     491           0 :         info_str = talloc_asprintf(ctx, "%u", info2->priority);
     492           0 :         if (info_str == NULL) {
     493           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     494             :         }
     495           0 :         ads_mod_str(ctx, mods, SPOOL_REG_PRIORITY, info_str);
     496             : 
     497           0 :         if (info2->attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) {
     498           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "TRUE");
     499             :         } else {
     500           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "FALSE");
     501             :         }
     502             : 
     503           0 :         switch (info2->attributes & 0x3) {
     504           0 :         case 0:
     505           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
     506             :                             SPOOL_REGVAL_PRINTWHILESPOOLING);
     507           0 :                 break;
     508           0 :         case 1:
     509           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
     510             :                             SPOOL_REGVAL_PRINTAFTERSPOOLED);
     511           0 :                 break;
     512           0 :         case 2:
     513           0 :                 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
     514             :                             SPOOL_REGVAL_PRINTDIRECT);
     515           0 :                 break;
     516           0 :         default:
     517           0 :                 DEBUG(3, ("unsupported printer attributes %x\n",
     518             :                           info2->attributes));
     519             :         }
     520             : 
     521           0 :         if (info2->devmode != NULL) {
     522           0 :                 WERROR werr;
     523           0 :                 werr = nt_printer_devmode_to_mods(ctx, info2->devmode, mods);
     524           0 :                 if (!W_ERROR_IS_OK(werr)) {
     525           0 :                         return werr;
     526             :                 }
     527             :         }
     528             : 
     529           0 :         return WERR_OK;
     530             : }
     531             : 
     532           0 : static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
     533             :                                      ADS_STRUCT *ads,
     534             :                                      struct spoolss_PrinterInfo2 *pinfo2)
     535             : {
     536           0 :         ADS_STATUS ads_rc;
     537           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     538           0 :         ADS_MODLIST mods;
     539           0 :         struct GUID guid;
     540           0 :         WERROR win_rc = WERR_OK;
     541           0 :         const char *printer = pinfo2->sharename;
     542           0 :         char *printer_dn = NULL;
     543             : 
     544             :         /* build the ads mods */
     545           0 :         DEBUG(5, ("publishing printer %s\n", printer));
     546             : 
     547           0 :         win_rc = nt_printer_dn_lookup(ctx, ads, printer, &printer_dn);
     548           0 :         if (!W_ERROR_IS_OK(win_rc)) {
     549           0 :                 DEBUG(2, ("Failed to create printer dn\n"));
     550           0 :                 TALLOC_FREE(ctx);
     551           0 :                 return win_rc;
     552             :         }
     553             : 
     554           0 :         mods = ads_init_mods(ctx);
     555             : 
     556           0 :         if (mods == NULL) {
     557           0 :                 TALLOC_FREE(ctx);
     558           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     559             :         }
     560             : 
     561           0 :         win_rc = nt_printer_info_to_mods(ctx, pinfo2, &mods);
     562           0 :         if (!W_ERROR_IS_OK(win_rc)) {
     563           0 :                 TALLOC_FREE(ctx);
     564           0 :                 return win_rc;
     565             :         }
     566             : 
     567             :         /* publish it */
     568           0 :         ads_rc = ads_mod_printer_entry(ads, printer_dn, ctx, &mods);
     569           0 :         if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
     570             :                 int i;
     571           0 :                 for (i=0; mods[i] != 0; i++)
     572             :                         ;
     573           0 :                 mods[i] = (LDAPMod *)-1;
     574           0 :                 ads_rc = ads_add_printer_entry(ads, printer_dn, ctx, &mods);
     575             :         }
     576             : 
     577           0 :         if (!ADS_ERR_OK(ads_rc)) {
     578           0 :                 DEBUG(3, ("error publishing %s: %s\n",
     579             :                           printer, ads_errstr(ads_rc)));
     580             :                 /* XXX failed to publish, so no guid to retrieve */
     581             :         }
     582             : 
     583           0 :         win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid);
     584           0 :         if (!W_ERROR_IS_OK(win_rc)) {
     585           0 :                 TALLOC_FREE(ctx);
     586           0 :                 return win_rc;
     587             :         }
     588             : 
     589           0 :         win_rc = nt_printer_guid_store(msg_ctx, printer, guid);
     590           0 :         if (!W_ERROR_IS_OK(win_rc)) {
     591           0 :                 DEBUG(3, ("failed to store printer %s guid\n",
     592             :                           printer));
     593             :                 /* not catastrophic, retrieve on next use */
     594           0 :                 win_rc = WERR_OK;
     595             :         }
     596             : 
     597           0 :         TALLOC_FREE(ctx);
     598             : 
     599           0 :         return win_rc;
     600             : }
     601             : 
     602           0 : static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
     603             :                                        const char *printer)
     604             : {
     605           0 :         ADS_STATUS ads_rc;
     606           0 :         LDAPMessage *res = NULL;
     607           0 :         char *prt_dn = NULL;
     608             : 
     609           0 :         DEBUG(5, ("unpublishing printer %s\n", printer));
     610             : 
     611             :         /* remove the printer from the directory */
     612           0 :         ads_rc = ads_find_printer_on_server(ads, &res,
     613             :                                             printer, lp_netbios_name());
     614             : 
     615           0 :         if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
     616           0 :                 prt_dn = ads_get_dn(ads, talloc_tos(), res);
     617           0 :                 if (!prt_dn) {
     618           0 :                         ads_msgfree(ads, res);
     619           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     620             :                 }
     621           0 :                 ads_rc = ads_del_dn(ads, prt_dn);
     622           0 :                 TALLOC_FREE(prt_dn);
     623             :         }
     624             : 
     625           0 :         if (res) {
     626           0 :                 ads_msgfree(ads, res);
     627             :         }
     628           0 :         return WERR_OK;
     629             : }
     630             : 
     631             : /****************************************************************************
     632             :  * Publish a printer in the directory
     633             :  *
     634             :  * @param mem_ctx      memory context
     635             :  * @param session_info  session_info to access winreg pipe
     636             :  * @param pinfo2       printer information
     637             :  * @param action       publish/unpublish action
     638             :  * @return WERROR indicating status of publishing
     639             :  ***************************************************************************/
     640             : 
     641           0 : WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
     642             :                           const struct auth_session_info *session_info,
     643             :                           struct messaging_context *msg_ctx,
     644             :                           struct spoolss_PrinterInfo2 *pinfo2,
     645             :                           int action)
     646             : {
     647           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     648           0 :         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
     649           0 :         struct spoolss_SetPrinterInfo2 *sinfo2;
     650           0 :         ADS_STATUS ads_rc;
     651           0 :         ADS_STRUCT *ads = NULL;
     652           0 :         WERROR win_rc;
     653           0 :         char *old_krb5ccname = NULL;
     654           0 :         char *machine_password = NULL;
     655             : 
     656           0 :         sinfo2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
     657           0 :         if (!sinfo2) {
     658           0 :                 win_rc = WERR_NOT_ENOUGH_MEMORY;
     659           0 :                 goto done;
     660             :         }
     661             : 
     662           0 :         switch (action) {
     663           0 :         case DSPRINT_PUBLISH:
     664             :         case DSPRINT_UPDATE:
     665           0 :                 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
     666           0 :                 break;
     667           0 :         case DSPRINT_UNPUBLISH:
     668           0 :                 pinfo2->attributes &= (~PRINTER_ATTRIBUTE_PUBLISHED);
     669           0 :                 break;
     670           0 :         default:
     671           0 :                 win_rc = WERR_NOT_SUPPORTED;
     672           0 :                 goto done;
     673             :         }
     674             : 
     675           0 :         sinfo2->attributes = pinfo2->attributes;
     676             : 
     677           0 :         win_rc = winreg_update_printer_internal(tmp_ctx, session_info, msg_ctx,
     678             :                                         pinfo2->sharename, info2_mask,
     679             :                                         sinfo2, NULL, NULL);
     680           0 :         if (!W_ERROR_IS_OK(win_rc)) {
     681           0 :                 DBG_NOTICE("Failed to update data for printer [%s] - %s\n",
     682             :                            pinfo2->sharename,
     683             :                            win_errstr(win_rc));
     684           0 :                 goto done;
     685             :         }
     686             : 
     687           0 :         TALLOC_FREE(sinfo2);
     688             : 
     689           0 :         ads = ads_init(tmp_ctx,
     690             :                        lp_realm(),
     691             :                        lp_workgroup(),
     692             :                        NULL,
     693             :                        ADS_SASL_PLAIN);
     694           0 :         if (!ads) {
     695           0 :                 DEBUG(3, ("ads_init() failed\n"));
     696           0 :                 win_rc = WERR_RPC_S_SERVER_UNAVAILABLE;
     697           0 :                 goto done;
     698             :         }
     699           0 :         old_krb5ccname = getenv(KRB5_ENV_CCNAME);
     700           0 :         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
     701           0 :         ADS_TALLOC_CONST_FREE(ads->auth.password);
     702           0 :         machine_password = secrets_fetch_machine_password(lp_workgroup(),
     703             :                 NULL, NULL);
     704           0 :         if (machine_password != NULL) {
     705           0 :                 ads->auth.password = talloc_strdup(ads, machine_password);
     706           0 :                 SAFE_FREE(machine_password);
     707           0 :                 if (ads->auth.password == NULL) {
     708           0 :                         win_rc = WERR_NOT_ENOUGH_MEMORY;
     709           0 :                         goto done;
     710             :                 }
     711             :         }
     712             : 
     713             :         /* ads_connect() will find the DC for us */
     714           0 :         ads_rc = ads_connect(ads);
     715           0 :         if (!ADS_ERR_OK(ads_rc)) {
     716           0 :                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
     717           0 :                 win_rc = WERR_ACCESS_DENIED;
     718           0 :                 goto done;
     719             :         }
     720             : 
     721           0 :         switch (action) {
     722           0 :         case DSPRINT_PUBLISH:
     723             :         case DSPRINT_UPDATE:
     724           0 :                 win_rc = nt_printer_publish_ads(msg_ctx, ads, pinfo2);
     725           0 :                 break;
     726           0 :         case DSPRINT_UNPUBLISH:
     727           0 :                 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
     728           0 :                 break;
     729             :         }
     730             : 
     731           0 : done:
     732           0 :         ads_kdestroy("MEMORY:prtpub_cache");
     733           0 :         unsetenv(KRB5_ENV_CCNAME);
     734           0 :         if (old_krb5ccname) {
     735           0 :                 setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
     736             :         }
     737             : 
     738           0 :         TALLOC_FREE(tmp_ctx);
     739             : 
     740           0 :         return win_rc;
     741             : }
     742             : 
     743           2 : WERROR check_published_printers(struct messaging_context *msg_ctx)
     744             : {
     745           0 :         const struct loadparm_substitution *lp_sub =
     746           2 :                 loadparm_s3_global_substitution();
     747           0 :         ADS_STATUS ads_rc;
     748           2 :         ADS_STRUCT *ads = NULL;
     749           0 :         int snum;
     750           2 :         int n_services = lp_numservices();
     751           2 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     752           2 :         struct auth_session_info *session_info = NULL;
     753           0 :         struct spoolss_PrinterInfo2 *pinfo2;
     754           0 :         NTSTATUS status;
     755           0 :         WERROR result;
     756           2 :         char *old_krb5ccname = NULL;
     757           2 :         char *machine_password = NULL;
     758             : 
     759           2 :         ads = ads_init(tmp_ctx,
     760             :                        lp_realm(),
     761             :                        lp_workgroup(),
     762             :                        NULL,
     763             :                        ADS_SASL_PLAIN);
     764           2 :         if (!ads) {
     765           0 :                 DEBUG(3, ("ads_init() failed\n"));
     766           0 :                 TALLOC_FREE(tmp_ctx);
     767           0 :                 return WERR_RPC_S_SERVER_UNAVAILABLE;
     768             :         }
     769           2 :         old_krb5ccname = getenv(KRB5_ENV_CCNAME);
     770           2 :         setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
     771           2 :         ADS_TALLOC_CONST_FREE(ads->auth.password);
     772           2 :         machine_password = secrets_fetch_machine_password(lp_workgroup(),
     773             :                 NULL, NULL);
     774           2 :         if (machine_password != NULL) {
     775           2 :                 ads->auth.password = talloc_strdup(ads, machine_password);
     776           2 :                 SAFE_FREE(machine_password);
     777           2 :                 if (ads->auth.password == NULL) {
     778           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
     779           0 :                         goto done;
     780             :                 }
     781             :         }
     782             :         /* ads_connect() will find the DC for us */
     783           2 :         ads_rc = ads_connect(ads);
     784           2 :         if (!ADS_ERR_OK(ads_rc)) {
     785           0 :                 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
     786           0 :                 result = WERR_ACCESS_DENIED;
     787           0 :                 goto done;
     788             :         }
     789             : 
     790           2 :         status = make_session_info_system(tmp_ctx, &session_info);
     791           2 :         if (!NT_STATUS_IS_OK(status)) {
     792           0 :                 DEBUG(0, ("check_published_printers: "
     793             :                           "Could not create system session_info\n"));
     794           0 :                 result = WERR_ACCESS_DENIED;
     795           0 :                 goto done;
     796             :         }
     797             : 
     798         240 :         for (snum = 0; snum < n_services; snum++) {
     799         238 :                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
     800         228 :                         continue;
     801             :                 }
     802             : 
     803          10 :                 result = winreg_get_printer_internal(tmp_ctx, session_info, msg_ctx,
     804          10 :                                             lp_servicename(talloc_tos(), lp_sub, snum),
     805             :                                             &pinfo2);
     806          10 :                 if (!W_ERROR_IS_OK(result)) {
     807          10 :                         continue;
     808             :                 }
     809             : 
     810           0 :                 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
     811           0 :                         nt_printer_publish_ads(msg_ctx, ads, pinfo2);
     812             :                 }
     813             : 
     814           0 :                 TALLOC_FREE(pinfo2);
     815             :         }
     816             : 
     817           2 :         result = WERR_OK;
     818           2 : done:
     819           2 :         ads_kdestroy("MEMORY:prtpub_cache");
     820           2 :         unsetenv(KRB5_ENV_CCNAME);
     821           2 :         if (old_krb5ccname) {
     822           2 :                 setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
     823             :         }
     824           2 :         talloc_free(tmp_ctx);
     825           2 :         return result;
     826             : }
     827             : 
     828          84 : bool is_printer_published(TALLOC_CTX *mem_ctx,
     829             :                           const struct auth_session_info *session_info,
     830             :                           struct messaging_context *msg_ctx,
     831             :                           const char *servername,
     832             :                           const char *printer,
     833             :                           struct spoolss_PrinterInfo2 **info2)
     834             : {
     835          84 :         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
     836           0 :         WERROR result;
     837           0 :         struct dcerpc_binding_handle *b;
     838             : 
     839          84 :         result = winreg_printer_binding_handle(mem_ctx,
     840             :                                                session_info,
     841             :                                                msg_ctx,
     842             :                                                &b);
     843          84 :         if (!W_ERROR_IS_OK(result)) {
     844           0 :                 return false;
     845             :         }
     846             : 
     847          84 :         result = winreg_get_printer(mem_ctx, b,
     848             :                                     printer, &pinfo2);
     849          84 :         if (!W_ERROR_IS_OK(result)) {
     850           0 :                 return false;
     851             :         }
     852             : 
     853          84 :         if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
     854          84 :                 TALLOC_FREE(pinfo2);
     855          84 :                 return false;
     856             :         }
     857             : 
     858           0 :         if (info2) {
     859           0 :                 *info2 = talloc_move(mem_ctx, &pinfo2);
     860             :         }
     861           0 :         talloc_free(pinfo2);
     862           0 :         return true;
     863             : }
     864             : #else
     865           0 : WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
     866             :                            const char *printer, struct GUID guid)
     867             : {
     868           0 :         return WERR_NOT_SUPPORTED;
     869             : }
     870             : 
     871           0 : WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
     872             :                                 struct GUID *pguid)
     873             : {
     874           0 :         return WERR_NOT_SUPPORTED;
     875             : }
     876             : 
     877           0 : WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
     878             :                            const struct auth_session_info *session_info,
     879             :                            struct messaging_context *msg_ctx,
     880             :                            const char *printer, struct GUID *guid)
     881             : {
     882           0 :         return WERR_NOT_SUPPORTED;
     883             : }
     884             : 
     885           0 : WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
     886             :                           const struct auth_session_info *session_info,
     887             :                           struct messaging_context *msg_ctx,
     888             :                           struct spoolss_PrinterInfo2 *pinfo2,
     889             :                           int action)
     890             : {
     891           0 :         return WERR_OK;
     892             : }
     893             : 
     894           0 : WERROR check_published_printers(struct messaging_context *msg_ctx)
     895             : {
     896           0 :         return WERR_OK;
     897             : }
     898             : 
     899          28 : bool is_printer_published(TALLOC_CTX *mem_ctx,
     900             :                           const struct auth_session_info *session_info,
     901             :                           struct messaging_context *msg_ctx,
     902             :                           const char *servername,
     903             :                           const char *printer,
     904             :                           struct spoolss_PrinterInfo2 **info2)
     905             : {
     906          28 :         return False;
     907             : }
     908             : #endif /* HAVE_ADS */

Generated by: LCOV version 1.14