LCOV - code coverage report
Current view: top level - providers/ad - ad_subdomains.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 601 0.0 %
Date: 2016-06-29 Functions: 0 30 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     AD Subdomains Module
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2013 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "providers/ldap/sdap_async.h"
      26             : #include "providers/ad/ad_subdomains.h"
      27             : #include "providers/ad/ad_domain_info.h"
      28             : #include "providers/ad/ad_srv.h"
      29             : #include "providers/ad/ad_common.h"
      30             : 
      31             : #include "providers/ldap/sdap_idmap.h"
      32             : #include "providers/ldap/sdap_ops.h"
      33             : #include "util/util_sss_idmap.h"
      34             : #include <ctype.h>
      35             : #include <ndr.h>
      36             : #include <ndr/ndr_nbt.h>
      37             : 
      38             : /* Attributes of AD trusted domains */
      39             : #define AD_AT_FLATNAME      "flatName"
      40             : #define AD_AT_SID           "securityIdentifier"
      41             : #define AD_AT_TRUST_TYPE    "trustType"
      42             : #define AD_AT_TRUST_PARTNER "trustPartner"
      43             : #define AD_AT_TRUST_ATTRS   "trustAttributes"
      44             : 
      45             : /* trustType=2 denotes uplevel (NT5 and later) trusted domains. See
      46             :  * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx
      47             :  * for example.
      48             :  *
      49             :  * The absence of msDS-TrustForestTrustInfo attribute denotes a domain from
      50             :  * the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx
      51             :  * for more information.
      52             :  */
      53             : #define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))"
      54             : #define SLAVE_DOMAIN_FILTER      "(&"SLAVE_DOMAIN_FILTER_BASE")"
      55             : #define FOREST_ROOT_FILTER_FMT   "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
      56             : 
      57             : /* do not refresh more often than every 5 seconds for now */
      58             : #define AD_SUBDOMAIN_REFRESH_LIMIT 5
      59             : 
      60             : static errno_t
      61           0 : ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
      62             :                      struct ad_id_ctx *id_ctx,
      63             :                      struct sss_domain_info *subdom,
      64             :                      struct ad_id_ctx **_subdom_id_ctx)
      65             : {
      66             :     struct ad_options *ad_options;
      67             :     struct ad_id_ctx *ad_id_ctx;
      68             :     const char *gc_service_name;
      69             :     struct ad_srv_plugin_ctx *srv_ctx;
      70             :     char *ad_domain;
      71             :     char *ad_site_override;
      72             :     struct sdap_domain *sdom;
      73             :     errno_t ret;
      74             :     const char *realm;
      75             :     const char *hostname;
      76             :     const char *keytab;
      77             : 
      78           0 :     realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
      79           0 :     hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
      80           0 :     keytab = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KEYTAB);
      81           0 :     ad_domain = subdom->name;
      82           0 :     if (realm == NULL || hostname == NULL || ad_domain == NULL) {
      83           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm or hostname.\n");
      84           0 :         return EINVAL;
      85             :     }
      86             : 
      87           0 :     ad_options = ad_create_2way_trust_options(id_ctx, realm, ad_domain,
      88             :                                               hostname, keytab);
      89           0 :     if (ad_options == NULL) {
      90           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
      91           0 :         talloc_free(ad_options);
      92           0 :         return ENOMEM;
      93             :     }
      94             : 
      95           0 :     ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
      96             : 
      97           0 :     gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
      98           0 :     if (gc_service_name == NULL) {
      99           0 :         talloc_free(ad_options);
     100           0 :         return ENOMEM;
     101             :     }
     102             : 
     103           0 :     ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
     104           0 :                            subdom->name, gc_service_name,
     105           0 :                            subdom->name, &ad_options->service);
     106           0 :     if (ret != EOK) {
     107           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
     108           0 :         talloc_free(ad_options);
     109           0 :         return ret;
     110             :     }
     111             : 
     112           0 :     ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
     113           0 :     if (ad_id_ctx == NULL) {
     114           0 :         talloc_free(ad_options);
     115           0 :         return ENOMEM;
     116             :     }
     117           0 :     ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
     118           0 :     ad_options->id_ctx = ad_id_ctx;
     119             : 
     120             :     /* use AD plugin */
     121           0 :     srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
     122             :                                      default_host_dbs,
     123           0 :                                      ad_id_ctx->ad_options->id,
     124             :                                      hostname,
     125             :                                      ad_domain,
     126             :                                      ad_site_override);
     127           0 :     if (srv_ctx == NULL) {
     128           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
     129           0 :         return ENOMEM;
     130             :     }
     131           0 :     be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
     132             :                                 ad_srv_plugin_recv, srv_ctx, "AD");
     133             : 
     134           0 :     ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
     135           0 :                                  ad_id_ctx->sdap_id_ctx->opts->sdom,
     136             :                                  subdom->parent);
     137           0 :     if (ret != EOK) {
     138           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize sdap domain\n");
     139           0 :         talloc_free(ad_options);
     140           0 :         return ret;
     141             :     }
     142             : 
     143           0 :     sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
     144           0 :     if (sdom == NULL) {
     145           0 :         return EFAULT;
     146             :     }
     147             : 
     148           0 :     sdap_inherit_options(subdom->parent->sd_inherit,
     149           0 :                          id_ctx->sdap_id_ctx->opts,
     150           0 :                          ad_id_ctx->sdap_id_ctx->opts);
     151             : 
     152             :     /* Set up the ID mapping object */
     153           0 :     ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
     154           0 :         id_ctx->sdap_id_ctx->opts->idmap_ctx;
     155             : 
     156           0 :     *_subdom_id_ctx = ad_id_ctx;
     157           0 :     return EOK;
     158             : }
     159             : 
     160             : struct ad_subdomains_ctx {
     161             :     struct be_ctx *be_ctx;
     162             :     struct ad_id_ctx *ad_id_ctx;
     163             :     struct sdap_id_ctx *sdap_id_ctx;
     164             : 
     165             :     struct sdap_domain *sdom;
     166             :     char *domain_name;
     167             : 
     168             :     time_t last_refreshed;
     169             : };
     170             : 
     171           0 : static errno_t ad_subdom_enumerates(struct sss_domain_info *parent,
     172             :                                     struct sysdb_attrs *attrs,
     173             :                                     bool *_enumerates)
     174             : {
     175             :     errno_t ret;
     176             :     const char *name;
     177             : 
     178           0 :     ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
     179           0 :     if (ret != EOK) {
     180           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     181           0 :         return ret;
     182             :     }
     183             : 
     184           0 :     *_enumerates = subdomain_enumerates(parent, name);
     185           0 :     return EOK;
     186             : }
     187             : 
     188             : static errno_t
     189           0 : ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
     190             :                 struct sss_domain_info *domain,
     191             :                 struct sysdb_attrs *subdom_attrs,
     192             :                 bool enumerate)
     193             : {
     194             :     TALLOC_CTX *tmp_ctx;
     195             :     const char *name;
     196             :     char *realm;
     197             :     const char *flat;
     198             :     errno_t ret;
     199             :     enum idmap_error_code err;
     200             :     struct ldb_message_element *el;
     201           0 :     char *sid_str = NULL;
     202             :     uint32_t trust_type;
     203             :     bool mpg;
     204             : 
     205           0 :     tmp_ctx = talloc_new(NULL);
     206           0 :     if (tmp_ctx == NULL) {
     207           0 :         ret = ENOMEM;
     208           0 :         goto done;
     209             :     }
     210             : 
     211           0 :     ret = sysdb_attrs_get_uint32_t(subdom_attrs, AD_AT_TRUST_TYPE,
     212             :                                    &trust_type);
     213           0 :     if (ret != EOK) {
     214           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_uint32_t failed.\n");
     215           0 :         goto done;
     216             :     }
     217             : 
     218           0 :     ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_TRUST_PARTNER, &name);
     219           0 :     if (ret != EOK) {
     220           0 :         DEBUG(SSSDBG_OP_FAILURE, "failed to get subdomain name\n");
     221           0 :         goto done;
     222             :     }
     223             : 
     224           0 :     realm = get_uppercase_realm(tmp_ctx, name);
     225           0 :     if (!realm) {
     226           0 :         ret = ENOMEM;
     227           0 :         goto done;
     228             :     }
     229             : 
     230           0 :     ret = sysdb_attrs_get_string(subdom_attrs, AD_AT_FLATNAME, &flat);
     231           0 :     if (ret) {
     232           0 :         DEBUG(SSSDBG_OP_FAILURE, "failed to get flat name of subdomain %s\n",
     233             :                                   name);
     234           0 :         goto done;
     235             :     }
     236             : 
     237           0 :     ret = sysdb_attrs_get_el(subdom_attrs, AD_AT_SID, &el);
     238           0 :     if (ret != EOK || el->num_values != 1) {
     239           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_attrs_get_el failed.\n");
     240           0 :         goto done;
     241             :     }
     242             : 
     243           0 :     err = sss_idmap_bin_sid_to_sid(idmap_ctx->map, el->values[0].data,
     244           0 :                                    el->values[0].length, &sid_str);
     245           0 :     if (err != IDMAP_SUCCESS) {
     246           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     247             :               "Could not convert SID: [%s].\n", idmap_error_string(err));
     248           0 :         ret = EFAULT;
     249           0 :         goto done;
     250             :     }
     251             : 
     252           0 :     mpg = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, name, sid_str);
     253             : 
     254           0 :     ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
     255           0 :                                 mpg, enumerate, domain->forest, 0);
     256           0 :     if (ret != EOK) {
     257           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
     258           0 :         goto done;
     259             :     }
     260             : 
     261           0 :     ret = EOK;
     262             : done:
     263           0 :     sss_idmap_free_sid(idmap_ctx->map, sid_str);
     264           0 :     talloc_free(tmp_ctx);
     265             : 
     266           0 :     return ret;
     267             : }
     268             : 
     269           0 : static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
     270             :                                      struct sdap_idmap_ctx *idmap_ctx,
     271             :                                      struct sdap_options *opts,
     272             :                                      struct sysdb_attrs **subdomains,
     273             :                                      size_t num_subdomains,
     274             :                                      bool root_domain,
     275             :                                      time_t *_last_refreshed,
     276             :                                      bool *_changes)
     277             : {
     278             :     struct sdap_domain *sdom;
     279             :     struct sss_domain_info *domain;
     280             :     struct sss_domain_info *dom;
     281           0 :     bool handled[num_subdomains];
     282             :     const char *value;
     283           0 :     const char *root_name = NULL;
     284             :     size_t c, h;
     285             :     int ret;
     286             :     bool enumerate;
     287             : 
     288           0 :     domain = be_ctx->domain;
     289           0 :     memset(handled, 0, sizeof(bool) * num_subdomains);
     290           0 :     h = 0;
     291             : 
     292           0 :     if (root_domain) {
     293           0 :         ret = sysdb_attrs_get_string(subdomains[0], AD_AT_TRUST_PARTNER,
     294             :                                      &root_name);
     295           0 :         if (ret != EOK) {
     296           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     297           0 :             goto done;
     298             :         }
     299             :     }
     300             : 
     301             :     /* check existing subdomains */
     302           0 :     for (dom = get_next_domain(domain, SSS_GND_DESCEND);
     303           0 :          dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
     304           0 :          dom = get_next_domain(dom, 0)) {
     305             : 
     306             :         /* If we are handling root domain, skip all the other domains. We don't
     307             :          * want to accidentally remove non-root domains
     308             :          */
     309           0 :         if (root_name && strcmp(root_name, dom->name) != 0) {
     310           0 :             continue;
     311             :         }
     312             : 
     313           0 :         for (c = 0; c < num_subdomains; c++) {
     314           0 :             if (handled[c]) {
     315           0 :                 continue;
     316             :             }
     317           0 :             ret = sysdb_attrs_get_string(subdomains[c], AD_AT_TRUST_PARTNER,
     318             :                                          &value);
     319           0 :             if (ret != EOK) {
     320           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     321           0 :                 goto done;
     322             :             }
     323           0 :             if (strcmp(value, dom->name) == 0) {
     324           0 :                 break;
     325             :             }
     326             :         }
     327             : 
     328           0 :         if (c >= num_subdomains) {
     329             :             /* ok this subdomain does not exist anymore, let's clean up */
     330           0 :             sss_domain_set_state(dom, DOM_DISABLED);
     331           0 :             ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
     332           0 :             if (ret != EOK) {
     333           0 :                 goto done;
     334             :             }
     335             : 
     336           0 :             sdom = sdap_domain_get(opts, dom);
     337           0 :             if (sdom == NULL) {
     338           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Domain does not exist?\n");
     339           0 :                 continue;
     340             :             }
     341             : 
     342             :             /* Remove the subdomain from the list of LDAP domains */
     343           0 :             sdap_domain_remove(opts, dom);
     344             : 
     345           0 :             be_ptask_destroy(&sdom->enum_task);
     346           0 :             be_ptask_destroy(&sdom->cleanup_task);
     347             : 
     348             :             /* terminate all requests for this subdomain so we can free it */
     349           0 :             dp_terminate_domain_requests(be_ctx->provider, dom->name);
     350           0 :             talloc_zfree(sdom);
     351             :         } else {
     352             :             /* ok let's try to update it */
     353           0 :             ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate);
     354           0 :             if (ret != EOK) {
     355           0 :                 goto done;
     356             :             }
     357             : 
     358           0 :             ret = ad_subdom_store(idmap_ctx, domain, subdomains[c], enumerate);
     359           0 :             if (ret) {
     360             :                 /* Nothing we can do about the error. Let's at least try
     361             :                  * to reuse the existing domains
     362             :                  */
     363           0 :                 DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
     364             :                       "will try to use cached subdomain\n");
     365             :             }
     366           0 :             handled[c] = true;
     367           0 :             h++;
     368             :         }
     369             :     }
     370             : 
     371           0 :     if (num_subdomains == h) {
     372             :         /* all domains were already accounted for and have been updated */
     373           0 :         ret = EOK;
     374           0 :         *_changes = false;
     375           0 :         goto done;
     376             :     }
     377             : 
     378             :     /* if we get here it means we have changes to the subdomains list */
     379           0 :     *_changes = true;
     380             : 
     381           0 :     for (c = 0; c < num_subdomains; c++) {
     382           0 :         if (handled[c]) {
     383           0 :             continue;
     384             :         }
     385             :         /* Nothing we can do about the error. Let's at least try
     386             :          * to reuse the existing domains.
     387             :          */
     388           0 :         ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate);
     389           0 :         if (ret != EOK) {
     390           0 :             goto done;
     391             :         }
     392             : 
     393           0 :         ret = ad_subdom_store(idmap_ctx, domain, subdomains[c], enumerate);
     394           0 :         if (ret) {
     395           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
     396             :                   "will try to use cached subdomain\n");
     397             :         }
     398             :     }
     399             : 
     400           0 :     ret = EOK;
     401             : 
     402             : done:
     403           0 :     if (ret != EOK) {
     404           0 :         *_last_refreshed = 0;
     405             :     } else {
     406           0 :         *_last_refreshed = time(NULL);
     407             :     }
     408             : 
     409           0 :     return ret;
     410             : }
     411             : 
     412           0 : static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx,
     413             :                                      struct sss_domain_info *domain,
     414             :                                      size_t nsd, struct sysdb_attrs **sd,
     415             :                                      struct sysdb_attrs *root,
     416             :                                      size_t *_nsd_out,
     417             :                                      struct sysdb_attrs ***_sd_out)
     418             : {
     419             :     size_t i, sdi;
     420             :     struct sysdb_attrs **sd_out;
     421             :     const char *sd_name;
     422             :     errno_t ret;
     423             : 
     424           0 :     if (root == NULL) {
     425             :         /* We are connected directly to the root domain. The 'sd'
     426             :          * list is complete and we can just use it
     427             :          */
     428           0 :         *_nsd_out = nsd;
     429           0 :         *_sd_out = sd;
     430           0 :         return EOK;
     431             :     }
     432             : 
     433             :     /* If we searched for root separately, we must:
     434             :      *  a) treat the root domain as a subdomain
     435             :      *  b) filter the subdomain we are connected to from the subdomain
     436             :      *     list, from our point of view, it's the master domain
     437             :      */
     438           0 :     sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1);
     439           0 :     if (sd_out == NULL) {
     440           0 :         return ENOMEM;
     441             :     }
     442             : 
     443           0 :     sdi = 0;
     444           0 :     for (i = 0; i < nsd; i++) {
     445           0 :         ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name);
     446           0 :         if (ret != EOK) {
     447           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     448           0 :             goto fail;
     449             :         }
     450             : 
     451           0 :         if (strcasecmp(sd_name, domain->name) == 0) {
     452           0 :             DEBUG(SSSDBG_TRACE_INTERNAL,
     453             :                   "Not including primary domain %s in the subdomain list\n",
     454             :                   domain->name);
     455           0 :             continue;
     456             :         }
     457             : 
     458           0 :         sd_out[sdi] = talloc_steal(sd_out, sd[i]);
     459           0 :         sdi++;
     460             :     }
     461             : 
     462             :     /* Now include the root */
     463           0 :     sd_out[sdi] = talloc_steal(sd_out, root);
     464             : 
     465           0 :     *_nsd_out = sdi+1;
     466           0 :     *_sd_out = sd_out;
     467           0 :     return EOK;
     468             : 
     469             : fail:
     470           0 :     talloc_free(sd_out);
     471           0 :     return ret;
     472             : }
     473             : 
     474             : static errno_t
     475           0 : ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
     476             :                       struct sss_domain_info *parent)
     477             : {
     478             :     int ret;
     479             :     struct sdap_domain *sditer;
     480             :     struct ad_id_ctx *subdom_id_ctx;
     481             : 
     482           0 :     ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
     483           0 :     if (ret != EOK) {
     484           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_domain_subdom_add failed.\n");
     485           0 :         return ret;
     486             :     }
     487             : 
     488           0 :     DLIST_FOR_EACH(sditer, ctx->sdom) {
     489           0 :         if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
     490           0 :             ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
     491             :                                        sditer->dom, &subdom_id_ctx);
     492           0 :             if (ret != EOK) {
     493           0 :                 DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
     494             :             } else {
     495           0 :                 sditer->pvt = subdom_id_ctx;
     496             :             }
     497             :         }
     498             :     }
     499             : 
     500           0 :     return EOK;
     501             : }
     502             : 
     503           0 : static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx)
     504             : {
     505             :     const char *path;
     506             :     errno_t ret;
     507             : 
     508           0 :     path = dp_opt_get_string(subdoms_ctx->ad_id_ctx->ad_options->basic,
     509             :                              AD_KRB5_CONFD_PATH);
     510             : 
     511           0 :     ret = sss_write_krb5_conf_snippet(path);
     512           0 :     if (ret != EOK) {
     513           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
     514             :         /* Just continue */
     515             :     }
     516             : 
     517           0 :     ret = sysdb_update_subdomains(subdoms_ctx->be_ctx->domain);
     518           0 :     if (ret != EOK) {
     519           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
     520           0 :         return ret;
     521             :     }
     522             : 
     523           0 :     ret = sss_write_domain_mappings(subdoms_ctx->be_ctx->domain);
     524           0 :     if (ret != EOK) {
     525           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "sss_krb5_write_mappings failed.\n");
     526             :         /* Just continue */
     527             :     }
     528             : 
     529           0 :     ret = ads_store_sdap_subdom(subdoms_ctx, subdoms_ctx->be_ctx->domain);
     530           0 :     if (ret != EOK) {
     531           0 :         DEBUG(SSSDBG_OP_FAILURE, "ads_store_sdap_subdom failed.\n");
     532           0 :         return ret;
     533             :     }
     534             : 
     535           0 :     return EOK;
     536             : }
     537             : 
     538             : struct ad_get_slave_domain_state {
     539             :     struct tevent_context *ev;
     540             :     struct ad_subdomains_ctx *sd_ctx;
     541             :     struct be_ctx *be_ctx;
     542             :     struct sdap_options *opts;
     543             :     struct sdap_idmap_ctx *idmap_ctx;
     544             :     struct sysdb_attrs *root_attrs;
     545             :     struct sdap_id_op *sdap_op;
     546             : };
     547             : 
     548             : static errno_t ad_get_slave_domain_retry(struct tevent_req *req);
     549             : static void ad_get_slave_domain_connect_done(struct tevent_req *subreq);
     550             : static void ad_get_slave_domain_done(struct tevent_req *subreq);
     551             : 
     552             : static struct tevent_req *
     553           0 : ad_get_slave_domain_send(TALLOC_CTX *mem_ctx,
     554             :                          struct tevent_context *ev,
     555             :                          struct ad_subdomains_ctx *sd_ctx,
     556             :                          struct sysdb_attrs *root_attrs,
     557             :                          struct ad_id_ctx *root_id_ctx)
     558             : {
     559             :     struct ad_get_slave_domain_state *state;
     560             :     struct tevent_req *req;
     561             :     errno_t ret;
     562             : 
     563           0 :     req = tevent_req_create(mem_ctx, &state,
     564             :                             struct ad_get_slave_domain_state);
     565           0 :     if (req == NULL) {
     566           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     567           0 :         return NULL;
     568             :     }
     569             : 
     570           0 :     state->ev = ev;
     571           0 :     state->sd_ctx = sd_ctx;
     572           0 :     state->be_ctx = sd_ctx->be_ctx;
     573           0 :     state->opts = root_id_ctx->sdap_id_ctx->opts;
     574           0 :     state->idmap_ctx = root_id_ctx->sdap_id_ctx->opts->idmap_ctx;
     575           0 :     state->root_attrs = root_attrs;
     576             : 
     577           0 :     state->sdap_op = sdap_id_op_create(state, root_id_ctx->ldap_ctx->conn_cache);
     578           0 :     if (state->sdap_op == NULL) {
     579           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
     580           0 :         ret = ENOMEM;
     581           0 :         goto immediately;
     582             :     }
     583             : 
     584           0 :     ret = ad_get_slave_domain_retry(req);
     585           0 :     if (ret == EAGAIN) {
     586             :         /* asynchronous processing */
     587           0 :         return req;
     588             :     }
     589             : 
     590             : immediately:
     591           0 :     if (ret == EOK) {
     592           0 :         tevent_req_done(req);
     593             :     } else {
     594           0 :         tevent_req_error(req, ret);
     595             :     }
     596           0 :     tevent_req_post(req, ev);
     597             : 
     598           0 :     return req;
     599             : }
     600             : 
     601           0 : static errno_t ad_get_slave_domain_retry(struct tevent_req *req)
     602             : {
     603             :     struct ad_get_slave_domain_state *state;
     604             :     struct tevent_req *subreq;
     605             :     int ret;
     606             : 
     607           0 :     state = tevent_req_data(req, struct ad_get_slave_domain_state);
     608             : 
     609           0 :     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
     610           0 :     if (subreq == NULL) {
     611           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
     612             :               "[%d]: %s\n", ret, sss_strerror(ret));
     613           0 :         return ret;
     614             :     }
     615             : 
     616           0 :     tevent_req_set_callback(subreq, ad_get_slave_domain_connect_done, req);
     617             : 
     618           0 :     return EAGAIN;
     619             : }
     620             : 
     621           0 : static void ad_get_slave_domain_connect_done(struct tevent_req *subreq)
     622             : {
     623             :     struct ad_get_slave_domain_state *state;
     624           0 :     struct tevent_req *req = NULL;
     625             :     int dp_error;
     626             :     errno_t ret;
     627           0 :     const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
     628             :                             AD_AT_SID, AD_AT_TRUST_TYPE,
     629             :                             AD_AT_TRUST_ATTRS, NULL };
     630             : 
     631           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     632           0 :     state = tevent_req_data(req, struct ad_get_slave_domain_state);
     633             : 
     634           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     635           0 :     talloc_zfree(subreq);
     636             : 
     637           0 :     if (ret != EOK) {
     638           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
     639             :               "[%d]: %s\n", ret, sss_strerror(ret));
     640           0 :         if (dp_error == DP_ERR_OFFLINE) {
     641           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
     642             :                   "cannot get the subdomain list while offline\n");
     643           0 :             ret = ERR_OFFLINE;
     644             :         }
     645           0 :         tevent_req_error(req, ret);
     646           0 :         return;
     647             :     }
     648             : 
     649           0 :     subreq = sdap_search_bases_send(state, state->ev, state->opts,
     650             :                                     sdap_id_op_handle(state->sdap_op),
     651           0 :                                     state->opts->sdom->search_bases,
     652             :                                     NULL, false, 0,
     653             :                                     SLAVE_DOMAIN_FILTER, attrs);
     654           0 :     if (subreq == NULL) {
     655           0 :         tevent_req_error(req, ret);
     656           0 :         return;
     657             :     }
     658             : 
     659           0 :     tevent_req_set_callback(subreq, ad_get_slave_domain_done, req);
     660           0 :     return;
     661             : }
     662             : 
     663           0 : static void ad_get_slave_domain_done(struct tevent_req *subreq)
     664             : {
     665             :     struct ad_get_slave_domain_state *state;
     666             :     struct tevent_req *req;
     667             :     struct sysdb_attrs **reply;
     668             :     size_t reply_count;
     669             :     struct sysdb_attrs **subdoms;
     670             :     size_t nsubdoms;
     671             :     bool has_changes;
     672             :     int dp_error;
     673             :     errno_t ret;
     674             : 
     675           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     676           0 :     state = tevent_req_data(req, struct ad_get_slave_domain_state);
     677             : 
     678           0 :     ret = sdap_search_bases_recv(subreq, state, &reply_count, &reply);
     679           0 :     talloc_zfree(subreq);
     680           0 :     if (ret != EOK) {
     681           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup slave domain data "
     682             :               "[%d]: %s\n", ret, sss_strerror(ret));
     683             :         /* We continue to finish sdap_id_op. */
     684             :     }
     685             : 
     686           0 :     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
     687           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     688             :         /* retry */
     689           0 :         ret = ad_get_slave_domain_retry(req);
     690           0 :         if (ret != EOK) {
     691           0 :             goto done;
     692             :         }
     693           0 :         return;
     694           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
     695           0 :         ret = ERR_OFFLINE;
     696           0 :         goto done;
     697           0 :     } else if (ret != EOK) {
     698           0 :         goto done;
     699             :     }
     700             : 
     701             :     /* Based on whether we are connected to the forest root or not, we might
     702             :      * need to exclude the subdomain we are connected to from the list of
     703             :      * subdomains.
     704             :      */
     705           0 :     ret = ad_subdomains_process(state, state->be_ctx->domain,
     706             :                                 reply_count, reply, state->root_attrs,
     707             :                                 &nsubdoms, &subdoms);
     708           0 :     if (ret != EOK) {
     709           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot process subdomain list\n");
     710           0 :         tevent_req_error(req, ret);
     711           0 :         return;
     712             :     }
     713             : 
     714             :     /* Got all the subdomains, let's process them. */
     715           0 :     ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
     716             :                                 subdoms, nsubdoms, false,
     717           0 :                                 &state->sd_ctx->last_refreshed,
     718             :                                 &has_changes);
     719           0 :     if (ret != EOK) {
     720           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
     721           0 :         goto done;
     722             :     }
     723             : 
     724           0 :     DEBUG(SSSDBG_TRACE_LIBS, "There are %schanges\n",
     725             :           has_changes ? "" : "no ");
     726             : 
     727           0 :     if (has_changes) {
     728           0 :         ret = ad_subdom_reinit(state->sd_ctx);
     729           0 :         if (ret != EOK) {
     730           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
     731           0 :             goto done;
     732             :         }
     733             :     }
     734             : 
     735           0 :     state->sd_ctx->last_refreshed = time(NULL);
     736           0 :     ret = EOK;
     737             : 
     738             : done:
     739           0 :     if (ret != EOK) {
     740           0 :         tevent_req_error(req, ret);
     741           0 :         return;
     742             :     }
     743             : 
     744           0 :     tevent_req_done(req);
     745             : }
     746             : 
     747           0 : static errno_t ad_get_slave_domain_recv(struct tevent_req *req)
     748             : {
     749           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     750             : 
     751           0 :     return EOK;
     752             : }
     753             : 
     754             : static struct sss_domain_info *
     755           0 : ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs)
     756             : {
     757             :     struct sss_domain_info *root;
     758             :     const char *name;
     759             :     errno_t ret;
     760             : 
     761           0 :     ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name);
     762           0 :     if (ret != EOK) {
     763           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     764           0 :         return NULL;
     765             :     }
     766             : 
     767             :     /* With a subsequent run, the root should already be known */
     768           0 :     root = find_domain_by_name(be_ctx->domain, name, false);
     769             : 
     770           0 :     return root;
     771             : }
     772             : 
     773             : static struct ad_id_ctx *
     774           0 : ads_get_root_id_ctx(struct be_ctx *be_ctx,
     775             :                     struct ad_id_ctx *ad_id_ctx,
     776             :                     struct sss_domain_info *root_domain,
     777             :                     struct sdap_options *opts)
     778             : {
     779             :     errno_t ret;
     780             :     struct sdap_domain *sdom;
     781             :     struct ad_id_ctx *root_id_ctx;
     782             : 
     783           0 :     sdom = sdap_domain_get(opts, root_domain);
     784           0 :     if (sdom == NULL) {
     785           0 :         DEBUG(SSSDBG_OP_FAILURE,
     786             :               "Cannot get the sdom for %s!\n", root_domain->name);
     787           0 :         return NULL;
     788             :     }
     789             : 
     790           0 :     if (sdom->pvt == NULL) {
     791           0 :         ret = ad_subdom_ad_ctx_new(be_ctx, ad_id_ctx, root_domain,
     792             :                                    &root_id_ctx);
     793           0 :         if (ret != EOK) {
     794           0 :             DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
     795           0 :             return NULL;
     796             :         }
     797             : 
     798           0 :         sdom->pvt = root_id_ctx;
     799             :     } else {
     800           0 :         root_id_ctx = sdom->pvt;
     801             :     }
     802             : 
     803           0 :     root_id_ctx->ldap_ctx->ignore_mark_offline = true;
     804           0 :     return root_id_ctx;
     805             : }
     806             : 
     807             : struct ad_get_root_domain_state {
     808             :     struct ad_subdomains_ctx *sd_ctx;
     809             :     struct be_ctx *be_ctx;
     810             :     struct sdap_idmap_ctx *idmap_ctx;
     811             :     struct sdap_options *opts;
     812             : 
     813             :     struct ad_id_ctx *root_id_ctx;
     814             :     struct sysdb_attrs *root_domain_attrs;
     815             : };
     816             : 
     817             : static void ad_get_root_domain_done(struct tevent_req *subreq);
     818             : 
     819             : static struct tevent_req *
     820           0 : ad_get_root_domain_send(TALLOC_CTX *mem_ctx,
     821             :                         struct tevent_context *ev,
     822             :                         const char *forest,
     823             :                         struct sdap_handle *sh,
     824             :                         struct ad_subdomains_ctx *sd_ctx)
     825             : {
     826             :     struct ad_get_root_domain_state *state;
     827             :     struct tevent_req *subreq;
     828             :     struct tevent_req *req;
     829             :     struct sdap_options *opts;
     830             :     errno_t ret;
     831             :     const char *filter;
     832           0 :     const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
     833             :                             AD_AT_SID, AD_AT_TRUST_TYPE,
     834             :                             AD_AT_TRUST_ATTRS, NULL };
     835             : 
     836           0 :     req = tevent_req_create(mem_ctx, &state, struct ad_get_root_domain_state);
     837           0 :     if (req == NULL) {
     838           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     839           0 :         return NULL;
     840             :     }
     841             : 
     842           0 :     if (forest != NULL && strcasecmp(sd_ctx->be_ctx->domain->name, forest) == 0) {
     843           0 :         state->root_id_ctx = sd_ctx->ad_id_ctx;
     844           0 :         state->root_domain_attrs = NULL;
     845           0 :         ret = EOK;
     846           0 :         goto immediately;
     847             :     }
     848             : 
     849           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Looking up the forest root domain.\n");
     850             : 
     851           0 :     state->sd_ctx = sd_ctx;
     852           0 :     state->opts = opts = sd_ctx->sdap_id_ctx->opts;
     853           0 :     state->be_ctx = sd_ctx->be_ctx;
     854           0 :     state->idmap_ctx = opts->idmap_ctx;
     855             : 
     856           0 :     filter = talloc_asprintf(state, FOREST_ROOT_FILTER_FMT, forest);
     857           0 :     if (filter == NULL) {
     858           0 :         ret = ENOMEM;
     859           0 :         goto immediately;
     860             :     }
     861             : 
     862           0 :     subreq = sdap_search_bases_return_first_send(state, ev, opts, sh,
     863           0 :                                                  opts->sdom->search_bases,
     864             :                                                  NULL, false, 0, filter, attrs);
     865           0 :     if (subreq == NULL) {
     866           0 :         ret = ENOMEM;
     867           0 :         goto immediately;
     868             :     }
     869             : 
     870           0 :     tevent_req_set_callback(subreq, ad_get_root_domain_done, req);
     871             : 
     872           0 :     return req;
     873             : 
     874             : immediately:
     875           0 :     if (ret == EOK) {
     876           0 :         tevent_req_done(req);
     877             :     } else {
     878           0 :         tevent_req_error(req, ret);
     879             :     }
     880           0 :     tevent_req_post(req, ev);
     881             : 
     882           0 :     return req;
     883             : }
     884             : 
     885           0 : static void ad_get_root_domain_done(struct tevent_req *subreq)
     886             : {
     887             :     struct tevent_req *req;
     888             :     struct ad_get_root_domain_state *state;
     889             :     struct sysdb_attrs **reply;
     890             :     struct sss_domain_info *root_domain;
     891             :     size_t reply_count;
     892             :     bool has_changes;
     893             :     errno_t ret;
     894             : 
     895           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     896           0 :     state = tevent_req_data(req, struct ad_get_root_domain_state);
     897             : 
     898           0 :     ret = sdap_search_bases_return_first_recv(subreq, state, &reply_count,
     899             :                                               &reply);
     900           0 :     talloc_zfree(subreq);
     901           0 :     if (ret != EOK) {
     902           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to lookup forest root information "
     903             :               "[%d]: %s\n", ret, sss_strerror(ret));
     904           0 :         goto done;
     905             :     }
     906             : 
     907           0 :     if (reply_count == 0) {
     908           0 :         DEBUG(SSSDBG_OP_FAILURE, "No information provided for root domain\n");
     909           0 :         ret = ENOENT;
     910           0 :         goto done;
     911           0 :     } else if (reply_count > 1) {
     912           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Multiple results for root domain search, "
     913             :               "domain list might be incomplete!\n");
     914           0 :         ret = ERR_MALFORMED_ENTRY;
     915           0 :         goto done;
     916             :     }
     917             : 
     918           0 :     ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts,
     919             :                                 reply, reply_count, true,
     920           0 :                                 &state->sd_ctx->last_refreshed,
     921             :                                 &has_changes);
     922           0 :     if (ret != EOK) {
     923           0 :         DEBUG(SSSDBG_OP_FAILURE, "ad_subdomains_refresh failed [%d]: %s\n",
     924             :               ret, sss_strerror(ret));
     925           0 :         goto done;
     926             :     }
     927             : 
     928           0 :     if (has_changes) {
     929           0 :         ret = ad_subdom_reinit(state->sd_ctx);
     930           0 :         if (ret != EOK) {
     931           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
     932           0 :             goto done;
     933             :         }
     934             :     }
     935             : 
     936           0 :     state->root_domain_attrs = reply[0];
     937           0 :     root_domain = ads_get_root_domain(state->be_ctx, reply[0]);
     938           0 :     if (root_domain == NULL) {
     939           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
     940           0 :         ret = EFAULT;
     941           0 :         goto done;
     942             :     }
     943             : 
     944           0 :     state->root_id_ctx = ads_get_root_id_ctx(state->be_ctx,
     945           0 :                                              state->sd_ctx->ad_id_ctx,
     946             :                                              root_domain, state->opts);
     947           0 :     if (state->root_id_ctx == NULL) {
     948           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n");
     949           0 :         ret = EFAULT;
     950           0 :         goto done;
     951             :     }
     952             : 
     953           0 :     ret = EOK;
     954             : 
     955             : done:
     956           0 :     if (ret != EOK) {
     957           0 :         tevent_req_error(req, ret);
     958           0 :         return;
     959             :     }
     960             : 
     961           0 :     tevent_req_done(req);
     962             : }
     963             : 
     964           0 : static errno_t ad_get_root_domain_recv(TALLOC_CTX *mem_ctx,
     965             :                                        struct tevent_req *req,
     966             :                                        struct sysdb_attrs **_attrs,
     967             :                                        struct ad_id_ctx **_id_ctx)
     968             : {
     969           0 :     struct ad_get_root_domain_state *state = NULL;
     970           0 :     state = tevent_req_data(req, struct ad_get_root_domain_state);
     971             : 
     972           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     973             : 
     974           0 :     *_attrs = talloc_steal(mem_ctx, state->root_domain_attrs);
     975           0 :     *_id_ctx = state->root_id_ctx;
     976             : 
     977           0 :     return EOK;
     978             : }
     979             : 
     980             : struct ad_subdomains_refresh_state {
     981             :     struct tevent_context *ev;
     982             :     struct be_ctx *be_ctx;
     983             :     struct ad_subdomains_ctx *sd_ctx;
     984             :     struct sdap_id_op *sdap_op;
     985             :     struct sdap_id_ctx *id_ctx;
     986             :     struct ad_options *ad_options;
     987             : };
     988             : 
     989             : static errno_t ad_subdomains_refresh_retry(struct tevent_req *req);
     990             : static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq);
     991             : static void ad_subdomains_refresh_master_done(struct tevent_req *subreq);
     992             : static void ad_subdomains_refresh_root_done(struct tevent_req *subreq);
     993             : static void ad_subdomains_refresh_done(struct tevent_req *subreq);
     994             : 
     995             : static struct tevent_req *
     996           0 : ad_subdomains_refresh_send(TALLOC_CTX *mem_ctx,
     997             :                            struct tevent_context *ev,
     998             :                            struct ad_subdomains_ctx *sd_ctx)
     999             : {
    1000             :     struct ad_subdomains_refresh_state *state;
    1001             :     struct tevent_req *req;
    1002             :     errno_t ret;
    1003             : 
    1004           0 :     req = tevent_req_create(mem_ctx, &state,
    1005             :                             struct ad_subdomains_refresh_state);
    1006           0 :     if (req == NULL) {
    1007           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
    1008           0 :         return NULL;
    1009             :     }
    1010             : 
    1011           0 :     state->ev = ev;
    1012           0 :     state->be_ctx = sd_ctx->be_ctx;
    1013           0 :     state->sd_ctx = sd_ctx;
    1014           0 :     state->id_ctx = sd_ctx->sdap_id_ctx;
    1015           0 :     state->ad_options = sd_ctx->ad_id_ctx->ad_options;
    1016             : 
    1017           0 :     state->sdap_op = sdap_id_op_create(state,
    1018           0 :                                        sd_ctx->sdap_id_ctx->conn->conn_cache);
    1019           0 :     if (state->sdap_op == NULL) {
    1020           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
    1021           0 :         ret = ENOMEM;
    1022           0 :         goto immediately;
    1023             :     }
    1024             : 
    1025           0 :     ret = ad_subdomains_refresh_retry(req);
    1026           0 :     if (ret == EAGAIN) {
    1027             :         /* asynchronous processing */
    1028           0 :         return req;
    1029             :     }
    1030             : 
    1031             : immediately:
    1032           0 :     if (ret == EOK) {
    1033           0 :         tevent_req_done(req);
    1034             :     } else {
    1035           0 :         tevent_req_error(req, ret);
    1036             :     }
    1037           0 :     tevent_req_post(req, ev);
    1038             : 
    1039           0 :     return req;
    1040             : }
    1041             : 
    1042           0 : static errno_t ad_subdomains_refresh_retry(struct tevent_req *req)
    1043             : {
    1044             :     struct ad_subdomains_refresh_state *state;
    1045             :     struct tevent_req *subreq;
    1046             :     int ret;
    1047             : 
    1048           0 :     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
    1049             : 
    1050           0 :     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
    1051           0 :     if (subreq == NULL) {
    1052           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed "
    1053             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1054           0 :         return ret;
    1055             :     }
    1056             : 
    1057           0 :     tevent_req_set_callback(subreq, ad_subdomains_refresh_connect_done, req);
    1058             : 
    1059           0 :     return EAGAIN;
    1060             : }
    1061             : 
    1062           0 : static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq)
    1063             : {
    1064             :     struct ad_subdomains_refresh_state *state;
    1065             :     struct tevent_req *req;
    1066             :     int dp_error;
    1067             :     errno_t ret;
    1068             : 
    1069           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1070           0 :     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
    1071             : 
    1072           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
    1073           0 :     talloc_zfree(subreq);
    1074             : 
    1075           0 :     if (ret != EOK) {
    1076           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
    1077             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1078           0 :         if (dp_error == DP_ERR_OFFLINE) {
    1079           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
    1080             :                   "cannot get the subdomain list while offline\n");
    1081           0 :             ret = ERR_OFFLINE;
    1082             :         }
    1083           0 :         tevent_req_error(req, ret);
    1084           0 :         return;
    1085             :     }
    1086             : 
    1087           0 :     subreq = ad_master_domain_send(state, state->ev, state->id_ctx->conn,
    1088           0 :                                    state->sdap_op, state->sd_ctx->domain_name);
    1089           0 :     if (subreq == NULL) {
    1090           0 :         tevent_req_error(req, ENOMEM);
    1091           0 :         return;
    1092             :     }
    1093             : 
    1094           0 :     tevent_req_set_callback(subreq, ad_subdomains_refresh_master_done, req);
    1095           0 :     return;
    1096             : }
    1097             : 
    1098           0 : static void ad_subdomains_refresh_master_done(struct tevent_req *subreq)
    1099             : {
    1100             :     struct ad_subdomains_refresh_state *state;
    1101             :     struct tevent_req *req;
    1102             :     const char *realm;
    1103             :     char *master_sid;
    1104             :     char *flat_name;
    1105             :     char *forest;
    1106             :     char *site;
    1107             :     errno_t ret;
    1108             : 
    1109           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1110           0 :     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
    1111             : 
    1112           0 :     ret = ad_master_domain_recv(subreq, state, &flat_name, &master_sid,
    1113             :                                 &site, &forest);
    1114           0 :     talloc_zfree(subreq);
    1115           0 :     if (ret != EOK) {
    1116           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get master domain information "
    1117             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1118           0 :         goto done;
    1119             :     }
    1120             : 
    1121           0 :     realm = dp_opt_get_cstring(state->ad_options->basic, AD_KRB5_REALM);
    1122           0 :     if (realm == NULL) {
    1123           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm.\n");
    1124           0 :         ret = EINVAL;
    1125           0 :         goto done;
    1126             :     }
    1127             : 
    1128           0 :     ret = sysdb_master_domain_add_info(state->be_ctx->domain, realm,
    1129             :                                        flat_name, master_sid, forest);
    1130           0 :     if (ret != EOK) {
    1131           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info [%d]: %s\n",
    1132             :               ret, sss_strerror(ret));
    1133           0 :         goto done;
    1134             :     }
    1135             : 
    1136           0 :     subreq = ad_get_root_domain_send(state, state->ev, forest,
    1137             :                                      sdap_id_op_handle(state->sdap_op),
    1138             :                                      state->sd_ctx);
    1139           0 :     if (subreq == NULL) {
    1140           0 :         ret = ENOMEM;
    1141           0 :         goto done;
    1142             :     }
    1143             : 
    1144           0 :     tevent_req_set_callback(subreq, ad_subdomains_refresh_root_done, req);
    1145           0 :     return;
    1146             : 
    1147             : done:
    1148           0 :     if (ret != EOK) {
    1149           0 :         tevent_req_error(req, ret);
    1150           0 :         return;
    1151             :     }
    1152             : 
    1153           0 :     tevent_req_done(req);
    1154             : }
    1155             : 
    1156           0 : static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
    1157             : {
    1158             :     struct ad_subdomains_refresh_state *state;
    1159             :     struct tevent_req *req;
    1160             :     struct ad_id_ctx *root_id_ctx;
    1161             :     struct sysdb_attrs *root_attrs;
    1162             :     int dp_error;
    1163             :     errno_t ret;
    1164             : 
    1165           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1166           0 :     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
    1167             : 
    1168           0 :     ret = ad_get_root_domain_recv(state, subreq, &root_attrs, &root_id_ctx);
    1169           0 :     talloc_zfree(subreq);
    1170           0 :     if (ret != EOK) {
    1171           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get forest root [%d]: %s\n",
    1172             :               ret, sss_strerror(ret));
    1173           0 :         root_attrs = NULL;
    1174           0 :         root_id_ctx = NULL;
    1175             :         /* We continue to finish sdap_id_op. */
    1176             :     }
    1177             : 
    1178             :     /* We finish sdap_id_op here since we connect
    1179             :      * to forest root for slave domains. */
    1180           0 :     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
    1181           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
    1182             :         /* retry */
    1183           0 :         ret = ad_subdomains_refresh_retry(req);
    1184           0 :         if (ret != EOK) {
    1185           0 :             tevent_req_error(req, ret);
    1186             :         }
    1187           0 :         return;
    1188           0 :     } else if (dp_error == DP_ERR_OFFLINE) {
    1189           0 :         tevent_req_error(req, ERR_OFFLINE);
    1190           0 :         return;
    1191           0 :     } else if (ret != EOK) {
    1192           0 :         tevent_req_error(req, ret);
    1193           0 :         return;
    1194             :     }
    1195             : 
    1196           0 :     subreq = ad_get_slave_domain_send(state, state->ev, state->sd_ctx,
    1197             :                                       root_attrs, root_id_ctx);
    1198           0 :     if (subreq == NULL) {
    1199           0 :         tevent_req_error(req, ENOMEM);
    1200           0 :         return;
    1201             :     }
    1202             : 
    1203           0 :     tevent_req_set_callback(subreq, ad_subdomains_refresh_done, req);
    1204           0 :     return;
    1205             : }
    1206             : 
    1207           0 : static void ad_subdomains_refresh_done(struct tevent_req *subreq)
    1208             : {
    1209             :     struct tevent_req *req;
    1210             :     errno_t ret;
    1211             : 
    1212           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1213             : 
    1214           0 :     ret = ad_get_slave_domain_recv(subreq);
    1215           0 :     talloc_zfree(subreq);
    1216           0 :     if (ret != EOK) {
    1217           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to get subdomains [%d]: %s\n",
    1218             :               ret, sss_strerror(ret));
    1219             :     }
    1220             : 
    1221           0 :     if (ret != EOK) {
    1222           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n",
    1223             :               ret, sss_strerror(ret));
    1224           0 :         tevent_req_error(req, ret);
    1225           0 :         return;
    1226             :     }
    1227             : 
    1228           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Subdomains refreshed.\n");
    1229           0 :     tevent_req_done(req);
    1230             : }
    1231             : 
    1232           0 : static errno_t ad_subdomains_refresh_recv(struct tevent_req *req)
    1233             : {
    1234           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1235             : 
    1236           0 :     return EOK;
    1237             : }
    1238             : 
    1239             : struct ad_subdomains_handler_state {
    1240             :     struct dp_reply_std reply;
    1241             : };
    1242             : 
    1243             : static void ad_subdomains_handler_done(struct tevent_req *subreq);
    1244             : 
    1245             : static struct tevent_req *
    1246           0 : ad_subdomains_handler_send(TALLOC_CTX *mem_ctx,
    1247             :                            struct ad_subdomains_ctx *sd_ctx,
    1248             :                            struct dp_subdomains_data *data,
    1249             :                            struct dp_req_params *params)
    1250             : {
    1251             :     struct ad_subdomains_handler_state *state;
    1252             :     struct tevent_req *req;
    1253             :     struct tevent_req *subreq;
    1254             :     errno_t ret;
    1255             : 
    1256           0 :     req = tevent_req_create(mem_ctx, &state,
    1257             :                             struct ad_subdomains_handler_state);
    1258           0 :     if (req == NULL) {
    1259           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
    1260           0 :         return NULL;
    1261             :     }
    1262             : 
    1263             : 
    1264           0 :     if (sd_ctx->last_refreshed > time(NULL) - AD_SUBDOMAIN_REFRESH_LIMIT) {
    1265           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Subdomains were recently refreshed, "
    1266             :               "nothing to do\n");
    1267           0 :         ret = EOK;
    1268           0 :         goto immediately;
    1269             :     }
    1270             : 
    1271           0 :     subreq = ad_subdomains_refresh_send(state, params->ev, sd_ctx);
    1272           0 :     if (subreq == NULL) {
    1273           0 :         ret = ENOMEM;
    1274           0 :         goto immediately;
    1275             :     }
    1276             : 
    1277           0 :     tevent_req_set_callback(subreq, ad_subdomains_handler_done, req);
    1278             : 
    1279           0 :     return req;
    1280             : 
    1281             : immediately:
    1282           0 :     dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
    1283             : 
    1284             :     /* TODO For backward compatibility we always return EOK to DP now. */
    1285           0 :     tevent_req_done(req);
    1286           0 :     tevent_req_post(req, params->ev);
    1287             : 
    1288           0 :     return req;
    1289             : }
    1290             : 
    1291           0 : static void ad_subdomains_handler_done(struct tevent_req *subreq)
    1292             : {
    1293             :     struct ad_subdomains_handler_state *state;
    1294             :     struct tevent_req *req;
    1295             :     errno_t ret;
    1296             : 
    1297           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1298           0 :     state = tevent_req_data(req, struct ad_subdomains_handler_state);
    1299             : 
    1300           0 :     ret = ad_subdomains_refresh_recv(subreq);
    1301           0 :     talloc_zfree(subreq);
    1302             : 
    1303             :     /* TODO For backward compatibility we always return EOK to DP now. */
    1304           0 :     dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
    1305           0 :     tevent_req_done(req);
    1306           0 : }
    1307             : 
    1308           0 : static errno_t ad_subdomains_handler_recv(TALLOC_CTX *mem_ctx,
    1309             :                                           struct tevent_req *req,
    1310             :                                           struct dp_reply_std *data)
    1311             : {
    1312             :    struct ad_subdomains_handler_state *state;
    1313             : 
    1314           0 :    state = tevent_req_data(req, struct ad_subdomains_handler_state);
    1315             : 
    1316           0 :    TEVENT_REQ_RETURN_ON_ERROR(req);
    1317             : 
    1318           0 :    *data = state->reply;
    1319             : 
    1320           0 :    return EOK;
    1321             : }
    1322             : 
    1323             : static struct tevent_req *
    1324           0 : ad_subdomains_ptask_send(TALLOC_CTX *mem_ctx,
    1325             :                          struct tevent_context *ev,
    1326             :                          struct be_ctx *be_ctx,
    1327             :                          struct be_ptask *be_ptask,
    1328             :                          void *pvt)
    1329             : {
    1330             :     struct ad_subdomains_ctx *sd_ctx;
    1331           0 :     sd_ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
    1332             : 
    1333           0 :     return ad_subdomains_refresh_send(mem_ctx, ev, sd_ctx);
    1334             : }
    1335             : 
    1336             : static errno_t
    1337           0 : ad_subdomains_ptask_recv(struct tevent_req *req)
    1338             : {
    1339           0 :     return ad_subdomains_refresh_recv(req);
    1340             : }
    1341             : 
    1342           0 : errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx,
    1343             :                            struct be_ctx *be_ctx,
    1344             :                            struct ad_id_ctx *ad_id_ctx,
    1345             :                            struct dp_method *dp_methods)
    1346             : {
    1347             :     struct ad_subdomains_ctx *sd_ctx;
    1348             :     const char *ad_domain;
    1349             :     time_t period;
    1350             :     errno_t ret;
    1351             : 
    1352           0 :     ad_domain = dp_opt_get_string(ad_id_ctx->ad_options->basic, AD_DOMAIN);
    1353             : 
    1354           0 :     sd_ctx = talloc_zero(mem_ctx, struct ad_subdomains_ctx);
    1355           0 :     if (sd_ctx == NULL) {
    1356           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1357           0 :         return ENOMEM;
    1358             :     }
    1359             : 
    1360           0 :     sd_ctx->be_ctx = be_ctx;
    1361           0 :     sd_ctx->sdom = ad_id_ctx->sdap_id_ctx->opts->sdom;
    1362           0 :     sd_ctx->sdap_id_ctx = ad_id_ctx->sdap_id_ctx;
    1363           0 :     sd_ctx->domain_name = talloc_strdup(sd_ctx, ad_domain);
    1364           0 :     if (sd_ctx->domain_name == NULL) {
    1365           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
    1366           0 :         return ENOMEM;
    1367             :     }
    1368           0 :     sd_ctx->ad_id_ctx = ad_id_ctx;
    1369             : 
    1370           0 :     dp_set_method(dp_methods, DPM_DOMAINS_HANDLER,
    1371             :                   ad_subdomains_handler_send, ad_subdomains_handler_recv, sd_ctx,
    1372             :                   struct ad_subdomains_ctx, struct dp_subdomains_data, struct dp_reply_std);
    1373             : 
    1374           0 :     period = be_ctx->domain->subdomain_refresh_interval;
    1375           0 :     ret = be_ptask_create(sd_ctx, be_ctx, period, 0, 0, 0, period,
    1376             :                           BE_PTASK_OFFLINE_DISABLE, 0,
    1377             :                           ad_subdomains_ptask_send, ad_subdomains_ptask_recv, sd_ctx,
    1378             :                           "Subdomains Refresh", NULL);
    1379           0 :     if (ret != EOK) {
    1380           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask "
    1381             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1382             :         /* Ignore, responders will trigger refresh from time to time. */
    1383             :     }
    1384             : 
    1385           0 :     ret = ad_subdom_reinit(sd_ctx);
    1386           0 :     if (ret != EOK) {
    1387           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not reinitialize subdomains. "
    1388             :               "Users from trusted domains might not be resolved correctly\n");
    1389             :         /* Ignore this error and try to discover the subdomains later */
    1390             :     }
    1391             : 
    1392           0 :     return EOK;
    1393             : }

Generated by: LCOV version 1.10