"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.2.3/src/providers/ad/ad_common.c" (30 Nov 2019, 45893 Bytes) of package /linux/misc/sssd-2.2.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ad_common.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.1.0_vs_2.2.0.

    1 /*
    2     SSSD
    3 
    4     Authors:
    5         Stephen Gallagher <sgallagh@redhat.com>
    6 
    7     Copyright (C) 2012 Red Hat
    8 
    9     This program is free software; you can redistribute it and/or modify
   10     it under the terms of the GNU General Public License as published by
   11     the Free Software Foundation; either version 3 of the License, or
   12     (at your option) any later version.
   13 
   14     This program is distributed in the hope that it will be useful,
   15     but WITHOUT ANY WARRANTY; without even the implied warranty of
   16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17     GNU General Public License for more details.
   18 
   19     You should have received a copy of the GNU General Public License
   20     along with this program.  If not, see <http://www.gnu.org/licenses/>.
   21 */
   22 #include <ctype.h>
   23 
   24 #include "providers/ad/ad_common.h"
   25 #include "providers/ad/ad_opts.h"
   26 #include "providers/be_dyndns.h"
   27 #include "providers/fail_over.h"
   28 
   29 struct ad_server_data {
   30     bool gc;
   31 };
   32 
   33 errno_t ad_set_search_bases(struct sdap_options *id_opts,
   34                             struct sdap_domain *sdap);
   35 static errno_t ad_set_sdap_options(struct ad_options *ad_opts,
   36                                    struct sdap_options *id_opts);
   37 
   38 static struct sdap_options *
   39 ad_create_default_sdap_options(TALLOC_CTX *mem_ctx,
   40                                struct data_provider *dp)
   41 {
   42     struct sdap_options *id_opts;
   43     errno_t ret;
   44 
   45     id_opts = talloc_zero(mem_ctx, struct sdap_options);
   46     if (!id_opts) {
   47         return NULL;
   48     }
   49     id_opts->dp = dp;
   50 
   51     ret = dp_copy_defaults(id_opts,
   52                            ad_def_ldap_opts,
   53                            SDAP_OPTS_BASIC,
   54                            &id_opts->basic);
   55     if (ret != EOK) {
   56         goto fail;
   57     }
   58 
   59     /* Get sdap option maps */
   60 
   61     /* General Attribute Map */
   62     ret = sdap_copy_map(id_opts,
   63                        ad_2008r2_attr_map,
   64                        SDAP_AT_GENERAL,
   65                        &id_opts->gen_map);
   66     if (ret != EOK) {
   67         goto fail;
   68     }
   69 
   70     /* User map */
   71     ret = sdap_copy_map(id_opts,
   72                        ad_2008r2_user_map,
   73                        SDAP_OPTS_USER,
   74                        &id_opts->user_map);
   75     if (ret != EOK) {
   76         goto fail;
   77     }
   78     id_opts->user_map_cnt = SDAP_OPTS_USER;
   79 
   80     /* Group map */
   81     ret = sdap_copy_map(id_opts,
   82                        ad_2008r2_group_map,
   83                        SDAP_OPTS_GROUP,
   84                        &id_opts->group_map);
   85     if (ret != EOK) {
   86         goto fail;
   87     }
   88 
   89     /* Netgroup map */
   90     ret = sdap_copy_map(id_opts,
   91                        ad_netgroup_map,
   92                        SDAP_OPTS_NETGROUP,
   93                        &id_opts->netgroup_map);
   94     if (ret != EOK) {
   95         goto fail;
   96     }
   97 
   98     /* Services map */
   99     ret = sdap_copy_map(id_opts,
  100                        ad_service_map,
  101                        SDAP_OPTS_SERVICES,
  102                        &id_opts->service_map);
  103     if (ret != EOK) {
  104         goto fail;
  105     }
  106 
  107     return id_opts;
  108 
  109 fail:
  110     talloc_free(id_opts);
  111     return NULL;
  112 }
  113 
  114 static errno_t
  115 ad_create_sdap_options(TALLOC_CTX *mem_ctx,
  116                        struct confdb_ctx *cdb,
  117                        const char *conf_path,
  118                        struct data_provider *dp,
  119                        struct sdap_options **_id_opts)
  120 {
  121     struct sdap_options *id_opts;
  122     errno_t ret = EOK;
  123 
  124     if (cdb == NULL || conf_path == NULL) {
  125         /* Fallback to defaults if there is no confdb */
  126         id_opts = ad_create_default_sdap_options(mem_ctx, dp);
  127         if (id_opts == NULL) {
  128             DEBUG(SSSDBG_CRIT_FAILURE,
  129                   "Failed to initialize default sdap options\n");
  130             ret = EIO;
  131         }
  132         /* Nothing to do without cdb */
  133         goto done;
  134     }
  135 
  136     id_opts = talloc_zero(mem_ctx, struct sdap_options);
  137     if (!id_opts) {
  138         ret = ENOMEM;
  139         goto done;
  140     }
  141 
  142     ret = dp_get_options(id_opts, cdb, conf_path,
  143                          ad_def_ldap_opts,
  144                          SDAP_OPTS_BASIC,
  145                          &id_opts->basic);
  146     if (ret != EOK) {
  147         goto done;
  148     }
  149 
  150     /* Get sdap option maps */
  151 
  152     /* General Attribute Map */
  153     ret = sdap_get_map(id_opts,
  154                        cdb, conf_path,
  155                        ad_2008r2_attr_map,
  156                        SDAP_AT_GENERAL,
  157                        &id_opts->gen_map);
  158     if (ret != EOK) {
  159         goto done;
  160     }
  161 
  162     /* User map */
  163     ret = sdap_get_map(id_opts,
  164                        cdb, conf_path,
  165                        ad_2008r2_user_map,
  166                        SDAP_OPTS_USER,
  167                        &id_opts->user_map);
  168     if (ret != EOK) {
  169         goto done;
  170     }
  171 
  172     ret = sdap_extend_map_with_list(id_opts, id_opts,
  173                                     SDAP_USER_EXTRA_ATTRS,
  174                                     id_opts->user_map,
  175                                     SDAP_OPTS_USER,
  176                                     &id_opts->user_map,
  177                                     &id_opts->user_map_cnt);
  178     if (ret != EOK) {
  179         goto done;
  180     }
  181 
  182     /* Group map */
  183     ret = sdap_get_map(id_opts,
  184                        cdb, conf_path,
  185                        ad_2008r2_group_map,
  186                        SDAP_OPTS_GROUP,
  187                        &id_opts->group_map);
  188     if (ret != EOK) {
  189         goto done;
  190     }
  191 
  192     /* Netgroup map */
  193     ret = sdap_get_map(id_opts,
  194                        cdb, conf_path,
  195                        ad_netgroup_map,
  196                        SDAP_OPTS_NETGROUP,
  197                        &id_opts->netgroup_map);
  198     if (ret != EOK) {
  199         goto done;
  200     }
  201 
  202     /* Services map */
  203     ret = sdap_get_map(id_opts,
  204                        cdb, conf_path,
  205                        ad_service_map,
  206                        SDAP_OPTS_SERVICES,
  207                        &id_opts->service_map);
  208     if (ret != EOK) {
  209         goto done;
  210     }
  211 
  212     ret = EOK;
  213 done:
  214     if (ret == EOK) {
  215         *_id_opts = id_opts;
  216     } else {
  217         talloc_free(id_opts);
  218     }
  219 
  220     return ret;
  221 }
  222 
  223 struct ad_options *
  224 ad_create_options(TALLOC_CTX *mem_ctx,
  225                   struct confdb_ctx *cdb,
  226                   const char *conf_path,
  227                   struct data_provider *dp,
  228                   struct sss_domain_info *subdom)
  229 {
  230     struct ad_options *ad_options;
  231     errno_t ret;
  232 
  233     ad_options = talloc_zero(mem_ctx, struct ad_options);
  234     if (ad_options == NULL) return NULL;
  235 
  236     if (cdb != NULL && conf_path != NULL) {
  237         ret = dp_get_options(ad_options,
  238                              cdb,
  239                              conf_path,
  240                              ad_basic_opts,
  241                              AD_OPTS_BASIC,
  242                              &ad_options->basic);
  243     } else {
  244         /* Fallback to reading the defaults only if no confdb
  245          * is available */
  246         ret = dp_copy_defaults(ad_options,
  247                                ad_basic_opts,
  248                                AD_OPTS_BASIC,
  249                                &ad_options->basic);
  250     }
  251     if (ret != EOK) {
  252         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get basic AD options\n");
  253         talloc_free(ad_options);
  254         return NULL;
  255     }
  256 
  257     ret = ad_create_sdap_options(ad_options,
  258                                  cdb,
  259                                  conf_path,
  260                                  dp,
  261                                  &ad_options->id);
  262     if (ret != EOK) {
  263         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD LDAP options\n");
  264         talloc_free(ad_options);
  265         return NULL;
  266     }
  267 
  268     return ad_options;
  269 }
  270 
  271 static errno_t
  272 set_common_ad_trust_opts(struct ad_options *ad_options,
  273                          const char *realm,
  274                          const char *ad_domain,
  275                          const char *hostname,
  276                          const char *keytab)
  277 {
  278     errno_t ret;
  279 
  280     ret = dp_opt_set_string(ad_options->basic, AD_KRB5_REALM, realm);
  281     if (ret != EOK) {
  282         DEBUG(SSSDBG_OP_FAILURE, "Cannot set AD krb5 realm\n");
  283         return ret;
  284     }
  285 
  286     ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, ad_domain);
  287     if (ret != EOK) {
  288         DEBUG(SSSDBG_OP_FAILURE, "Cannot set AD domain\n");
  289         return ret;
  290     }
  291 
  292     ret = dp_opt_set_string(ad_options->basic, AD_HOSTNAME, hostname);
  293     if (ret != EOK) {
  294         DEBUG(SSSDBG_OP_FAILURE, "Cannot set AD hostname\n");
  295         return ret;
  296     }
  297 
  298     if (keytab != NULL) {
  299         ret = dp_opt_set_string(ad_options->basic, AD_KEYTAB, keytab);
  300         if (ret != EOK) {
  301             DEBUG(SSSDBG_OP_FAILURE, "Cannot set keytab\n");
  302             return ret;
  303         }
  304     }
  305 
  306     return EOK;
  307 }
  308 
  309 struct ad_options *
  310 ad_create_2way_trust_options(TALLOC_CTX *mem_ctx,
  311                              struct confdb_ctx *cdb,
  312                              const char *conf_path,
  313                              struct data_provider *dp,
  314                              const char *realm,
  315                              struct sss_domain_info *subdom,
  316                              const char *hostname,
  317                              const char *keytab)
  318 {
  319     struct ad_options *ad_options;
  320     errno_t ret;
  321 
  322     DEBUG(SSSDBG_TRACE_FUNC, "2way trust is defined to domain '%s'\n",
  323           subdom->name);
  324 
  325     ad_options = ad_create_options(mem_ctx, cdb, conf_path, dp, subdom);
  326     if (ad_options == NULL) {
  327         DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n");
  328         return NULL;
  329     }
  330 
  331     ret = set_common_ad_trust_opts(ad_options, realm, subdom->name, hostname,
  332                                    keytab);
  333     if (ret != EOK) {
  334         DEBUG(SSSDBG_CRIT_FAILURE, "set_common_ad_trust_opts failed\n");
  335         talloc_free(ad_options);
  336         return NULL;
  337     }
  338 
  339     ret = ad_set_sdap_options(ad_options, ad_options->id);
  340     if (ret != EOK) {
  341         DEBUG(SSSDBG_CRIT_FAILURE, "ad_set_sdap_options failed");
  342         talloc_free(ad_options);
  343         return NULL;
  344     }
  345 
  346     return ad_options;
  347 }
  348 
  349 struct ad_options *
  350 ad_create_1way_trust_options(TALLOC_CTX *mem_ctx,
  351                              struct confdb_ctx *cdb,
  352                              const char *subdom_conf_path,
  353                              struct data_provider *dp,
  354                              struct sss_domain_info *subdom,
  355                              const char *hostname,
  356                              const char *keytab,
  357                              const char *sasl_authid)
  358 {
  359     struct ad_options *ad_options;
  360     const char *realm;
  361     errno_t ret;
  362 
  363     DEBUG(SSSDBG_TRACE_FUNC, "1way trust is defined to domain '%s'\n",
  364           subdom->name);
  365 
  366     ad_options = ad_create_options(mem_ctx, cdb, subdom_conf_path, dp, subdom);
  367     if (ad_options == NULL) {
  368         DEBUG(SSSDBG_CRIT_FAILURE, "ad_create_options failed\n");
  369         return NULL;
  370     }
  371 
  372     realm = get_uppercase_realm(ad_options, subdom->name);
  373     if (!realm) {
  374         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get uppercase realm\n");
  375         talloc_free(ad_options);
  376         return NULL;
  377     }
  378 
  379     ret = set_common_ad_trust_opts(ad_options, realm,
  380                                    subdom->name, hostname, keytab);
  381     if (ret != EOK) {
  382         DEBUG(SSSDBG_CRIT_FAILURE,
  383               "set_common_ad_trust_opts failed [%d]: %s\n",
  384               ret, sss_strerror(ret));
  385         talloc_free(ad_options);
  386         return NULL;
  387     }
  388 
  389     /* Set SDAP_SASL_AUTHID to the trust principal */
  390     ret = dp_opt_set_string(ad_options->id->basic,
  391                             SDAP_SASL_AUTHID, sasl_authid);
  392     if (ret != EOK) {
  393         DEBUG(SSSDBG_OP_FAILURE, "Cannot set SASL authid\n");
  394         talloc_free(ad_options);
  395         return NULL;
  396     }
  397 
  398     ret = ad_set_sdap_options(ad_options, ad_options->id);
  399     if (ret != EOK) {
  400         DEBUG(SSSDBG_CRIT_FAILURE, "ad_set_sdap_options failed [%d]: %s\n",
  401               ret, sss_strerror(ret));
  402         talloc_free(ad_options);
  403         return NULL;
  404     }
  405 
  406     return ad_options;
  407 }
  408 
  409 errno_t
  410 ad_get_common_options(TALLOC_CTX *mem_ctx,
  411                       struct confdb_ctx *cdb,
  412                       const char *conf_path,
  413                       struct sss_domain_info *dom,
  414                       struct ad_options **_opts)
  415 {
  416     errno_t ret;
  417     int gret;
  418     struct ad_options *opts = NULL;
  419     char *domain;
  420     char *server;
  421     char *realm;
  422     char *ad_hostname;
  423     char hostname[HOST_NAME_MAX + 1];
  424     char *case_sensitive_opt;
  425     const char *opt_override;
  426 
  427     opts = talloc_zero(mem_ctx, struct ad_options);
  428     if (!opts) return ENOMEM;
  429 
  430     ret = dp_get_options(opts, cdb, conf_path,
  431                          ad_basic_opts,
  432                          AD_OPTS_BASIC,
  433                          &opts->basic);
  434     if (ret != EOK) {
  435         goto done;
  436     }
  437 
  438     /* If the AD domain name wasn't explicitly set, assume that it
  439      * matches the SSSD domain name
  440      */
  441     domain = dp_opt_get_string(opts->basic, AD_DOMAIN);
  442     if (!domain) {
  443         ret = dp_opt_set_string(opts->basic, AD_DOMAIN, dom->name);
  444         if (ret != EOK) {
  445             goto done;
  446         }
  447         domain = dom->name;
  448     }
  449 
  450     /* Did we get an explicit server name, or are we discovering it? */
  451     server = dp_opt_get_string(opts->basic, AD_SERVER);
  452     if (!server) {
  453         DEBUG(SSSDBG_CONF_SETTINGS,
  454               "No AD server set, will use service discovery!\n");
  455     }
  456 
  457     /* Set the machine's hostname to the local host name if it
  458      * wasn't explicitly specified.
  459      */
  460     ad_hostname = dp_opt_get_string(opts->basic, AD_HOSTNAME);
  461     if (ad_hostname == NULL) {
  462         gret = gethostname(hostname, sizeof(hostname));
  463         if (gret != 0) {
  464             ret = errno;
  465             DEBUG(SSSDBG_FATAL_FAILURE,
  466                   "gethostname failed [%s].\n",
  467                    strerror(ret));
  468             goto done;
  469         }
  470         hostname[HOST_NAME_MAX] = '\0';
  471         DEBUG(SSSDBG_CONF_SETTINGS,
  472               "Setting ad_hostname to [%s].\n", hostname);
  473         ret = dp_opt_set_string(opts->basic, AD_HOSTNAME, hostname);
  474         if (ret != EOK) {
  475             DEBUG(SSSDBG_FATAL_FAILURE,
  476                   "Setting ad_hostname failed [%s].\n",
  477                    strerror(ret));
  478             goto done;
  479         }
  480     }
  481 
  482 
  483     /* Always use the upper-case AD domain for the kerberos realm */
  484     realm = get_uppercase_realm(opts, domain);
  485     if (!realm) {
  486         ret = ENOMEM;
  487         goto done;
  488     }
  489 
  490     ret = dp_opt_set_string(opts->basic, AD_KRB5_REALM, realm);
  491     if (ret != EOK) {
  492         goto done;
  493     }
  494 
  495     /* Active Directory is always case-insensitive */
  496     ret = confdb_get_string(cdb, mem_ctx, conf_path,
  497                             CONFDB_DOMAIN_CASE_SENSITIVE, "false",
  498                             &case_sensitive_opt);
  499     if (ret != EOK) {
  500         DEBUG(SSSDBG_CRIT_FAILURE, "condb_get_string failed.\n");
  501         goto done;
  502     }
  503 
  504     if (strcasecmp(case_sensitive_opt, "true") == 0) {
  505         DEBUG(SSSDBG_CRIT_FAILURE,
  506               "Warning: AD domain can not be set as case-sensitive.\n");
  507         dom->case_sensitive = false;
  508         dom->case_preserve = false;
  509     } else if (strcasecmp(case_sensitive_opt, "false") == 0) {
  510         dom->case_sensitive = false;
  511         dom->case_preserve = false;
  512     } else if (strcasecmp(case_sensitive_opt, "preserving") == 0) {
  513         dom->case_sensitive = false;
  514         dom->case_preserve = true;
  515     } else {
  516         DEBUG(SSSDBG_FATAL_FAILURE,
  517               "Invalid value for %s\n", CONFDB_DOMAIN_CASE_SENSITIVE);
  518         goto done;
  519     }
  520 
  521     opt_override = dom->case_preserve ? "preserving" : "false";
  522 
  523     /* Set this in the confdb so that the responders pick it
  524      * up when they start up.
  525      */
  526     ret = confdb_set_string(cdb, conf_path, "case_sensitive", opt_override);
  527     if (ret != EOK) {
  528         DEBUG(SSSDBG_CRIT_FAILURE,
  529               "Could not set domain option case_sensitive: [%s]\n",
  530                strerror(ret));
  531         goto done;
  532     }
  533 
  534     DEBUG(SSSDBG_CONF_SETTINGS,
  535           "Setting domain option case_sensitive to [%s]\n", opt_override);
  536 
  537     ret = EOK;
  538     *_opts = opts;
  539 
  540 done:
  541     if (ret != EOK) {
  542         talloc_zfree(opts);
  543     }
  544     return ret;
  545 }
  546 
  547 static void
  548 ad_resolve_callback(void *private_data, struct fo_server *server);
  549 
  550 static errno_t
  551 _ad_servers_init(struct ad_service *service,
  552                  struct be_ctx *bectx,
  553                  const char *fo_service,
  554                  const char *fo_gc_service,
  555                  const char *servers,
  556                  const char *ad_domain,
  557                  bool primary)
  558 {
  559     size_t i;
  560     size_t j;
  561     errno_t ret = 0;
  562     char **list;
  563     struct ad_server_data *sdata;
  564     TALLOC_CTX *tmp_ctx;
  565 
  566     tmp_ctx = talloc_new(NULL);
  567     if (!tmp_ctx) return ENOMEM;
  568 
  569     /* Split the server list */
  570     ret = split_on_separator(tmp_ctx, servers, ',', true, true, &list, NULL);
  571     if (ret != EOK) {
  572         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n");
  573         goto done;
  574     }
  575 
  576     for (j = 0; list[j]; j++) {
  577         if (resolv_is_address(list[j])) {
  578             DEBUG(SSSDBG_IMPORTANT_INFO,
  579                   "ad_server [%s] is detected as IP address, "
  580                   "this can cause GSSAPI/GSS-SPNEGO problems\n", list[j]);
  581         }
  582     }
  583 
  584     /* Add each of these servers to the failover service */
  585     for (i = 0; list[i]; i++) {
  586         if (be_fo_is_srv_identifier(list[i])) {
  587             if (!primary) {
  588                 DEBUG(SSSDBG_MINOR_FAILURE,
  589                       "Failed to add server [%s] to failover service: "
  590                        "SRV resolution only allowed for primary servers!\n",
  591                        list[i]);
  592                 continue;
  593             }
  594 
  595             sdata = talloc(service, struct ad_server_data);
  596             if (sdata == NULL) {
  597                 ret = ENOMEM;
  598                 goto done;
  599             }
  600             sdata->gc = true;
  601 
  602             ret = be_fo_add_srv_server(bectx, fo_gc_service, "gc",
  603                                        ad_domain, BE_FO_PROTO_TCP,
  604                                        false, sdata);
  605             if (ret != EOK) {
  606                 DEBUG(SSSDBG_FATAL_FAILURE,
  607                       "Failed to add service discovery to failover: [%s]\n",
  608                       strerror(ret));
  609                 goto done;
  610             }
  611 
  612             sdata = talloc(service, struct ad_server_data);
  613             if (sdata == NULL) {
  614                 ret = ENOMEM;
  615                 goto done;
  616             }
  617             sdata->gc = false;
  618 
  619             ret = be_fo_add_srv_server(bectx, fo_service, "ldap",
  620                                        ad_domain, BE_FO_PROTO_TCP,
  621                                        false, sdata);
  622             if (ret != EOK) {
  623                 DEBUG(SSSDBG_FATAL_FAILURE,
  624                       "Failed to add service discovery to failover: [%s]\n",
  625                       strerror(ret));
  626                 goto done;
  627             }
  628 
  629             DEBUG(SSSDBG_CONF_SETTINGS, "Added service discovery for AD\n");
  630             continue;
  631         }
  632 
  633         /* It could be ipv6 address in square brackets. Remove
  634          * the brackets if needed. */
  635         ret = remove_ipv6_brackets(list[i]);
  636         if (ret != EOK) {
  637             goto done;
  638         }
  639 
  640         sdata = talloc(service, struct ad_server_data);
  641         if (sdata == NULL) {
  642             ret = ENOMEM;
  643             goto done;
  644         }
  645         sdata->gc = true;
  646 
  647         ret = be_fo_add_server(bectx, fo_gc_service, list[i], 0, sdata, primary);
  648         if (ret && ret != EEXIST) {
  649             DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n");
  650             goto done;
  651         }
  652 
  653         sdata = talloc(service, struct ad_server_data);
  654         if (sdata == NULL) {
  655             ret = ENOMEM;
  656             goto done;
  657         }
  658         sdata->gc = false;
  659 
  660         ret = be_fo_add_server(bectx, fo_service, list[i], 0, sdata, primary);
  661         if (ret && ret != EEXIST) {
  662             DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n");
  663             goto done;
  664         }
  665 
  666         DEBUG(SSSDBG_CONF_SETTINGS, "Added failover server %s\n", list[i]);
  667     }
  668 done:
  669     talloc_free(tmp_ctx);
  670     return ret;
  671 }
  672 
  673 static inline errno_t
  674 ad_primary_servers_init(struct ad_service *service,
  675                         struct be_ctx *bectx, const char *servers,
  676                         const char *fo_service, const char *fo_gc_service,
  677                         const char *ad_domain)
  678 {
  679     return _ad_servers_init(service, bectx, fo_service,
  680                             fo_gc_service, servers, ad_domain, true);
  681 }
  682 
  683 static inline errno_t
  684 ad_backup_servers_init(struct ad_service *service,
  685                         struct be_ctx *bectx, const char *servers,
  686                         const char *fo_service, const char *fo_gc_service,
  687                         const char *ad_domain)
  688 {
  689     return _ad_servers_init(service, bectx, fo_service,
  690                             fo_gc_service, servers, ad_domain, false);
  691 }
  692 
  693 static int ad_user_data_cmp(void *ud1, void *ud2)
  694 {
  695     struct ad_server_data *sd1, *sd2;
  696 
  697     sd1 = talloc_get_type(ud1, struct ad_server_data);
  698     sd2 = talloc_get_type(ud2, struct ad_server_data);
  699     if (sd1 == NULL || sd2 == NULL) {
  700         DEBUG(SSSDBG_TRACE_FUNC, "No user data\n");
  701         return sd1 == sd2 ? 0 : 1;
  702     }
  703 
  704     if (sd1->gc == sd2->gc) {
  705         return 0;
  706     }
  707 
  708     return 1;
  709 }
  710 
  711 static void ad_online_cb(void *pvt)
  712 {
  713     struct ad_service *service = talloc_get_type(pvt, struct ad_service);
  714 
  715     if (service == NULL) {
  716         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid private pointer\n");
  717         return;
  718     }
  719 
  720     DEBUG(SSSDBG_TRACE_FUNC, "The AD provider is online\n");
  721 }
  722 
  723 errno_t
  724 ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
  725                  const char *primary_servers,
  726                  const char *backup_servers,
  727                  const char *krb5_realm,
  728                  const char *ad_service,
  729                  const char *ad_gc_service,
  730                  const char *ad_domain,
  731                  bool use_kdcinfo,
  732                  size_t n_lookahead_primary,
  733                  size_t n_lookahead_backup,
  734                  struct ad_service **_service)
  735 {
  736     errno_t ret;
  737     TALLOC_CTX *tmp_ctx;
  738     struct ad_service *service;
  739 
  740     tmp_ctx = talloc_new(mem_ctx);
  741     if (!tmp_ctx) return ENOMEM;
  742 
  743     service = talloc_zero(tmp_ctx, struct ad_service);
  744     if (!service) {
  745         ret = ENOMEM;
  746         goto done;
  747     }
  748 
  749     service->sdap = talloc_zero(service, struct sdap_service);
  750     service->gc = talloc_zero(service, struct sdap_service);
  751     if (!service->sdap || !service->gc) {
  752         ret = ENOMEM;
  753         goto done;
  754     }
  755 
  756     service->sdap->name = talloc_strdup(service->sdap, ad_service);
  757     service->gc->name = talloc_strdup(service->gc, ad_gc_service);
  758     if (!service->sdap->name || !service->gc->name) {
  759         ret = ENOMEM;
  760         goto done;
  761     }
  762 
  763     service->krb5_service = krb5_service_new(service, bectx,
  764                                              ad_service, krb5_realm,
  765                                              use_kdcinfo,
  766                                              n_lookahead_primary,
  767                                              n_lookahead_backup);
  768     if (!service->krb5_service) {
  769         ret = ENOMEM;
  770         goto done;
  771     }
  772 
  773     ret = be_fo_add_service(bectx, ad_service, ad_user_data_cmp);
  774     if (ret != EOK) {
  775         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
  776         goto done;
  777     }
  778 
  779     ret = be_fo_add_service(bectx, ad_gc_service, ad_user_data_cmp);
  780     if (ret != EOK) {
  781         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create GC failover service!\n");
  782         goto done;
  783     }
  784 
  785     service->sdap->kinit_service_name = service->krb5_service->name;
  786     service->gc->kinit_service_name = service->krb5_service->name;
  787 
  788     if (!krb5_realm) {
  789         DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm set\n");
  790         ret = EINVAL;
  791         goto done;
  792     }
  793 
  794     if (!primary_servers) {
  795         DEBUG(SSSDBG_CONF_SETTINGS,
  796               "No primary servers defined, using service discovery\n");
  797         primary_servers = BE_SRV_IDENTIFIER;
  798     }
  799 
  800     ret = ad_primary_servers_init(service, bectx,
  801                                   primary_servers, ad_service,
  802                                   ad_gc_service, ad_domain);
  803     if (ret != EOK) {
  804         goto done;
  805     }
  806 
  807     if (backup_servers) {
  808         ret = ad_backup_servers_init(service, bectx,
  809                                      backup_servers, ad_service,
  810                                      ad_gc_service, ad_domain);
  811         if (ret != EOK) {
  812             goto done;
  813         }
  814     }
  815 
  816     ret = be_add_online_cb(bectx, bectx, ad_online_cb, service, NULL);
  817     if (ret != EOK) {
  818         DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up AD online callback\n");
  819         goto done;
  820     }
  821 
  822     ret = be_fo_service_add_callback(mem_ctx, bectx, ad_service,
  823                                      ad_resolve_callback, service);
  824     if (ret != EOK) {
  825         DEBUG(SSSDBG_FATAL_FAILURE,
  826               "Failed to add failover callback! [%s]\n", strerror(ret));
  827         goto done;
  828     }
  829 
  830     ret = be_fo_service_add_callback(mem_ctx, bectx, ad_gc_service,
  831                                      ad_resolve_callback, service);
  832     if (ret != EOK) {
  833         DEBUG(SSSDBG_FATAL_FAILURE,
  834               "Failed to add failover callback! [%s]\n", strerror(ret));
  835         goto done;
  836     }
  837 
  838     *_service = talloc_steal(mem_ctx, service);
  839 
  840     ret = EOK;
  841 
  842 done:
  843     talloc_free(tmp_ctx);
  844     return ret;
  845 }
  846 
  847 void
  848 ad_failover_reset(struct be_ctx *bectx,
  849                   struct ad_service *adsvc)
  850 {
  851     if (adsvc == NULL) {
  852         DEBUG(SSSDBG_CRIT_FAILURE, "NULL service\n");
  853         return;
  854     }
  855 
  856     sdap_service_reset_fo(bectx, adsvc->sdap);
  857     sdap_service_reset_fo(bectx, adsvc->gc);
  858 }
  859 
  860 static bool
  861 ad_krb5info_file_filter(struct fo_server *server)
  862 {
  863     struct ad_server_data *sdata = NULL;
  864     if (server == NULL) return true;
  865 
  866     sdata = fo_get_server_user_data(server);
  867     if (sdata && sdata->gc) {
  868         /* Only write kdcinfo files for local servers */
  869         return true;
  870     }
  871     return false;
  872 }
  873 
  874 static void
  875 ad_resolve_callback(void *private_data, struct fo_server *server)
  876 {
  877     errno_t ret;
  878     TALLOC_CTX *tmp_ctx;
  879     struct ad_service *service;
  880     struct resolv_hostent *srvaddr;
  881     struct sockaddr_storage *sockaddr;
  882     char *address;
  883     char *new_uri;
  884     int new_port;
  885     const char *srv_name;
  886     struct ad_server_data *sdata = NULL;
  887 
  888     tmp_ctx = talloc_new(NULL);
  889     if (!tmp_ctx) {
  890         DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
  891         return;
  892     }
  893 
  894     sdata = fo_get_server_user_data(server);
  895     if (fo_is_srv_lookup(server) == false && sdata == NULL) {
  896         DEBUG(SSSDBG_CRIT_FAILURE, "No user data?\n");
  897         ret = EINVAL;
  898         goto done;
  899     }
  900 
  901     service = talloc_get_type(private_data, struct ad_service);
  902     if (!service) {
  903         ret = EINVAL;
  904         goto done;
  905     }
  906 
  907     srvaddr = fo_get_server_hostent(server);
  908     if (!srvaddr) {
  909         DEBUG(SSSDBG_CRIT_FAILURE,
  910               "No hostent available for server (%s)\n",
  911                fo_get_server_str_name(server));
  912         ret = EINVAL;
  913         goto done;
  914     }
  915 
  916     address = resolv_get_string_address(tmp_ctx, srvaddr);
  917     if (address == NULL) {
  918         DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_string_address failed.\n");
  919         ret = EIO;
  920         goto done;
  921     }
  922 
  923     srv_name = fo_get_server_name(server);
  924     if (srv_name == NULL) {
  925         DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n");
  926         ret = EINVAL;
  927         goto done;
  928     }
  929 
  930     new_uri = talloc_asprintf(service->sdap, "ldap://%s", srv_name);
  931     if (!new_uri) {
  932         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy URI\n");
  933         ret = ENOMEM;
  934         goto done;
  935     }
  936     DEBUG(SSSDBG_CONF_SETTINGS, "Constructed uri '%s'\n", new_uri);
  937 
  938     sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT);
  939     if (sockaddr == NULL) {
  940         DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n");
  941         ret = EIO;
  942         goto done;
  943     }
  944 
  945     /* free old one and replace with new one */
  946     talloc_zfree(service->sdap->uri);
  947     service->sdap->uri = new_uri;
  948     talloc_zfree(service->sdap->sockaddr);
  949     service->sdap->sockaddr = talloc_steal(service->sdap, sockaddr);
  950 
  951     talloc_zfree(service->gc->uri);
  952     talloc_zfree(service->gc->sockaddr);
  953     if (sdata && sdata->gc) {
  954         new_port = fo_get_server_port(server);
  955         new_port = (new_port == 0) ? AD_GC_PORT : new_port;
  956 
  957         service->gc->uri = talloc_asprintf(service->gc, "%s:%d",
  958                                            new_uri, new_port);
  959 
  960         service->gc->sockaddr = resolv_get_sockaddr_address(service->gc,
  961                                                             srvaddr,
  962                                                             new_port);
  963     } else {
  964         /* Make sure there always is an URI even if we know that this
  965          * server doesn't support GC. That way the lookup would go through
  966          * just not return anything
  967          */
  968         service->gc->uri = talloc_strdup(service->gc, service->sdap->uri);
  969         service->gc->sockaddr = talloc_memdup(service->gc, service->sdap->sockaddr,
  970                                               sizeof(struct sockaddr_storage));
  971     }
  972 
  973     if (!service->gc->uri) {
  974         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to append to URI\n");
  975         ret = ENOMEM;
  976         goto done;
  977     }
  978     DEBUG(SSSDBG_CONF_SETTINGS, "Constructed GC uri '%s'\n", service->gc->uri);
  979 
  980     if (service->gc->sockaddr == NULL) {
  981         DEBUG(SSSDBG_CRIT_FAILURE,
  982                 "resolv_get_sockaddr_address failed.\n");
  983         ret = EIO;
  984         goto done;
  985     }
  986 
  987     if (service->krb5_service->write_kdcinfo) {
  988         ret = write_krb5info_file_from_fo_server(service->krb5_service,
  989                                                  server,
  990                                                  SSS_KRB5KDC_FO_SRV,
  991                                                  ad_krb5info_file_filter);
  992         if (ret != EOK) {
  993             DEBUG(SSSDBG_MINOR_FAILURE,
  994                   "write_krb5info_file failed, authentication might fail.\n");
  995         }
  996     }
  997 
  998     ret = EOK;
  999 done:
 1000     if (ret != EOK) {
 1001         DEBUG(SSSDBG_CRIT_FAILURE,
 1002               "Error: [%s]\n", strerror(ret));
 1003     }
 1004     talloc_free(tmp_ctx);
 1005     return;
 1006 }
 1007 
 1008 static errno_t
 1009 ad_set_sdap_options(struct ad_options *ad_opts,
 1010                     struct sdap_options *id_opts)
 1011 {
 1012     errno_t ret;
 1013     char *krb5_realm;
 1014     char *keytab_path;
 1015     const char *schema;
 1016 
 1017     /* We only support Kerberos password policy with AD, so
 1018      * force that on.
 1019      */
 1020     ret = dp_opt_set_string(id_opts->basic,
 1021                             SDAP_PWD_POLICY,
 1022                             PWD_POL_OPT_MIT);
 1023     if (ret != EOK) {
 1024         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set password policy\n");
 1025         goto done;
 1026     }
 1027 
 1028     /* Set the Kerberos Realm for GSSAPI or GSS-SPNEGO */
 1029     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
 1030     if (!krb5_realm) {
 1031         /* Should be impossible, this is set in ad_get_common_options() */
 1032         DEBUG(SSSDBG_FATAL_FAILURE, "No Kerberos realm\n");
 1033         ret = EINVAL;
 1034         goto done;
 1035     }
 1036 
 1037     ret = dp_opt_set_string(id_opts->basic, SDAP_KRB5_REALM, krb5_realm);
 1038     if (ret != EOK) goto done;
 1039     DEBUG(SSSDBG_CONF_SETTINGS,
 1040           "Option %s set to %s\n",
 1041            id_opts->basic[SDAP_KRB5_REALM].opt_name,
 1042            krb5_realm);
 1043 
 1044     keytab_path = dp_opt_get_string(ad_opts->basic, AD_KEYTAB);
 1045     if (keytab_path) {
 1046         ret = dp_opt_set_string(id_opts->basic, SDAP_KRB5_KEYTAB,
 1047                                 keytab_path);
 1048         if (ret != EOK) goto done;
 1049         DEBUG(SSSDBG_CONF_SETTINGS,
 1050               "Option %s set to %s\n",
 1051                id_opts->basic[SDAP_KRB5_KEYTAB].opt_name,
 1052                keytab_path);
 1053     }
 1054 
 1055     ret = sdap_set_sasl_options(id_opts,
 1056                                 dp_opt_get_string(ad_opts->basic,
 1057                                                   AD_HOSTNAME),
 1058                                 dp_opt_get_string(ad_opts->basic,
 1059                                                   AD_KRB5_REALM),
 1060                                 keytab_path);
 1061     if (ret != EOK) {
 1062         DEBUG(SSSDBG_OP_FAILURE, "Cannot set the SASL-related options\n");
 1063         goto done;
 1064     }
 1065 
 1066     /* Warn if the user is doing something silly like overriding the schema
 1067      * with the AD provider
 1068      */
 1069     schema = dp_opt_get_string(id_opts->basic, SDAP_SCHEMA);
 1070     if (schema != NULL && strcasecmp(schema, "ad") != 0) {
 1071         DEBUG(SSSDBG_IMPORTANT_INFO,
 1072               "The AD provider only supports the AD LDAP schema. "
 1073               "SSSD will ignore the ldap_schema option value and proceed "
 1074               "with ldap_schema=ad\n");
 1075     }
 1076 
 1077     /* fix schema to AD  */
 1078     id_opts->schema_type = SDAP_SCHEMA_AD;
 1079 
 1080     ad_opts->id = id_opts;
 1081     ret = EOK;
 1082 done:
 1083     return ret;
 1084 }
 1085 
 1086 errno_t
 1087 ad_get_id_options(struct ad_options *ad_opts,
 1088                   struct confdb_ctx *cdb,
 1089                   const char *conf_path,
 1090                   struct data_provider *dp,
 1091                   struct sdap_options **_opts)
 1092 {
 1093     struct sdap_options *id_opts;
 1094     errno_t ret;
 1095 
 1096     ret = ad_create_sdap_options(ad_opts, cdb, conf_path, dp, &id_opts);
 1097     if (ret != EOK) {
 1098         return ENOMEM;
 1099     }
 1100 
 1101     ret = ad_set_sdap_options(ad_opts, id_opts);
 1102     if (ret != EOK) {
 1103         talloc_free(id_opts);
 1104         return ret;
 1105     }
 1106 
 1107     ret = sdap_domain_add(id_opts,
 1108                           ad_opts->id_ctx->sdap_id_ctx->be->domain,
 1109                           NULL);
 1110     if (ret != EOK) {
 1111         talloc_free(id_opts);
 1112         return ret;
 1113     }
 1114 
 1115     /* Set up search bases if they were assigned explicitly */
 1116     ret = ad_set_search_bases(id_opts, NULL);
 1117     if (ret != EOK) {
 1118         talloc_free(id_opts);
 1119         return ret;
 1120     }
 1121 
 1122     *_opts = id_opts;
 1123     return EOK;
 1124 }
 1125 
 1126 errno_t
 1127 ad_get_autofs_options(struct ad_options *ad_opts,
 1128                       struct confdb_ctx *cdb,
 1129                       const char *conf_path)
 1130 {
 1131     errno_t ret;
 1132 
 1133     /* autofs maps */
 1134     ret = sdap_get_map(ad_opts->id,
 1135                        cdb,
 1136                        conf_path,
 1137                        ad_autofs_mobject_map,
 1138                        SDAP_OPTS_AUTOFS_MAP,
 1139                        &ad_opts->id->autofs_mobject_map);
 1140     if (ret != EOK) {
 1141         return ret;
 1142     }
 1143 
 1144     ret = sdap_get_map(ad_opts->id,
 1145                        cdb,
 1146                        conf_path,
 1147                        ad_autofs_entry_map,
 1148                        SDAP_OPTS_AUTOFS_ENTRY,
 1149                        &ad_opts->id->autofs_entry_map);
 1150     if (ret != EOK) {
 1151         return ret;
 1152     }
 1153 
 1154     return EOK;
 1155 }
 1156 
 1157 errno_t
 1158 ad_set_search_bases(struct sdap_options *id_opts,
 1159                     struct sdap_domain *sdom)
 1160 {
 1161     errno_t ret;
 1162     char *default_search_base = NULL;
 1163     size_t o;
 1164     struct sdap_domain *sdap_dom;
 1165     bool has_default;
 1166     const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
 1167                                         SDAP_GROUP_SEARCH_BASE,
 1168                                         SDAP_NETGROUP_SEARCH_BASE,
 1169                                         SDAP_SERVICE_SEARCH_BASE,
 1170                                         -1 };
 1171 
 1172     /* AD servers provide defaultNamingContext, so we will
 1173      * rely on that to specify the search base unless it has
 1174      * been specifically overridden.
 1175      */
 1176 
 1177     if (sdom != NULL) {
 1178         sdap_dom = sdom;
 1179     } else {
 1180         /* If no specific sdom was given, use the first in the list. */
 1181         sdap_dom = id_opts->sdom;
 1182     }
 1183 
 1184     has_default = sdap_dom->search_bases != NULL;
 1185 
 1186     if (has_default == false) {
 1187         default_search_base =
 1188                 dp_opt_get_string(id_opts->basic, SDAP_SEARCH_BASE);
 1189     }
 1190 
 1191     if (default_search_base && has_default == false) {
 1192         /* set search bases if they are not */
 1193         for (o = 0; search_base_options[o] != -1; o++) {
 1194             if (NULL == dp_opt_get_string(id_opts->basic,
 1195                                           search_base_options[o])) {
 1196                 ret = dp_opt_set_string(id_opts->basic,
 1197                                         search_base_options[o],
 1198                                         default_search_base);
 1199                 if (ret != EOK) {
 1200                     goto done;
 1201                 }
 1202                 DEBUG(SSSDBG_CONF_SETTINGS,
 1203                       "Option %s set to %s\n",
 1204                        id_opts->basic[search_base_options[o]].opt_name,
 1205                        dp_opt_get_string(id_opts->basic,
 1206                                          search_base_options[o]));
 1207             }
 1208         }
 1209     } else {
 1210         DEBUG(SSSDBG_CONF_SETTINGS,
 1211               "Search base not set. SSSD will attempt to discover it later, "
 1212                "when connecting to the LDAP server.\n");
 1213     }
 1214 
 1215     /* Default search */
 1216     ret = sdap_parse_search_base(id_opts, id_opts->basic,
 1217                                  SDAP_SEARCH_BASE,
 1218                                  &sdap_dom->search_bases);
 1219     if (ret != EOK && ret != ENOENT) goto done;
 1220 
 1221     /* User search */
 1222     ret = sdap_parse_search_base(id_opts, id_opts->basic,
 1223                                  SDAP_USER_SEARCH_BASE,
 1224                                  &sdap_dom->user_search_bases);
 1225     if (ret != EOK && ret != ENOENT) goto done;
 1226 
 1227     /* Group search base */
 1228     ret = sdap_parse_search_base(id_opts, id_opts->basic,
 1229                                  SDAP_GROUP_SEARCH_BASE,
 1230                                  &sdap_dom->group_search_bases);
 1231     if (ret != EOK && ret != ENOENT) goto done;
 1232 
 1233     /* Netgroup search */
 1234     ret = sdap_parse_search_base(id_opts, id_opts->basic,
 1235                                  SDAP_NETGROUP_SEARCH_BASE,
 1236                                  &sdap_dom->netgroup_search_bases);
 1237     if (ret != EOK && ret != ENOENT) goto done;
 1238 
 1239     /* Service search */
 1240     ret = sdap_parse_search_base(id_opts, id_opts->basic,
 1241                                  SDAP_SERVICE_SEARCH_BASE,
 1242                                  &sdap_dom->service_search_bases);
 1243     if (ret != EOK && ret != ENOENT) goto done;
 1244 
 1245     ret = EOK;
 1246 done:
 1247     return ret;
 1248 }
 1249 
 1250 errno_t
 1251 ad_get_auth_options(TALLOC_CTX *mem_ctx,
 1252                     struct ad_options *ad_opts,
 1253                     struct be_ctx *bectx,
 1254                     struct dp_option **_opts)
 1255 {
 1256     errno_t ret;
 1257     struct dp_option *krb5_options;
 1258     const char *ad_servers;
 1259     const char *krb5_realm;
 1260 
 1261     TALLOC_CTX *tmp_ctx = talloc_new(NULL);
 1262     if (!tmp_ctx) return ENOMEM;
 1263 
 1264     /* Get krb5 options */
 1265     ret = dp_get_options(tmp_ctx, bectx->cdb, bectx->conf_path,
 1266                          ad_def_krb5_opts, KRB5_OPTS,
 1267                          &krb5_options);
 1268     if (ret != EOK) {
 1269         DEBUG(SSSDBG_CRIT_FAILURE,
 1270               "Could not read Kerberos options from the configuration\n");
 1271         goto done;
 1272     }
 1273 
 1274     ad_servers = dp_opt_get_string(ad_opts->basic, AD_SERVER);
 1275 
 1276     /* Force the krb5_servers to match the ad_servers */
 1277     ret = dp_opt_set_string(krb5_options, KRB5_KDC, ad_servers);
 1278     if (ret != EOK) goto done;
 1279     DEBUG(SSSDBG_CONF_SETTINGS,
 1280           "Option %s set to %s\n",
 1281            krb5_options[KRB5_KDC].opt_name,
 1282            ad_servers);
 1283 
 1284     /* Set krb5 realm */
 1285     /* Set the Kerberos Realm for GSSAPI/GSS-SPNEGO */
 1286     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
 1287     if (!krb5_realm) {
 1288         /* Should be impossible, this is set in ad_get_common_options() */
 1289         DEBUG(SSSDBG_FATAL_FAILURE, "No Kerberos realm\n");
 1290         ret = EINVAL;
 1291         goto done;
 1292     }
 1293 
 1294     /* Force the kerberos realm to match the AD_KRB5_REALM (which may have
 1295      * been upper-cased in ad_common_options()
 1296      */
 1297     ret = dp_opt_set_string(krb5_options, KRB5_REALM, krb5_realm);
 1298     if (ret != EOK) goto done;
 1299     DEBUG(SSSDBG_CONF_SETTINGS,
 1300           "Option %s set to %s\n",
 1301            krb5_options[KRB5_REALM].opt_name,
 1302            krb5_realm);
 1303 
 1304     /* Set flag that controls whether we want to write the
 1305      * kdcinfo files at all
 1306      */
 1307     ad_opts->service->krb5_service->write_kdcinfo = \
 1308         dp_opt_get_bool(krb5_options, KRB5_USE_KDCINFO);
 1309     DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
 1310           krb5_options[KRB5_USE_KDCINFO].opt_name,
 1311           ad_opts->service->krb5_service->write_kdcinfo ? "true" : "false");
 1312     sss_krb5_parse_lookahead(
 1313         dp_opt_get_string(krb5_options, KRB5_KDCINFO_LOOKAHEAD),
 1314         &ad_opts->service->krb5_service->lookahead_primary,
 1315         &ad_opts->service->krb5_service->lookahead_backup);
 1316 
 1317     *_opts = talloc_steal(mem_ctx, krb5_options);
 1318 
 1319     ret = EOK;
 1320 
 1321 done:
 1322     talloc_free(tmp_ctx);
 1323     return ret;
 1324 }
 1325 
 1326 errno_t ad_get_dyndns_options(struct be_ctx *be_ctx,
 1327                               struct ad_options *ad_opts)
 1328 {
 1329     errno_t ret;
 1330 
 1331     ret = be_nsupdate_init(ad_opts, be_ctx, ad_dyndns_opts,
 1332                            &ad_opts->dyndns_ctx);
 1333     if (ret != EOK) {
 1334         DEBUG(SSSDBG_OP_FAILURE,
 1335               "Cannot initialize AD dyndns opts [%d]: %s\n",
 1336                ret, sss_strerror(ret));
 1337         return ret;
 1338     }
 1339 
 1340     return EOK;
 1341 }
 1342 
 1343 
 1344 struct ad_id_ctx *
 1345 ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx)
 1346 {
 1347     struct sdap_id_ctx *sdap_ctx;
 1348     struct ad_id_ctx *ad_ctx;
 1349 
 1350     ad_ctx = talloc_zero(ad_opts, struct ad_id_ctx);
 1351     if (ad_ctx == NULL) {
 1352         return NULL;
 1353     }
 1354     ad_ctx->ad_options = ad_opts;
 1355 
 1356     sdap_ctx = sdap_id_ctx_new(ad_ctx, bectx, ad_opts->service->sdap);
 1357     if (sdap_ctx == NULL) {
 1358         talloc_free(ad_ctx);
 1359         return NULL;
 1360     }
 1361     ad_ctx->sdap_id_ctx = sdap_ctx;
 1362     ad_ctx->ldap_ctx = sdap_ctx->conn;
 1363 
 1364     ad_ctx->gc_ctx = sdap_id_ctx_conn_add(sdap_ctx, ad_opts->service->gc);
 1365     if (ad_ctx->gc_ctx == NULL) {
 1366         talloc_free(ad_ctx);
 1367         return NULL;
 1368     }
 1369 
 1370     return ad_ctx;
 1371 }
 1372 
 1373 struct sdap_id_conn_ctx *
 1374 ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom)
 1375 {
 1376     struct sdap_id_conn_ctx *conn;
 1377     struct sdap_domain *sdom;
 1378     struct ad_id_ctx *subdom_id_ctx;
 1379 
 1380     sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom);
 1381     if (sdom == NULL || sdom->pvt == NULL) {
 1382         DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
 1383                                     dom->name);
 1384         return NULL;
 1385     }
 1386     subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
 1387     conn = subdom_id_ctx->ldap_ctx;
 1388 
 1389     if (IS_SUBDOMAIN(sdom->dom) == true && conn != NULL) {
 1390         /* Regardless of connection types, a subdomain error must not be
 1391          * allowed to set the whole back end offline, rather report an error
 1392          * and let the caller deal with it (normally disable the subdomain
 1393          */
 1394         conn->ignore_mark_offline = true;
 1395     }
 1396 
 1397     return conn;
 1398 }
 1399 
 1400 struct sdap_id_conn_ctx **
 1401 ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
 1402                 struct sss_domain_info *dom)
 1403 {
 1404     struct sdap_id_conn_ctx **clist;
 1405     int cindex = 0;
 1406 
 1407     clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3);
 1408     if (clist == NULL) return NULL;
 1409 
 1410     /* Always try GC first */
 1411     if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) {
 1412         clist[cindex] = ad_ctx->gc_ctx;
 1413         clist[cindex]->ignore_mark_offline = true;
 1414         clist[cindex]->no_mpg_user_fallback = true;
 1415         cindex++;
 1416     }
 1417 
 1418     clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
 1419 
 1420     return clist;
 1421 }
 1422 
 1423 struct sdap_id_conn_ctx **
 1424 ad_ldap_conn_list(TALLOC_CTX *mem_ctx,
 1425                   struct ad_id_ctx *ad_ctx,
 1426                   struct sss_domain_info *dom)
 1427 {
 1428     struct sdap_id_conn_ctx **clist;
 1429 
 1430     clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 2);
 1431     if (clist == NULL) {
 1432         return NULL;
 1433     }
 1434 
 1435     clist[0] = ad_get_dom_ldap_conn(ad_ctx, dom);
 1436 
 1437     clist[1] = NULL;
 1438     return clist;
 1439 }
 1440 
 1441 struct sdap_id_conn_ctx **
 1442 ad_user_conn_list(TALLOC_CTX *mem_ctx,
 1443                   struct ad_id_ctx *ad_ctx,
 1444                   struct sss_domain_info *dom)
 1445 {
 1446     struct sdap_id_conn_ctx **clist;
 1447     int cindex = 0;
 1448 
 1449     clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3);
 1450     if (clist == NULL) {
 1451         return NULL;
 1452     }
 1453 
 1454     /* Try GC first for users from trusted domains, but go to LDAP
 1455      * for users from non-trusted domains to get all POSIX attrs
 1456      */
 1457     if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)
 1458             && IS_SUBDOMAIN(dom)) {
 1459         clist[cindex] = ad_ctx->gc_ctx;
 1460         clist[cindex]->ignore_mark_offline = true;
 1461         cindex++;
 1462     }
 1463 
 1464     /* Users from primary domain can be just downloaded from LDAP.
 1465      * The domain's LDAP connection also works as a fallback
 1466      */
 1467     clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
 1468 
 1469     return clist;
 1470 }
 1471 
 1472 errno_t ad_inherit_opts_if_needed(struct dp_option *parent_opts,
 1473                                   struct dp_option *suddom_opts,
 1474                                   struct confdb_ctx *cdb,
 1475                                   const char *subdom_conf_path,
 1476                                   int opt_id)
 1477 {
 1478     int ret;
 1479     const char *parent_val = NULL;
 1480     char *dummy = NULL;
 1481     char *option_list[2] = { NULL, NULL };
 1482 
 1483     parent_val = dp_opt_get_cstring(parent_opts, opt_id);
 1484     if (parent_val != NULL) {
 1485         ret = confdb_get_string(cdb, NULL, subdom_conf_path,
 1486                                 parent_opts[opt_id].opt_name, NULL, &dummy);
 1487         if (ret != EOK) {
 1488             DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed.\n");
 1489             goto done;
 1490         }
 1491 
 1492         if (dummy == NULL) {
 1493             DEBUG(SSSDBG_CONF_SETTINGS,
 1494                   "Option [%s] is set in parent domain but not set for "
 1495                   "sub-domain trying to set it to [%s].\n",
 1496                   parent_opts[opt_id].opt_name, parent_val);
 1497             option_list[0] = discard_const(parent_opts[opt_id].opt_name);
 1498             dp_option_inherit(option_list, opt_id, parent_opts, suddom_opts);
 1499         }
 1500     }
 1501 
 1502     ret = EOK;
 1503 
 1504 done:
 1505     talloc_free(dummy);
 1506 
 1507     return ret;
 1508 }