LCOV - code coverage report
Current view: top level - providers/ipa - ipa_subdomains.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 715 0.0 %
Date: 2015-10-19 Functions: 0 30 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     IPA Subdomains Module
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2011 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/ldap/sdap_idmap.h"
      27             : #include "providers/ipa/ipa_subdomains.h"
      28             : #include "providers/ipa/ipa_common.h"
      29             : #include "providers/ipa/ipa_id.h"
      30             : 
      31             : #include <ctype.h>
      32             : 
      33             : #define SUBDOMAINS_FILTER "objectclass=ipaNTTrustedDomain"
      34             : #define MASTER_DOMAIN_FILTER "objectclass=ipaNTDomainAttrs"
      35             : #define RANGE_FILTER "objectclass=ipaIDRange"
      36             : 
      37             : #define IPA_CN "cn"
      38             : #define IPA_FLATNAME "ipaNTFlatName"
      39             : #define IPA_SID "ipaNTSecurityIdentifier"
      40             : #define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID"
      41             : #define IPA_RANGE_TYPE "ipaRangeType"
      42             : 
      43             : #define IPA_BASE_ID "ipaBaseID"
      44             : #define IPA_ID_RANGE_SIZE "ipaIDRangeSize"
      45             : #define IPA_BASE_RID "ipaBaseRID"
      46             : #define IPA_SECONDARY_BASE_RID "ipaSecondaryBaseRID"
      47             : #define OBJECTCLASS "objectClass"
      48             : 
      49             : #define IPA_ASSIGNED_ID_VIEW "ipaAssignedIDView"
      50             : 
      51             : /* do not refresh more often than every 5 seconds for now */
      52             : #define IPA_SUBDOMAIN_REFRESH_LIMIT 5
      53             : 
      54             : #define IPA_SUBDOMAIN_DISABLED_PERIOD 3600
      55             : 
      56             : enum ipa_subdomains_req_type {
      57             :     IPA_SUBDOMAINS_MASTER,
      58             :     IPA_SUBDOMAINS_SLAVE,
      59             :     IPA_SUBDOMAINS_RANGES,
      60             : 
      61             :     IPA_SUBDOMAINS_MAX /* Counter */
      62             : };
      63             : 
      64             : struct ipa_subdomains_req_params {
      65             :     const char *filter;
      66             :     tevent_req_fn cb;
      67             :     const char *attrs[9];
      68             : };
      69             : 
      70             : struct ipa_subdomains_ctx {
      71             :     struct be_ctx *be_ctx;
      72             :     struct ipa_id_ctx *id_ctx;
      73             :     struct sdap_id_ctx *sdap_id_ctx;
      74             :     struct sdap_search_base **search_bases;
      75             :     struct sdap_search_base **master_search_bases;
      76             :     struct sdap_search_base **ranges_search_bases;
      77             :     struct sdap_search_base **host_search_bases;
      78             : 
      79             :     time_t last_refreshed;
      80             :     struct tevent_timer *timer_event;
      81             :     bool configured_explicit;
      82             :     time_t disabled_until;
      83             :     bool view_read_at_init;
      84             : };
      85             : 
      86           0 : static void ipa_subdomains_done(struct ipa_subdomains_ctx *sd_ctx,
      87             :                                 struct be_req *req, int dp_err,
      88             :                                 int error, const char *errstr)
      89             : {
      90           0 :     sd_ctx->view_read_at_init = true;
      91           0 :     return be_req_terminate(req, dp_err, error, errstr);
      92             : }
      93             : 
      94           0 : struct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx)
      95             : {
      96             :     struct ipa_subdomains_ctx *subdom_ctx;
      97             : 
      98           0 :     subdom_ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
      99             :                                  struct ipa_subdomains_ctx);
     100           0 :     if (subdom_ctx == NULL) {
     101           0 :         DEBUG(SSSDBG_TRACE_ALL, "Subdomains are not configured.\n");
     102           0 :         return NULL;
     103             :     }
     104             : 
     105           0 :     return subdom_ctx->be_ctx;
     106             : }
     107             : 
     108             : static errno_t
     109           0 : ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx)
     110             : {
     111             :     errno_t ret;
     112             : 
     113           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
     114             :           "Re-initializing domain %s\n", ctx->be_ctx->domain->name);
     115             : 
     116           0 :     ret = sss_write_krb5_conf_snippet(
     117           0 :                               dp_opt_get_string(ctx->id_ctx->ipa_options->basic,
     118             :                                                 IPA_KRB5_CONFD_PATH));
     119           0 :     if (ret != EOK) {
     120           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
     121             :         /* Just continue */
     122             :     }
     123             : 
     124           0 :     ret = sysdb_master_domain_update(ctx->be_ctx->domain);
     125           0 :     if (ret != EOK) {
     126           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed.\n");
     127           0 :         return ret;
     128             :     }
     129             : 
     130           0 :     ret = sysdb_update_subdomains(ctx->be_ctx->domain);
     131           0 :     if (ret != EOK) {
     132           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
     133           0 :         return ret;
     134             :     }
     135             : 
     136           0 :     ret = sss_write_domain_mappings(ctx->be_ctx->domain);
     137           0 :     if (ret != EOK) {
     138           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     139             :                 "sss_krb5_write_mappings failed.\n");
     140             :         /* Just continue */
     141             :     }
     142             : 
     143           0 :     return EOK;
     144             : }
     145             : 
     146           0 : static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
     147             :                                         char *domain_name,
     148             :                                         size_t count,
     149             :                                         struct sysdb_attrs **reply,
     150             :                                         struct range_info ***_range_list)
     151             : {
     152           0 :     struct range_info **range_list = NULL;
     153             :     struct range_info *r;
     154             :     const char *value;
     155             :     size_t c;
     156             :     size_t d;
     157             :     int ret;
     158             :     enum idmap_error_code err;
     159             :     char *name1;
     160             :     char *name2;
     161             :     char *sid1;
     162             :     char *sid2;
     163             :     uint32_t rid1;
     164             :     uint32_t rid2;
     165             :     struct sss_idmap_range range1;
     166             :     struct sss_idmap_range range2;
     167             :     bool mapping1;
     168             :     bool mapping2;
     169             : 
     170           0 :     range_list = talloc_array(mem_ctx, struct range_info *, count + 1);
     171           0 :     if (range_list == NULL) {
     172           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
     173           0 :         return ENOMEM;
     174             :     }
     175             : 
     176           0 :     for (c = 0; c < count; c++) {
     177           0 :         r = talloc_zero(range_list, struct range_info);
     178           0 :         if (r == NULL) {
     179           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
     180           0 :             ret = ENOMEM;
     181           0 :             goto done;
     182             :         }
     183             : 
     184           0 :         ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
     185           0 :         if (ret != EOK) {
     186           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     187           0 :             goto done;
     188             :         }
     189             : 
     190           0 :         r->name = talloc_strdup(r, value);
     191           0 :         if (r->name == NULL) {
     192           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     193           0 :             ret = ENOMEM;
     194           0 :             goto done;
     195             :         }
     196             : 
     197           0 :         ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value);
     198           0 :         if (ret == EOK) {
     199           0 :             r->trusted_dom_sid = talloc_strdup(r, value);
     200           0 :             if (r->trusted_dom_sid == NULL) {
     201           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     202           0 :                 ret = ENOMEM;
     203           0 :                 goto done;
     204             :             }
     205           0 :         } else if (ret != ENOENT) {
     206           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     207           0 :             goto done;
     208             :         }
     209             : 
     210           0 :         ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID,
     211             :                                        &r->base_id);
     212           0 :         if (ret != EOK && ret != ENOENT) {
     213           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     214           0 :             goto done;
     215             :         }
     216             : 
     217           0 :         ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE,
     218             :                                        &r->id_range_size);
     219           0 :         if (ret != EOK && ret != ENOENT) {
     220           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     221           0 :             goto done;
     222             :         }
     223             : 
     224           0 :         ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID,
     225             :                                        &r->base_rid);
     226           0 :         if (ret != EOK && ret != ENOENT) {
     227           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     228           0 :             goto done;
     229             :         }
     230             : 
     231           0 :         ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID,
     232             :                                        &r->secondary_base_rid);
     233           0 :         if (ret != EOK && ret != ENOENT) {
     234           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     235           0 :             goto done;
     236             :         }
     237             : 
     238           0 :         ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value);
     239           0 :         if (ret == EOK) {
     240           0 :             r->range_type = talloc_strdup(r, value);
     241           0 :             if (r->range_type == NULL) {
     242           0 :                 DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     243           0 :                 ret = ENOMEM;
     244           0 :                 goto done;
     245             :             }
     246           0 :         } else if (ret == ENOENT) {
     247             :             /* Older IPA servers might not have the range_type attribute, but
     248             :              * only support local ranges and trusts with algorithmic mapping. */
     249           0 :             if (r->trusted_dom_sid == NULL) {
     250           0 :                 r->range_type = talloc_strdup(r, IPA_RANGE_LOCAL);
     251             :             } else {
     252           0 :                 r->range_type = talloc_strdup(r, IPA_RANGE_AD_TRUST);
     253             :             }
     254             :         } else {
     255           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     256           0 :             goto done;
     257             :         }
     258           0 :         if (r->range_type == NULL) {
     259           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
     260           0 :             ret = ENOMEM;
     261           0 :             goto done;
     262             :         }
     263             : 
     264           0 :         ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1,
     265             :                                         &range1, &mapping1);
     266           0 :         if (ret != EOK) {
     267           0 :             DEBUG(SSSDBG_OP_FAILURE, "get_idmap_data_from_range failed.\n");
     268           0 :             goto done;
     269             :         }
     270           0 :         for (d = 0; d < c; d++) {
     271           0 :             ret = get_idmap_data_from_range(range_list[d], domain_name, &name2,
     272             :                                             &sid2, &rid2, &range2, &mapping2);
     273           0 :             if (ret != EOK) {
     274           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     275             :                       "get_idmap_data_from_range failed.\n");
     276           0 :                 goto done;
     277             :             }
     278             : 
     279           0 :             err = sss_idmap_check_collision_ex(name1, sid1, &range1, rid1,
     280           0 :                                                r->name, mapping1,
     281             :                                                name2, sid2, &range2, rid2,
     282           0 :                                                range_list[d]->name, mapping2);
     283           0 :             if (err != IDMAP_SUCCESS) {
     284           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     285             :                       "Collision of ranges [%s] and [%s] detected.\n",
     286             :                       r->name, range_list[d]->name);
     287           0 :                 ret = EINVAL;
     288           0 :                 goto done;
     289             :             }
     290             :         }
     291             : 
     292           0 :         range_list[c] = r;
     293             :     }
     294             : 
     295           0 :     range_list[c] = NULL;
     296             : 
     297           0 :     *_range_list = range_list;
     298           0 :     ret = EOK;
     299             : 
     300             : done:
     301           0 :     if (ret != EOK) {
     302           0 :         talloc_free(range_list);
     303             :     }
     304             : 
     305           0 :     return ret;
     306             : }
     307             : 
     308           0 : static errno_t ipa_subdom_enumerates(struct sss_domain_info *parent,
     309             :                                      struct sysdb_attrs *attrs,
     310             :                                      bool *_enumerates)
     311             : {
     312             :     errno_t ret;
     313             :     const char *name;
     314             : 
     315           0 :     ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
     316           0 :     if (ret != EOK) {
     317           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     318           0 :         return ret;
     319             :     }
     320             : 
     321           0 :     *_enumerates = subdomain_enumerates(parent, name);
     322           0 :     return EOK;
     323             : }
     324             : 
     325           0 : static errno_t ipa_subdom_get_forest(TALLOC_CTX *mem_ctx,
     326             :                                      struct ldb_context *ldb_ctx,
     327             :                                      struct sysdb_attrs *attrs,
     328             :                                      char **_forest)
     329             : {
     330             :     int ret;
     331           0 :     struct ldb_dn *dn = NULL;
     332             :     const char *name;
     333             :     const struct ldb_val *val;
     334           0 :     char *forest = NULL;
     335             : 
     336           0 :     dn = ipa_subdom_ldb_dn(mem_ctx, ldb_ctx, attrs);
     337           0 :     if (dn == NULL) {
     338           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_subdom_ldb_dn failed.\n");
     339           0 :         ret = EIO;
     340           0 :         goto done;
     341             :     }
     342             : 
     343           0 :     if (ipa_subdom_is_member_dom(dn) == false) {
     344           0 :         ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
     345           0 :         if (ret) {
     346           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     347           0 :             goto done;
     348             :         }
     349             : 
     350           0 :         forest = talloc_strdup(mem_ctx, name);
     351           0 :         if (forest == NULL) {
     352           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     353           0 :             ret = ENOMEM;
     354           0 :             goto done;
     355             :         }
     356             : 
     357           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "The forest name is %s\n", forest);
     358           0 :         ret = EOK;
     359           0 :         goto done;
     360             :     }
     361             : 
     362           0 :     val = ldb_dn_get_component_val(dn, 1);
     363           0 :     forest = talloc_strndup(mem_ctx, (const char *) val->data, val->length);
     364           0 :     if (forest == NULL) {
     365           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     366           0 :         ret = ENOMEM;
     367           0 :         goto done;
     368             :     }
     369             : 
     370           0 :     ret = EOK;
     371             : done:
     372           0 :     talloc_free(dn);
     373             : 
     374           0 :     if (ret == EOK) {
     375           0 :         *_forest = forest;
     376             :     }
     377             : 
     378           0 :     return ret;
     379             : }
     380             : 
     381           0 : static errno_t ipa_get_sd_trust_direction(struct sysdb_attrs *sd,
     382             :                                           struct ipa_id_ctx *id_ctx,
     383             :                                           struct ldb_context *ldb_ctx,
     384             :                                           uint32_t *_direction)
     385             : {
     386           0 :     if (id_ctx->server_mode != NULL) {
     387           0 :         return ipa_server_get_trust_direction(sd, ldb_ctx, _direction);
     388             :     } else {
     389             :         /* Clients do not have access to the trust objects's trust direction
     390             :          * and don't generally care
     391             :          */
     392           0 :         *_direction = 0;
     393           0 :         return EOK;
     394             :     }
     395             : }
     396             : 
     397           0 : static errno_t ipa_subdom_store(struct sss_domain_info *parent,
     398             :                                 struct ipa_id_ctx *id_ctx,
     399             :                                 struct sdap_idmap_ctx *sdap_idmap_ctx,
     400             :                                 struct sysdb_attrs *attrs)
     401             : {
     402             :     TALLOC_CTX *tmp_ctx;
     403             :     const char *name;
     404             :     char *realm;
     405             :     const char *flat;
     406             :     const char *id;
     407           0 :     char *forest = NULL;
     408             :     int ret;
     409             :     bool mpg;
     410             :     bool enumerate;
     411             :     uint32_t direction;
     412             : 
     413           0 :     tmp_ctx = talloc_new(parent);
     414           0 :     if (tmp_ctx == NULL) {
     415           0 :         return ENOMEM;
     416             :     }
     417             : 
     418           0 :     ret = sysdb_attrs_get_string(attrs, IPA_CN, &name);
     419           0 :     if (ret != EOK) {
     420           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     421           0 :         goto done;
     422             :     }
     423             : 
     424           0 :     realm = get_uppercase_realm(tmp_ctx, name);
     425           0 :     if (!realm) {
     426           0 :         ret = ENOMEM;
     427           0 :         goto done;
     428             :     }
     429             : 
     430           0 :     ret = sysdb_attrs_get_string(attrs, IPA_FLATNAME, &flat);
     431           0 :     if (ret) {
     432           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     433           0 :         goto done;
     434             :     }
     435             : 
     436           0 :     ret = sysdb_attrs_get_string(attrs, IPA_TRUSTED_DOMAIN_SID, &id);
     437           0 :     if (ret) {
     438           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     439           0 :         goto done;
     440             :     }
     441             : 
     442           0 :     mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, id);
     443             : 
     444           0 :     ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb),
     445             :                                 attrs, &forest);
     446           0 :     if (ret != EOK) {
     447           0 :         goto done;
     448             :     }
     449             : 
     450           0 :     ret = ipa_subdom_enumerates(parent, attrs, &enumerate);
     451           0 :     if (ret != EOK) {
     452           0 :         goto done;
     453             :     }
     454             : 
     455           0 :     ret = ipa_get_sd_trust_direction(attrs, id_ctx,
     456             :                                      sysdb_ctx_get_ldb(parent->sysdb),
     457             :                                      &direction);
     458           0 :     if (ret != EOK) {
     459           0 :         DEBUG(SSSDBG_OP_FAILURE,
     460             :               "ipa_get_sd_trust_direction failed: %d\n", ret);
     461           0 :         goto done;
     462             :     }
     463             : 
     464           0 :     DEBUG(SSSDBG_FUNC_DATA,
     465             :           "Trust direction of %s is %s\n", name, ipa_trust_dir2str(direction));
     466           0 :     ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat,
     467             :                                 id, mpg, enumerate, forest,
     468             :                                 direction);
     469           0 :     if (ret) {
     470           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n");
     471           0 :         goto done;
     472             :     }
     473             : 
     474           0 :     ret = EOK;
     475             : done:
     476           0 :     talloc_free(tmp_ctx);
     477           0 :     return ret;
     478             : }
     479             : 
     480           0 : static void ipa_subdom_store_step(struct sss_domain_info *parent,
     481             :                                   struct ipa_id_ctx *id_ctx,
     482             :                                   struct sdap_idmap_ctx *sdap_idmap_ctx,
     483             :                                   struct sysdb_attrs *attrs)
     484             : {
     485             :     int ret;
     486             : 
     487           0 :     ret = ipa_subdom_store(parent, id_ctx, sdap_idmap_ctx, attrs);
     488           0 :     if (ret == ERR_TRUST_NOT_SUPPORTED) {
     489           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Unsupported trust type, skipping\n");
     490           0 :     } else if (ret) {
     491             :         /* Nothing we can do about the error. */
     492           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
     493             :               "will try to use cached subdomain\n");
     494             :     }
     495           0 : }
     496             : 
     497           0 : static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
     498             :                                       int count, struct sysdb_attrs **reply,
     499             :                                       bool *changes)
     500           0 : {
     501             :     struct sss_domain_info *parent, *dom;
     502           0 :     bool handled[count];
     503             :     const char *value;
     504             :     int c, h;
     505             :     int ret;
     506             : 
     507           0 :     parent = ctx->be_ctx->domain;
     508           0 :     memset(handled, 0, sizeof(bool) * count);
     509           0 :     h = 0;
     510             : 
     511             :     /* check existing subdomains */
     512           0 :     for (dom = get_next_domain(parent, true);
     513           0 :          dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */
     514           0 :          dom = get_next_domain(dom, false)) {
     515           0 :         for (c = 0; c < count; c++) {
     516           0 :             if (handled[c]) {
     517           0 :                 continue;
     518             :             }
     519           0 :             ret = sysdb_attrs_get_string(reply[c], IPA_CN, &value);
     520           0 :             if (ret != EOK) {
     521           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     522           0 :                 goto done;
     523             :             }
     524           0 :             if (strcmp(value, dom->name) == 0) {
     525           0 :                 break;
     526             :             }
     527             :         }
     528             : 
     529           0 :         if (c >= count) {
     530             :             /* ok this subdomain does not exist anymore, let's clean up */
     531           0 :             sss_domain_set_state(dom, DOM_DISABLED);
     532           0 :             ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
     533           0 :             if (ret != EOK) {
     534           0 :                 goto done;
     535             :             }
     536             : 
     537             :             /* Remove the AD ID ctx from the list of LDAP domains */
     538           0 :             ipa_ad_subdom_remove(ctx->be_ctx, ctx->id_ctx, dom);
     539             :         } else {
     540             :             /* ok let's try to update it */
     541           0 :             ipa_subdom_store_step(parent, ctx->id_ctx,
     542           0 :                                   ctx->sdap_id_ctx->opts->idmap_ctx,
     543           0 :                                   reply[c]);
     544           0 :             handled[c] = true;
     545           0 :             h++;
     546             :         }
     547             :     }
     548             : 
     549           0 :     if (count == h) {
     550             :         /* all domains were already accounted for and have been updated */
     551           0 :         ret = EOK;
     552           0 :         goto done;
     553             :     }
     554             : 
     555             :     /* if we get here it means we have changes to the subdomains list */
     556           0 :     *changes = true;
     557             : 
     558           0 :     for (c = 0; c < count; c++) {
     559           0 :         if (handled[c]) {
     560           0 :             continue;
     561             :         }
     562             : 
     563           0 :         ipa_subdom_store_step(parent, ctx->id_ctx,
     564           0 :                               ctx->sdap_id_ctx->opts->idmap_ctx,
     565           0 :                               reply[c]);
     566             :     }
     567             : 
     568           0 :     ret = EOK;
     569             : done:
     570           0 :     if (ret != EOK) {
     571           0 :         ctx->last_refreshed = 0;
     572             :     } else {
     573           0 :         ctx->last_refreshed = time(NULL);
     574             :     }
     575             : 
     576           0 :     return ret;
     577             : }
     578             : 
     579             : struct ipa_subdomains_req_ctx {
     580             :     struct be_req *be_req;
     581             :     struct ipa_subdomains_ctx *sd_ctx;
     582             :     struct sdap_id_op *sdap_op;
     583             : 
     584             :     char *current_filter;
     585             : 
     586             :     struct sdap_search_base **search_bases;
     587             :     int search_base_iter;
     588             : 
     589             :     size_t reply_count;
     590             :     struct sysdb_attrs **reply;
     591             : };
     592             : 
     593             : static void ipa_subdomains_get_conn_done(struct tevent_req *req);
     594             : static errno_t
     595             : ipa_subdomains_handler_get_start(struct ipa_subdomains_req_ctx *ctx,
     596             :                                  struct sdap_search_base **search_bases,
     597             :                                  enum ipa_subdomains_req_type type);
     598             : static errno_t
     599             : ipa_subdomains_handler_get_cont(struct ipa_subdomains_req_ctx *ctx,
     600             :                                 enum ipa_subdomains_req_type type);
     601             : static void ipa_subdomains_handler_done(struct tevent_req *req);
     602             : static void ipa_subdomains_handler_master_done(struct tevent_req *req);
     603             : static void ipa_subdomains_handler_ranges_done(struct tevent_req *req);
     604             : 
     605             : static struct ipa_subdomains_req_params subdomain_requests[] = {
     606             :     { MASTER_DOMAIN_FILTER,
     607             :       ipa_subdomains_handler_master_done,
     608             :       { IPA_CN, IPA_FLATNAME, IPA_SID, NULL }
     609             :     },
     610             :     { SUBDOMAINS_FILTER,
     611             :       ipa_subdomains_handler_done,
     612             :       { IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID,
     613             :         IPA_TRUST_DIRECTION, NULL }
     614             :     },
     615             :     { RANGE_FILTER,
     616             :       ipa_subdomains_handler_ranges_done,
     617             :       { OBJECTCLASS, IPA_CN,
     618             :         IPA_BASE_ID, IPA_BASE_RID, IPA_SECONDARY_BASE_RID,
     619             :         IPA_ID_RANGE_SIZE, IPA_TRUSTED_DOMAIN_SID, IPA_RANGE_TYPE, NULL
     620             :       }
     621             :     }
     622             : };
     623             : 
     624           0 : static void ipa_subdomains_retrieve(struct ipa_subdomains_ctx *ctx, struct be_req *be_req)
     625             : {
     626           0 :     struct ipa_subdomains_req_ctx *req_ctx = NULL;
     627             :     struct tevent_req *req;
     628           0 :     int dp_error = DP_ERR_FATAL;
     629             :     int ret;
     630             : 
     631           0 :     req_ctx = talloc(be_req, struct ipa_subdomains_req_ctx);
     632           0 :     if (req_ctx == NULL) {
     633           0 :         ret = ENOMEM;
     634           0 :         goto done;
     635             :     }
     636             : 
     637           0 :     req_ctx->be_req = be_req;
     638           0 :     req_ctx->sd_ctx = ctx;
     639           0 :     req_ctx->search_base_iter = 0;
     640           0 :     req_ctx->search_bases = ctx->ranges_search_bases;
     641           0 :     req_ctx->current_filter = NULL;
     642           0 :     req_ctx->reply_count = 0;
     643           0 :     req_ctx->reply = NULL;
     644             : 
     645           0 :     req_ctx->sdap_op = sdap_id_op_create(req_ctx,
     646           0 :                                          ctx->sdap_id_ctx->conn->conn_cache);
     647           0 :     if (req_ctx->sdap_op == NULL) {
     648           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
     649           0 :         ret = ENOMEM;
     650           0 :         goto done;
     651             :     }
     652             : 
     653           0 :     req = sdap_id_op_connect_send(req_ctx->sdap_op, req_ctx, &ret);
     654           0 :     if (req == NULL) {
     655           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: %d(%s).\n",
     656             :                                   ret, strerror(ret));
     657           0 :         goto done;
     658             :     }
     659             : 
     660           0 :     tevent_req_set_callback(req, ipa_subdomains_get_conn_done, req_ctx);
     661             : 
     662           0 :     return;
     663             : 
     664             : done:
     665           0 :     talloc_free(req_ctx);
     666           0 :     if (ret == EOK) {
     667           0 :         dp_error = DP_ERR_OK;
     668             :     }
     669           0 :     ipa_subdomains_done(ctx, be_req, dp_error, ret, NULL);
     670             : }
     671             : 
     672           0 : static void ipa_subdomains_get_conn_done(struct tevent_req *req)
     673             : {
     674             :     int ret;
     675           0 :     int dp_error = DP_ERR_FATAL;
     676             :     struct ipa_subdomains_req_ctx *ctx;
     677             : 
     678           0 :     ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
     679             : 
     680           0 :     ret = sdap_id_op_connect_recv(req, &dp_error);
     681           0 :     talloc_zfree(req);
     682           0 :     if (ret) {
     683           0 :         if (dp_error == DP_ERR_OFFLINE) {
     684           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     685             :                   "No IPA server is available, cannot get the "
     686             :                    "subdomain list while offline\n");
     687             :         } else {
     688           0 :             DEBUG(SSSDBG_OP_FAILURE,
     689             :                   "Failed to connect to IPA server: [%d](%s)\n",
     690             :                    ret, strerror(ret));
     691             :         }
     692             : 
     693           0 :         goto fail;
     694             :     }
     695             : 
     696           0 :     ret = ipa_subdomains_handler_get_start(ctx,
     697           0 :                                            ctx->sd_ctx->ranges_search_bases,
     698             :                                            IPA_SUBDOMAINS_RANGES);
     699           0 :     if (ret != EOK && ret != EAGAIN) {
     700           0 :         goto fail;
     701             :     }
     702             : 
     703           0 :     return;
     704             : 
     705             : fail:
     706           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
     707             : }
     708             : 
     709             : static errno_t
     710           0 : ipa_subdomains_handler_get(struct ipa_subdomains_req_ctx *ctx,
     711             :                            enum ipa_subdomains_req_type type)
     712             : {
     713             :     struct tevent_req *req;
     714             :     struct sdap_search_base *base;
     715             :     struct ipa_subdomains_req_params *params;
     716             : 
     717           0 :     if (type >= IPA_SUBDOMAINS_MAX) {
     718           0 :         return EINVAL;
     719             :     }
     720             : 
     721           0 :     params = &subdomain_requests[type];
     722             : 
     723           0 :     base = ctx->search_bases[ctx->search_base_iter];
     724           0 :     if (base == NULL) {
     725           0 :         return EOK;
     726             :     }
     727             : 
     728           0 :     talloc_free(ctx->current_filter);
     729           0 :     ctx->current_filter = sdap_get_id_specific_filter(ctx, params->filter,
     730             :                                                             base->filter);
     731           0 :     if (ctx->current_filter == NULL) {
     732           0 :         return ENOMEM;
     733             :     }
     734             : 
     735           0 :     req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
     736           0 :                         ctx->sd_ctx->sdap_id_ctx->opts,
     737             :                         sdap_id_op_handle(ctx->sdap_op),
     738             :                         base->basedn, base->scope,
     739           0 :                         ctx->current_filter, params->attrs, NULL, 0,
     740           0 :                         dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
     741             :                                        SDAP_SEARCH_TIMEOUT), false);
     742             : 
     743           0 :     if (req == NULL) {
     744           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
     745           0 :         return ENOMEM;
     746             :     }
     747             : 
     748           0 :     tevent_req_set_callback(req, params->cb, ctx);
     749             : 
     750           0 :     return EAGAIN;
     751             : }
     752             : 
     753             : static errno_t
     754           0 : ipa_subdomains_handler_get_start(struct ipa_subdomains_req_ctx *ctx,
     755             :                                  struct sdap_search_base **search_bases,
     756             :                                  enum ipa_subdomains_req_type type)
     757             : {
     758           0 :     ctx->search_base_iter = 0;
     759           0 :     ctx->search_bases = search_bases;
     760           0 :     return ipa_subdomains_handler_get(ctx, type);
     761             : }
     762             : 
     763             : static errno_t
     764           0 : ipa_subdomains_handler_get_cont(struct ipa_subdomains_req_ctx *ctx,
     765             :                                 enum ipa_subdomains_req_type type)
     766             : {
     767           0 :     ctx->search_base_iter++;
     768           0 :     return ipa_subdomains_handler_get(ctx, type);
     769             : }
     770             : 
     771             : static void ipa_get_view_name_done(struct tevent_req *req);
     772             : static void ipa_server_create_trusts_done(struct tevent_req *trust_req);
     773             : static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx);
     774             : 
     775           0 : static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx)
     776             : {
     777             :     struct tevent_req *req;
     778             :     struct sdap_search_base *base;
     779           0 :     const char *attrs[] = {IPA_CN, OBJECTCLASS, NULL};
     780             :     struct sdap_attr_map_info *maps;
     781             : 
     782           0 :     maps = talloc_zero(ctx, struct sdap_attr_map_info);
     783           0 :     if (maps == NULL) {
     784           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
     785           0 :         return ENOMEM;
     786             :     }
     787           0 :     maps->map = ctx->sd_ctx->id_ctx->ipa_options->view_map;
     788           0 :     maps->num_attrs = IPA_OPTS_VIEW;
     789             : 
     790           0 :     base = ctx->search_bases[ctx->search_base_iter];
     791           0 :     if (base == NULL) {
     792           0 :         return EOK;
     793             :     }
     794             : 
     795           0 :     req = sdap_deref_search_with_filter_send(ctx, ctx->sd_ctx->be_ctx->ev,
     796           0 :                         ctx->sd_ctx->sdap_id_ctx->opts,
     797             :                         sdap_id_op_handle(ctx->sdap_op),
     798             :                         base->basedn,
     799           0 :                         ctx->current_filter, IPA_ASSIGNED_ID_VIEW, attrs,
     800             :                         1, maps,
     801           0 :                         dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
     802             :                                        SDAP_SEARCH_TIMEOUT));
     803             : 
     804           0 :     if (req == NULL) {
     805           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n");
     806           0 :         return ENOMEM;
     807             :     }
     808             : 
     809           0 :     tevent_req_set_callback(req, ipa_get_view_name_done, ctx);
     810             : 
     811           0 :     return EAGAIN;
     812             : }
     813             : 
     814           0 : static void ipa_get_view_name_done(struct tevent_req *req)
     815             : {
     816             :     int ret;
     817             :     int sret;
     818             :     struct ipa_subdomains_req_ctx *ctx;
     819             :     size_t reply_count;
     820           0 :     struct sdap_deref_attrs **reply = NULL;
     821             :     const char *view_name;
     822           0 :     int dp_error = DP_ERR_FATAL;
     823             : 
     824           0 :     ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
     825             : 
     826           0 :     ret = sdap_deref_search_with_filter_recv(req, ctx, &reply_count, &reply);
     827           0 :     talloc_zfree(req);
     828           0 :     if (ret != EOK) {
     829             :         /* Depending on the version 389ds return a different error code if the
     830             :          * search for the view name failed because our dereference attribute
     831             :          * ipaAssignedIDView is not known. Newer version return
     832             :          * LDAP_UNAVAILABLE_CRITICAL_EXTENSION(12) which is translated to
     833             :          * EOPNOTSUPP and older versions return LDAP_PROTOCOL_ERROR(2) which
     834             :          * is returned as EIO. In both cases we have to assume that the server
     835             :          * is not view aware and keep the view name unset. */
     836           0 :         if (ret == EOPNOTSUPP || ret == EIO) {
     837           0 :             DEBUG(SSSDBG_TRACE_FUNC, "get_view_name request failed, looks " \
     838             :                                      "like server does not support views.\n");
     839           0 :             ret = ipa_check_master(ctx);
     840           0 :             if (ret == EAGAIN) {
     841           0 :                 return;
     842           0 :             } else if (ret != EOK) {
     843           0 :                 goto done;
     844             :             }
     845             : 
     846             :         } else {
     847           0 :             DEBUG(SSSDBG_OP_FAILURE, "get_view_name request failed.\n");
     848             :         }
     849           0 :         goto done;
     850             :     }
     851             : 
     852           0 :     if (reply_count == 0) {
     853           0 :         ctx->search_base_iter++;
     854           0 :         ret = ipa_get_view_name(ctx);
     855           0 :         if (ret == EAGAIN) {
     856           0 :             return;
     857           0 :         } else if (ret == EOK) {
     858           0 :             DEBUG(SSSDBG_TRACE_FUNC, "No view found, using default.\n");
     859           0 :             view_name = SYSDB_DEFAULT_VIEW_NAME;
     860             :         } else {
     861           0 :             goto done;
     862             :         }
     863           0 :     } else if (reply_count > 1) {
     864           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     865             :               "get_view_name request returned more than one object.\n");
     866           0 :         ret = EINVAL;
     867           0 :         goto done;
     868             :     } else {
     869           0 :         ret = sysdb_attrs_get_string(reply[0]->attrs, SYSDB_VIEW_NAME,
     870             :                                      &view_name);
     871           0 :         if (ret != EOK) {
     872           0 :             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
     873           0 :             goto done;
     874             :         }
     875             :     }
     876             : 
     877           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Found view name [%s].\n", view_name);
     878           0 :     if (is_default_view(view_name)) {
     879           0 :         DEBUG(SSSDBG_TRACE_ALL,
     880             :               "Found IPA default view name, replacing with sysdb default.\n");
     881           0 :         view_name = SYSDB_DEFAULT_VIEW_NAME;
     882             :     }
     883             : 
     884           0 :     DEBUG(SSSDBG_TRACE_ALL, "read_at_init [%s] current view  [%s].\n",
     885             :                              ctx->sd_ctx->view_read_at_init ? "true" : "false",
     886             :                              ctx->sd_ctx->id_ctx->view_name);
     887             : 
     888           0 :     if (ctx->sd_ctx->id_ctx->view_name != NULL
     889           0 :             && strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0
     890           0 :             && ctx->sd_ctx->view_read_at_init) {
     891           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     892             :               "View name changed, this is not supported at runtime. " \
     893             :               "Please restart SSSD to get the new view applied.\n");
     894             :     } else {
     895           0 :         if (ctx->sd_ctx->id_ctx->view_name == NULL
     896           0 :             || strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
     897             :             /* View name changed */
     898             : 
     899           0 :             if (ctx->sd_ctx->id_ctx->view_name != NULL) {
     900           0 :                 ret = sysdb_transaction_start(
     901           0 :                                             ctx->sd_ctx->be_ctx->domain->sysdb);
     902           0 :                 if (ret != EOK) {
     903           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     904             :                           "sysdb_transaction_start failed.\n");
     905           0 :                     goto done;
     906             :                 }
     907             : 
     908           0 :                 if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)
     909           0 :                         && !is_local_view(ctx->sd_ctx->id_ctx->view_name)) {
     910             :                     /* Old view was not the default view, delete view tree */
     911           0 :                     ret = sysdb_delete_view_tree(
     912           0 :                                              ctx->sd_ctx->be_ctx->domain->sysdb,
     913           0 :                                              ctx->sd_ctx->id_ctx->view_name);
     914           0 :                     if (ret != EOK) {
     915           0 :                         DEBUG(SSSDBG_OP_FAILURE,
     916             :                               "sysdb_delete_view_tree failed.\n");
     917           0 :                         sret = sysdb_transaction_cancel(
     918           0 :                                             ctx->sd_ctx->be_ctx->domain->sysdb);
     919           0 :                         if (sret != EOK) {
     920           0 :                             DEBUG(SSSDBG_OP_FAILURE,
     921             :                                   "sysdb_transaction_cancel failed.\n");
     922           0 :                             goto done;
     923             :                         }
     924           0 :                         goto done;
     925             :                     }
     926             :                 }
     927             : 
     928           0 :                 ret = sysdb_invalidate_overrides(
     929           0 :                                             ctx->sd_ctx->be_ctx->domain->sysdb);
     930           0 :                 if (ret != EOK) {
     931           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     932             :                           "sysdb_invalidate_overrides failed.\n");
     933           0 :                     sret = sysdb_transaction_cancel(
     934           0 :                                             ctx->sd_ctx->be_ctx->domain->sysdb);
     935           0 :                     if (sret != EOK) {
     936           0 :                         DEBUG(SSSDBG_OP_FAILURE,
     937             :                               "sysdb_transaction_cancel failed.\n");
     938           0 :                         goto done;
     939             :                     }
     940           0 :                     goto done;
     941             :                 }
     942             : 
     943           0 :                 ret = sysdb_transaction_commit(
     944           0 :                                             ctx->sd_ctx->be_ctx->domain->sysdb);
     945           0 :                 if (ret != EOK) {
     946           0 :                     DEBUG(SSSDBG_OP_FAILURE,
     947             :                                           "sysdb_transaction_commit failed.\n");
     948           0 :                     goto done;
     949             :                 }
     950             : 
     951             :                 /* TODO: start referesh task */
     952             :             }
     953             : 
     954           0 :             ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
     955             :                                          view_name);
     956           0 :             if (ret != EOK) {
     957           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     958             :                       "Cannot add/update view name to sysdb.\n");
     959             :             } else {
     960           0 :                 talloc_free(ctx->sd_ctx->id_ctx->view_name);
     961           0 :                 ctx->sd_ctx->id_ctx->view_name = talloc_strdup(
     962           0 :                                                             ctx->sd_ctx->id_ctx,
     963             :                                                             view_name);
     964           0 :                 if (ctx->sd_ctx->id_ctx->view_name == NULL) {
     965           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
     966             :                 }
     967             :             }
     968             :         }
     969             : 
     970           0 :         if (!ctx->sd_ctx->view_read_at_init) {
     971             :             /* refresh view data of all domains at startup */
     972           0 :             ret = sysdb_master_domain_update(ctx->sd_ctx->be_ctx->domain);
     973           0 :             if (ret != EOK) {
     974           0 :                 DEBUG(SSSDBG_OP_FAILURE,
     975             :                       "sysdb_master_domain_update failed.\n");
     976           0 :                 goto done;
     977             :             }
     978             : 
     979           0 :             ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain);
     980           0 :             if (ret != EOK) {
     981           0 :                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
     982           0 :                 goto done;
     983             :             }
     984             :         }
     985             : 
     986           0 :         ctx->sd_ctx->view_read_at_init = true;
     987             : 
     988             :     }
     989             : 
     990           0 :     ret = EOK;
     991             : done:
     992           0 :     if (ret == EOK) {
     993           0 :         dp_error = DP_ERR_OK;
     994             :     }
     995           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
     996             : }
     997             : 
     998           0 : static void ipa_subdomains_handler_done(struct tevent_req *req)
     999             : {
    1000             :     int ret;
    1001             :     size_t reply_count;
    1002           0 :     struct sysdb_attrs **reply = NULL;
    1003             :     struct ipa_subdomains_req_ctx *ctx;
    1004             :     struct sss_domain_info *domain;
    1005           0 :     bool refresh_has_changes = false;
    1006           0 :     int dp_error = DP_ERR_FATAL;
    1007             :     struct tevent_req *trust_req;
    1008             : 
    1009           0 :     ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
    1010           0 :     domain = ctx->sd_ctx->be_ctx->domain;
    1011             : 
    1012           0 :     ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
    1013           0 :     talloc_zfree(req);
    1014           0 :     if (ret != EOK) {
    1015           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
    1016           0 :         goto done;
    1017             :     }
    1018             : 
    1019           0 :     if (reply_count) {
    1020           0 :         ctx->reply = talloc_realloc(ctx, ctx->reply, struct sysdb_attrs *,
    1021             :                                     ctx->reply_count + reply_count);
    1022           0 :         if (ctx->reply == NULL) {
    1023           0 :             ret = ENOMEM;
    1024           0 :             goto done;
    1025             :         }
    1026           0 :         memcpy(ctx->reply+ctx->reply_count, reply,
    1027             :                reply_count * sizeof(struct sysdb_attrs *));
    1028           0 :         ctx->reply_count += reply_count;
    1029             :     }
    1030             : 
    1031           0 :     ret = ipa_subdomains_handler_get_cont(ctx, IPA_SUBDOMAINS_SLAVE);
    1032           0 :     if (ret == EAGAIN) {
    1033           0 :         return;
    1034           0 :     } else if (ret != EOK) {
    1035           0 :         goto done;
    1036             :     }
    1037             : 
    1038           0 :     ret = ipa_subdomains_refresh(ctx->sd_ctx, ctx->reply_count, ctx->reply,
    1039             :                                  &refresh_has_changes);
    1040           0 :     if (ret != EOK) {
    1041           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to refresh subdomains.\n");
    1042           0 :         goto done;
    1043             :     }
    1044             : 
    1045           0 :     if (refresh_has_changes) {
    1046           0 :         ret = ipa_subdom_reinit(ctx->sd_ctx);
    1047           0 :         if (ret != EOK) {
    1048           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n");
    1049           0 :             goto done;
    1050             :         }
    1051             : 
    1052           0 :         if (ctx->sd_ctx->id_ctx->server_mode != NULL) {
    1053           0 :             trust_req = ipa_server_create_trusts_send(ctx, ctx->sd_ctx->be_ctx->ev,
    1054           0 :                                                       ctx->sd_ctx->be_ctx,
    1055           0 :                                                       ctx->sd_ctx->id_ctx,
    1056             :                                                       domain);
    1057           0 :             if (trust_req == NULL) {
    1058           0 :                 ret = ENOMEM;
    1059           0 :                 goto done;
    1060             :             }
    1061           0 :             tevent_req_set_callback(trust_req, ipa_server_create_trusts_done, ctx);
    1062           0 :             return;
    1063             :         }
    1064             :     }
    1065             : 
    1066           0 :     ctx->search_base_iter = 0;
    1067           0 :     ctx->search_bases = ctx->sd_ctx->host_search_bases;
    1068           0 :     talloc_zfree(ctx->current_filter);
    1069           0 :     ctx->current_filter = talloc_asprintf(ctx, "(&(objectClass=%s)(%s=%s))",
    1070           0 :               ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_OC_HOST].name,
    1071           0 :               ctx->sd_ctx->id_ctx->ipa_options->host_map[IPA_AT_HOST_FQDN].name,
    1072           0 :               dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic,
    1073             :                                 IPA_HOSTNAME));
    1074           0 :     if (ctx->current_filter == NULL) {
    1075           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
    1076           0 :         ret = ENOMEM;
    1077           0 :         goto done;
    1078             :     }
    1079             : 
    1080           0 :     if (ctx->sd_ctx->id_ctx->server_mode == NULL) {
    1081             :         /* Only get view on clients, on servers it is always 'default' */
    1082           0 :         ret = ipa_get_view_name(ctx);
    1083           0 :         if (ret == EAGAIN) {
    1084           0 :             return;
    1085           0 :         } else if (ret != EOK) {
    1086           0 :             goto done;
    1087             :         }
    1088             :     }
    1089             : 
    1090           0 :     ret = EOK;
    1091             : done:
    1092           0 :     if (ret == EOK) {
    1093           0 :         dp_error = DP_ERR_OK;
    1094             :     }
    1095           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
    1096             : }
    1097             : 
    1098           0 : static void ipa_server_create_trusts_done(struct tevent_req *trust_req)
    1099             : {
    1100             :     errno_t ret;
    1101           0 :     int dp_error = DP_ERR_FATAL;
    1102             :     struct ipa_subdomains_req_ctx *ctx;
    1103             : 
    1104           0 :     ctx = tevent_req_callback_data(trust_req, struct ipa_subdomains_req_ctx);
    1105             : 
    1106           0 :     ret = ipa_server_create_trusts_recv(trust_req);
    1107           0 :     talloc_zfree(trust_req);
    1108           0 :     if (ret == EOK) {
    1109           0 :         dp_error = DP_ERR_OK;
    1110             :     }
    1111             : 
    1112           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
    1113           0 : }
    1114             : 
    1115           0 : static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx)
    1116             : {
    1117             :     int ret;
    1118             :     struct sss_domain_info *domain;
    1119             : 
    1120           0 :     domain = ctx->sd_ctx->be_ctx->domain;
    1121             : 
    1122           0 :     ret = sysdb_master_domain_update(domain);
    1123           0 :     if (ret != EOK) {
    1124           0 :         return ret;
    1125             :     }
    1126             : 
    1127           0 :     if (domain->flat_name == NULL ||
    1128           0 :         domain->domain_id == NULL ||
    1129           0 :         domain->realm == NULL) {
    1130             : 
    1131           0 :         ret = ipa_subdomains_handler_get_start(ctx,
    1132           0 :                                                ctx->sd_ctx->master_search_bases,
    1133             :                                                IPA_SUBDOMAINS_MASTER);
    1134           0 :         if (ret == EAGAIN) {
    1135           0 :             return EAGAIN;
    1136           0 :         } else if (ret != EOK) {
    1137           0 :             return ret;
    1138             :         }
    1139             :     }
    1140             : 
    1141           0 :     return EOK;
    1142             : }
    1143             : 
    1144             : 
    1145           0 : static void ipa_subdomains_handler_ranges_done(struct tevent_req *req)
    1146             : {
    1147             :     errno_t ret;
    1148           0 :     int dp_error = DP_ERR_FATAL;
    1149             :     size_t reply_count;
    1150           0 :     struct sysdb_attrs **reply = NULL;
    1151             :     struct ipa_subdomains_req_ctx *ctx;
    1152           0 :     struct range_info **range_list = NULL;
    1153             :     struct sysdb_ctx *sysdb;
    1154             :     struct sss_domain_info *domain;
    1155             : 
    1156           0 :     ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
    1157           0 :     domain = ctx->sd_ctx->be_ctx->domain;
    1158           0 :     sysdb = domain->sysdb;
    1159             : 
    1160           0 :     ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
    1161           0 :     talloc_zfree(req);
    1162           0 :     if (ret != EOK) {
    1163           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
    1164           0 :         goto done;
    1165             :     }
    1166             : 
    1167           0 :     ret = ipa_ranges_parse_results(ctx, domain->name,
    1168             :                                    reply_count, reply, &range_list);
    1169           0 :     if (ret != EOK) {
    1170           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1171             :               "ipa_ranges_parse_results request failed.\n");
    1172           0 :         goto done;
    1173             :     }
    1174             : 
    1175           0 :     ret = sysdb_update_ranges(sysdb, range_list);
    1176           0 :     talloc_free(range_list);
    1177           0 :     if (ret != EOK) {
    1178           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_ranges failed.\n");
    1179           0 :         goto done;
    1180             :     }
    1181             : 
    1182           0 :     ret = ipa_check_master(ctx);
    1183           0 :     if (ret == EAGAIN) {
    1184           0 :         DEBUG(SSSDBG_TRACE_ALL, "Checking master record..\n");
    1185           0 :         return;
    1186           0 :     } else if (ret != EOK) {
    1187           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_check_master failed.\n");
    1188           0 :         goto done;
    1189             :     }
    1190             :     /* Master domain is up-to-date. Continue checking subdomains */
    1191             : 
    1192           0 :     DEBUG(SSSDBG_TRACE_ALL, "Master record up2date, checking subdomains\n");
    1193           0 :     ret = ipa_subdomains_handler_get_start(ctx, ctx->sd_ctx->search_bases,
    1194             :                                            IPA_SUBDOMAINS_SLAVE);
    1195           0 :     if (ret == EAGAIN) {
    1196           0 :         return;
    1197           0 :     } else if (ret != EOK) {
    1198           0 :         goto done;
    1199             :     }
    1200             : 
    1201           0 :     DEBUG(SSSDBG_OP_FAILURE, "No search base for ranges available.\n");
    1202           0 :     ret = EINVAL;
    1203             : 
    1204             : done:
    1205           0 :     if (ret == EOK) {
    1206           0 :         dp_error = DP_ERR_OK;
    1207             :     }
    1208           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
    1209             : }
    1210             : 
    1211           0 : static void ipa_subdomains_handler_master_done(struct tevent_req *req)
    1212             : {
    1213             :     errno_t ret;
    1214           0 :     int dp_error = DP_ERR_FATAL;
    1215           0 :     size_t reply_count = 0;
    1216           0 :     struct sysdb_attrs **reply = NULL;
    1217             :     struct ipa_subdomains_req_ctx *ctx;
    1218             : 
    1219           0 :     ctx = tevent_req_callback_data(req, struct ipa_subdomains_req_ctx);
    1220             : 
    1221           0 :     ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
    1222           0 :     talloc_zfree(req);
    1223           0 :     if (ret != EOK) {
    1224           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send request failed.\n");
    1225           0 :         goto done;
    1226             :     }
    1227             : 
    1228           0 :     if (reply_count) {
    1229           0 :         const char *flat = NULL;
    1230           0 :         const char *id = NULL;
    1231             :         const char *realm;
    1232             : 
    1233           0 :         ret = sysdb_attrs_get_string(reply[0], IPA_FLATNAME, &flat);
    1234           0 :         if (ret != EOK) {
    1235           0 :             goto done;
    1236             :         }
    1237             : 
    1238           0 :         ret = sysdb_attrs_get_string(reply[0], IPA_SID, &id);
    1239           0 :         if (ret != EOK) {
    1240           0 :             goto done;
    1241             :         }
    1242             : 
    1243           0 :         realm = dp_opt_get_string(ctx->sd_ctx->id_ctx->ipa_options->basic,
    1244             :                                   IPA_KRB5_REALM);
    1245           0 :         if (realm == NULL) {
    1246           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
    1247           0 :             ret = EINVAL;
    1248           0 :             goto done;
    1249             :         }
    1250             : 
    1251           0 :         ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
    1252             :                                            realm, flat, id, NULL);
    1253           0 :         if (ret != EOK) {
    1254           0 :             goto done;
    1255             :         }
    1256             : 
    1257             :         /* There is only one master record. Don't bother checking other IPA
    1258             :          * search bases; move to checking subdomains instead
    1259             :          */
    1260           0 :         ret = ipa_subdomains_handler_get_start(ctx,
    1261           0 :                                                ctx->sd_ctx->search_bases,
    1262             :                                                IPA_SUBDOMAINS_SLAVE);
    1263           0 :         if (ret == EAGAIN) {
    1264           0 :             return;
    1265             :         }
    1266             : 
    1267             :         /* Either no search bases or an error. End the request in both cases */
    1268             :     } else {
    1269           0 :         ret = ipa_subdomains_handler_get_cont(ctx, IPA_SUBDOMAINS_MASTER);
    1270           0 :         if (ret == EAGAIN) {
    1271           0 :             return;
    1272           0 :         } else if (ret != EOK) {
    1273           0 :             goto done;
    1274             :         }
    1275             : 
    1276             :         /* Right now we know there has been an error
    1277             :          * and we don't have the master domain record
    1278             :          */
    1279           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Master domain record not found!\n");
    1280             : 
    1281           0 :         if (!ctx->sd_ctx->configured_explicit) {
    1282           0 :             ctx->sd_ctx->disabled_until = time(NULL) +
    1283             :                                           IPA_SUBDOMAIN_DISABLED_PERIOD;
    1284             :         }
    1285             : 
    1286           0 :         ret = EIO;
    1287             :     }
    1288             : 
    1289             : done:
    1290           0 :     if (ret == EOK) {
    1291           0 :         dp_error = DP_ERR_OK;
    1292             :     }
    1293           0 :     ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
    1294             : }
    1295             : 
    1296             : static void ipa_subdom_online_cb(void *pvt);
    1297             : 
    1298           0 : static void ipa_subdom_timer_refresh(struct tevent_context *ev,
    1299             :                                      struct tevent_timer *te,
    1300             :                                      struct timeval current_time,
    1301             :                                      void *pvt)
    1302             : {
    1303           0 :     ipa_subdom_online_cb(pvt);
    1304           0 : }
    1305             : 
    1306           0 : static void ipa_subdom_be_req_callback(struct be_req *be_req,
    1307             :                                        int dp_err, int dp_ret,
    1308             :                                        const char *errstr)
    1309             : {
    1310           0 :     talloc_free(be_req);
    1311           0 : }
    1312             : 
    1313           0 : static void ipa_subdom_reset_timeouts_cb(void *pvt)
    1314             : {
    1315             :     struct ipa_subdomains_ctx *ctx;
    1316             : 
    1317           0 :     ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
    1318           0 :     if (ctx == NULL) {
    1319           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
    1320           0 :         return;
    1321             :     }
    1322             : 
    1323           0 :     DEBUG(SSSDBG_TRACE_ALL, "Resetting last_refreshed and disabled_until.\n");
    1324           0 :     ctx->last_refreshed = 0;
    1325           0 :     ctx->disabled_until = 0;
    1326             : }
    1327             : 
    1328           0 : static void ipa_subdom_online_cb(void *pvt)
    1329             : {
    1330             :     struct ipa_subdomains_ctx *ctx;
    1331             :     struct be_req *be_req;
    1332             :     struct timeval tv;
    1333             :     uint32_t refresh_interval;
    1334             : 
    1335           0 :     ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
    1336           0 :     if (!ctx) {
    1337           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bad private pointer\n");
    1338           0 :         return;
    1339             :     }
    1340             : 
    1341           0 :     ctx->disabled_until = 0;
    1342             : 
    1343           0 :     refresh_interval = ctx->be_ctx->domain->subdomain_refresh_interval;
    1344             : 
    1345           0 :     be_req = be_req_create(ctx, NULL, ctx->be_ctx,
    1346             :                            ipa_subdom_be_req_callback, NULL);
    1347           0 :     if (be_req == NULL) {
    1348           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_req_create() failed.\n");
    1349           0 :         return;
    1350             :     }
    1351             : 
    1352           0 :     ipa_subdomains_retrieve(ctx, be_req);
    1353             : 
    1354           0 :     tv = tevent_timeval_current_ofs(refresh_interval, 0);
    1355           0 :     ctx->timer_event = tevent_add_timer(ctx->be_ctx->ev, ctx, tv,
    1356             :                                         ipa_subdom_timer_refresh, ctx);
    1357           0 :     if (!ctx->timer_event) {
    1358           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom timer event\n");
    1359             :     }
    1360             : }
    1361             : 
    1362           0 : static void ipa_subdom_offline_cb(void *pvt)
    1363             : {
    1364             :     struct ipa_subdomains_ctx *ctx;
    1365             : 
    1366           0 :     ctx = talloc_get_type(pvt, struct ipa_subdomains_ctx);
    1367             : 
    1368           0 :     if (ctx) {
    1369           0 :         talloc_zfree(ctx->timer_event);
    1370             :     }
    1371           0 : }
    1372             : 
    1373           0 : static errno_t get_config_status(struct be_ctx *be_ctx,
    1374             :                                  bool *configured_explicit)
    1375             : {
    1376             :     int ret;
    1377           0 :     TALLOC_CTX *tmp_ctx = NULL;
    1378             :     char *tmp_str;
    1379             : 
    1380           0 :     tmp_ctx = talloc_new(NULL);
    1381           0 :     if (tmp_ctx == NULL) {
    1382           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
    1383           0 :         return ENOMEM;
    1384             :     }
    1385             : 
    1386           0 :     ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
    1387             :                             CONFDB_DOMAIN_SUBDOMAINS_PROVIDER, NULL,
    1388             :                             &tmp_str);
    1389           0 :     if (ret != EOK) {
    1390           0 :         DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed.\n");
    1391           0 :         goto done;
    1392             :     }
    1393             : 
    1394           0 :     if (tmp_str == NULL) {
    1395           0 :         *configured_explicit = false;
    1396             :     } else {
    1397           0 :         *configured_explicit = true;
    1398             :     }
    1399             : 
    1400           0 :     DEBUG(SSSDBG_TRACE_ALL, "IPA subdomain provider is configured %s.\n",
    1401             :                              *configured_explicit ? "explicit" : "implicit");
    1402             : 
    1403           0 :     ret = EOK;
    1404             : 
    1405             : done:
    1406           0 :     talloc_free(tmp_ctx);
    1407             : 
    1408           0 :     return ret;
    1409             : }
    1410             : 
    1411           0 : void ipa_subdomains_handler(struct be_req *be_req)
    1412             : {
    1413           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
    1414             :     struct ipa_subdomains_ctx *ctx;
    1415             :     time_t now;
    1416             : 
    1417           0 :     ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
    1418             :                           struct ipa_subdomains_ctx);
    1419           0 :     if (!ctx) {
    1420           0 :         be_req_terminate(be_req, DP_ERR_FATAL, EINVAL, NULL);
    1421           0 :         return;
    1422             :     }
    1423             : 
    1424           0 :     now = time(NULL);
    1425             : 
    1426           0 :     if (ctx->disabled_until > now) {
    1427           0 :         DEBUG(SSSDBG_TRACE_ALL, "Subdomain provider disabled.\n");
    1428           0 :         ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
    1429           0 :         return;
    1430             :     }
    1431             : 
    1432           0 :     if (ctx->last_refreshed > now - IPA_SUBDOMAIN_REFRESH_LIMIT) {
    1433           0 :         ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
    1434           0 :         return;
    1435             :     }
    1436             : 
    1437           0 :     ipa_subdomains_retrieve(ctx, be_req);
    1438             : }
    1439             : 
    1440             : struct bet_ops ipa_subdomains_ops = {
    1441             :     .handler = ipa_subdomains_handler,
    1442             :     .finalize = NULL
    1443             : };
    1444             : 
    1445           0 : int ipa_subdom_init(struct be_ctx *be_ctx,
    1446             :                     struct ipa_id_ctx *id_ctx,
    1447             :                     struct bet_ops **ops,
    1448             :                     void **pvt_data)
    1449             : {
    1450             :     struct ipa_subdomains_ctx *ctx;
    1451             :     int ret;
    1452           0 :     bool configured_explicit = false;
    1453             : 
    1454           0 :     ret = get_config_status(be_ctx, &configured_explicit);
    1455           0 :     if (ret != EOK) {
    1456           0 :         DEBUG(SSSDBG_OP_FAILURE, "get_config_status failed.\n");
    1457           0 :         return ret;
    1458             :     }
    1459             : 
    1460           0 :     ctx = talloc_zero(id_ctx, struct ipa_subdomains_ctx);
    1461           0 :     if (ctx == NULL) {
    1462           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1463           0 :         return ENOMEM;
    1464             :     }
    1465             : 
    1466           0 :     ctx->be_ctx = be_ctx;
    1467           0 :     ctx->id_ctx = id_ctx;
    1468           0 :     ctx->sdap_id_ctx = id_ctx->sdap_id_ctx;
    1469           0 :     ctx->search_bases = id_ctx->ipa_options->subdomains_search_bases;
    1470           0 :     ctx->master_search_bases = id_ctx->ipa_options->master_domain_search_bases;
    1471           0 :     ctx->ranges_search_bases = id_ctx->ipa_options->ranges_search_bases;
    1472           0 :     ctx->host_search_bases = id_ctx->ipa_options->host_search_bases;
    1473           0 :     ctx->configured_explicit = configured_explicit;
    1474           0 :     ctx->disabled_until = 0;
    1475           0 :     *ops = &ipa_subdomains_ops;
    1476           0 :     *pvt_data = ctx;
    1477             : 
    1478           0 :     ret = be_add_unconditional_online_cb(ctx, be_ctx,
    1479             :                                          ipa_subdom_reset_timeouts_cb, ctx,
    1480             :                                          NULL);
    1481           0 :     if (ret != EOK) {
    1482           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    1483             :               "Failed to add subdom reset timeouts callback\n");
    1484             :     }
    1485             : 
    1486           0 :     ret = be_add_online_cb(ctx, be_ctx, ipa_subdom_online_cb, ctx, NULL);
    1487           0 :     if (ret != EOK) {
    1488           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom online callback\n");
    1489             :     }
    1490             : 
    1491           0 :     ret = be_add_offline_cb(ctx, be_ctx, ipa_subdom_offline_cb, ctx, NULL);
    1492           0 :     if (ret != EOK) {
    1493           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Failed to add subdom offline callback\n");
    1494             :     }
    1495             : 
    1496           0 :     ret = ipa_subdom_reinit(ctx);
    1497           0 :     if (ret != EOK) {
    1498           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not load the list of subdomains. "
    1499             :               "Users from trusted domains might not be resolved correctly\n");
    1500             :     }
    1501             : 
    1502           0 :     ret = ipa_ad_subdom_init(be_ctx, id_ctx);
    1503           0 :     if (ret != EOK) {
    1504           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ipa_ad_subdom_init failed.\n");
    1505           0 :         return ret;
    1506             :     }
    1507             : 
    1508           0 :     return EOK;
    1509             : }

Generated by: LCOV version 1.10