LCOV - code coverage report
Current view: top level - providers/ldap - ldap_common.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 425 1.6 %
Date: 2016-06-29 Functions: 1 24 4.2 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     LDAP Provider Common Functions
       5             : 
       6             :     Authors:
       7             :         Simo Sorce <ssorce@redhat.com>
       8             : 
       9             :     Copyright (C) 2008-2010 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/ldap_common.h"
      26             : #include "providers/fail_over.h"
      27             : #include "providers/ldap/sdap_async_private.h"
      28             : #include "providers/krb5/krb5_common.h"
      29             : #include "db/sysdb_sudo.h"
      30             : #include "db/sysdb_services.h"
      31             : #include "db/sysdb_autofs.h"
      32             : 
      33             : #include "util/sss_krb5.h"
      34             : #include "util/crypto/sss_crypto.h"
      35             : 
      36             : #include "providers/ldap/sdap_idmap.h"
      37             : 
      38             : /* a fd the child process would log into */
      39             : int ldap_child_debug_fd = -1;
      40             : 
      41           0 : int ldap_id_setup_tasks(struct sdap_id_ctx *ctx)
      42             : {
      43           0 :     return sdap_id_setup_tasks(ctx->be, ctx, ctx->opts->sdom,
      44             :                                ldap_enumeration_send,
      45             :                                ldap_enumeration_recv,
      46             :                                ctx);
      47             : }
      48             : 
      49           0 : int sdap_id_setup_tasks(struct be_ctx *be_ctx,
      50             :                         struct sdap_id_ctx *ctx,
      51             :                         struct sdap_domain *sdom,
      52             :                         be_ptask_send_t send_fn,
      53             :                         be_ptask_recv_t recv_fn,
      54             :                         void *pvt)
      55             : {
      56             :     int ret;
      57             : 
      58             :     /* set up enumeration task */
      59           0 :     if (sdom->dom->enumerate) {
      60           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Setting up enumeration for %s\n",
      61             :                                   sdom->dom->name);
      62           0 :         ret = ldap_setup_enumeration(be_ctx, ctx->opts, sdom,
      63             :                                      send_fn, recv_fn, pvt);
      64             :     } else {
      65             :         /* the enumeration task, runs the cleanup process by itself,
      66             :          * but if enumeration is not running we need to schedule it */
      67           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Setting up cleanup task for %s\n",
      68             :                                   sdom->dom->name);
      69           0 :         ret = ldap_setup_cleanup(ctx, sdom);
      70             :     }
      71             : 
      72           0 :     return ret;
      73             : }
      74             : 
      75           0 : static void sdap_uri_callback(void *private_data, struct fo_server *server)
      76             : {
      77           0 :     TALLOC_CTX *tmp_ctx = NULL;
      78             :     struct sdap_service *service;
      79             :     struct resolv_hostent *srvaddr;
      80             :     struct sockaddr_storage *sockaddr;
      81             :     const char *tmp;
      82             :     const char *srv_name;
      83             :     char *new_uri;
      84             : 
      85           0 :     tmp_ctx = talloc_new(NULL);
      86           0 :     if (tmp_ctx == NULL) {
      87           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
      88           0 :         return;
      89             :     }
      90             : 
      91           0 :     service = talloc_get_type(private_data, struct sdap_service);
      92           0 :     if (!service) {
      93           0 :         talloc_free(tmp_ctx);
      94           0 :         return;
      95             :     }
      96             : 
      97           0 :     tmp = (const char *)fo_get_server_user_data(server);
      98             : 
      99           0 :     srvaddr = fo_get_server_hostent(server);
     100           0 :     if (!srvaddr) {
     101           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     102             :               "FATAL: No hostent available for server (%s)\n",
     103             :                   fo_get_server_str_name(server));
     104           0 :         talloc_free(tmp_ctx);
     105           0 :         return;
     106             :     }
     107             : 
     108           0 :     sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr,
     109             :                                            fo_get_server_port(server));
     110           0 :     if (sockaddr == NULL) {
     111           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n");
     112           0 :         talloc_free(tmp_ctx);
     113           0 :         return;
     114             :     }
     115             : 
     116           0 :     if (fo_is_srv_lookup(server)) {
     117           0 :         if (!tmp) {
     118           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown service, using ldap\n");
     119           0 :             tmp = SSS_LDAP_SRV_NAME;
     120             :         }
     121             : 
     122           0 :         srv_name = fo_get_server_name(server);
     123           0 :         if (srv_name == NULL) {
     124           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n");
     125           0 :             talloc_free(tmp_ctx);
     126           0 :             return;
     127             :         }
     128             : 
     129           0 :         new_uri = talloc_asprintf(service, "%s://%s:%d",
     130             :                                   tmp, srv_name,
     131             :                                   fo_get_server_port(server));
     132             :     } else {
     133           0 :         new_uri = talloc_strdup(service, tmp);
     134             :     }
     135             : 
     136           0 :     if (!new_uri) {
     137           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to copy URI ...\n");
     138           0 :         talloc_free(tmp_ctx);
     139           0 :         return;
     140             :     }
     141             : 
     142           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Constructed uri '%s'\n", new_uri);
     143             : 
     144             :     /* free old one and replace with new one */
     145           0 :     talloc_zfree(service->uri);
     146           0 :     service->uri = new_uri;
     147           0 :     talloc_zfree(service->sockaddr);
     148           0 :     service->sockaddr = talloc_steal(service, sockaddr);
     149           0 :     talloc_free(tmp_ctx);
     150             : }
     151             : 
     152           0 : static void sdap_finalize(struct tevent_context *ev,
     153             :                           struct tevent_signal *se,
     154             :                           int signum,
     155             :                           int count,
     156             :                           void *siginfo,
     157             :                           void *private_data)
     158             : {
     159           0 :     char *realm = (char *) private_data;
     160             :     int ret;
     161             : 
     162           0 :     ret = remove_krb5_info_files(se, realm);
     163           0 :     if (ret != EOK) {
     164           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
     165             :     }
     166             : 
     167           0 :     orderly_shutdown(0);
     168           0 : }
     169             : 
     170           0 : errno_t sdap_install_sigterm_handler(TALLOC_CTX *mem_ctx,
     171             :                                      struct tevent_context *ev,
     172             :                                      const char *realm)
     173             : {
     174             :     char *sig_realm;
     175             :     struct tevent_signal *sige;
     176             : 
     177           0 :     BlockSignals(false, SIGTERM);
     178             : 
     179           0 :     sig_realm = talloc_strdup(mem_ctx, realm);
     180           0 :     if (sig_realm == NULL) {
     181           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
     182           0 :         return ENOMEM;
     183             :     }
     184             : 
     185           0 :     sige = tevent_add_signal(ev, mem_ctx, SIGTERM, SA_SIGINFO, sdap_finalize,
     186             :                              sig_realm);
     187           0 :     if (sige == NULL) {
     188           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n");
     189           0 :         talloc_free(sig_realm);
     190           0 :         return ENOMEM;
     191             :     }
     192           0 :     talloc_steal(sige, sig_realm);
     193             : 
     194           0 :     return EOK;
     195             : }
     196             : 
     197           0 : void sdap_remove_kdcinfo_files_callback(void *pvt)
     198             : {
     199             :     int ret;
     200           0 :     TALLOC_CTX *tmp_ctx = NULL;
     201           0 :     struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
     202             :                                                   struct remove_info_files_ctx);
     203             : 
     204           0 :     ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
     205             :                                               ctx->kdc_service_name);
     206           0 :     if (ret != EOK) {
     207           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     208             :               "be_fo_run_callbacks_at_next_request failed, "
     209             :                   "krb5 info files will not be removed, because "
     210             :                   "it is unclear if they will be recreated properly.\n");
     211           0 :         return;
     212             :     }
     213             : 
     214           0 :     tmp_ctx = talloc_new(NULL);
     215           0 :     if (tmp_ctx == NULL) {
     216           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     217             :               "talloc_new failed, cannot remove krb5 info files.\n");
     218           0 :         return;
     219             :     }
     220             : 
     221           0 :     ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
     222           0 :     if (ret != EOK) {
     223           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
     224             :     }
     225             : 
     226           0 :     talloc_zfree(tmp_ctx);
     227             : }
     228             : 
     229             : 
     230           0 : errno_t sdap_install_offline_callback(TALLOC_CTX *mem_ctx,
     231             :                                       struct be_ctx *be_ctx,
     232             :                                       const char *realm,
     233             :                                       const char *service_name)
     234             : {
     235             :     int ret;
     236             :     struct remove_info_files_ctx *ctx;
     237             : 
     238           0 :     ctx = talloc_zero(mem_ctx, struct remove_info_files_ctx);
     239           0 :     if (ctx == NULL) {
     240           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
     241           0 :         return ENOMEM;
     242             :     }
     243             : 
     244           0 :     ctx->be_ctx = be_ctx;
     245           0 :     ctx->realm = talloc_strdup(ctx, realm);
     246           0 :     ctx->kdc_service_name = talloc_strdup(ctx, service_name);
     247           0 :     if (ctx->realm == NULL || ctx->kdc_service_name == NULL) {
     248           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
     249           0 :         ret = ENOMEM;
     250           0 :         goto done;
     251             :     }
     252             : 
     253           0 :     ret = be_add_offline_cb(ctx, be_ctx,
     254             :                             sdap_remove_kdcinfo_files_callback,
     255             :                             ctx, NULL);
     256           0 :     if (ret != EOK) {
     257           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
     258           0 :         goto done;
     259             :     }
     260             : 
     261           0 :     ret = EOK;
     262             : done:
     263           0 :     if (ret != EOK) {
     264           0 :         talloc_zfree(ctx);
     265             :     }
     266           0 :     return ret;
     267             : }
     268             : 
     269             : errno_t
     270           0 : sdap_set_sasl_options(struct sdap_options *id_opts,
     271             :                       char *default_primary,
     272             :                       char *default_realm,
     273             :                       const char *keytab_path)
     274             : {
     275             :     errno_t ret;
     276             :     TALLOC_CTX *tmp_ctx;
     277             :     char *sasl_primary;
     278             :     char *desired_primary;
     279             :     char *primary_realm;
     280             :     char *sasl_realm;
     281             :     char *desired_realm;
     282           0 :     bool primary_requested = true;
     283           0 :     bool realm_requested = true;
     284             : 
     285           0 :     tmp_ctx = talloc_new(NULL);
     286           0 :     if (!tmp_ctx) return ENOMEM;
     287             : 
     288             :     /* Configuration of SASL auth ID and realm */
     289           0 :     desired_primary = dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID);
     290           0 :     if (!desired_primary) {
     291           0 :         primary_requested = false;
     292           0 :         desired_primary = default_primary;
     293             :     }
     294             : 
     295           0 :     if ((primary_realm = strchr(desired_primary, '@'))) {
     296           0 :         *primary_realm = '\0';
     297           0 :         desired_realm = primary_realm+1;
     298           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
     299             :               "authid contains realm [%s]\n", desired_realm);
     300             :     } else {
     301           0 :         desired_realm = dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM);
     302           0 :         if (!desired_realm) {
     303           0 :             realm_requested = false;
     304           0 :             desired_realm = default_realm;
     305             :         }
     306             :     }
     307             : 
     308           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Will look for %s@%s in %s\n",
     309             :           desired_primary, desired_realm,
     310             :           keytab_path ? keytab_path : "default keytab");
     311             : 
     312           0 :     ret = select_principal_from_keytab(tmp_ctx,
     313             :                                        desired_primary, desired_realm,
     314             :                                        keytab_path,
     315             :                                        NULL, &sasl_primary, &sasl_realm);
     316           0 :     if (ret != EOK) {
     317           0 :         goto done;
     318             :     }
     319             : 
     320           0 :     if (primary_requested && strcmp(desired_primary, sasl_primary) != 0) {
     321           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     322             :                "Configured SASL auth ID not found in keytab. "
     323             :                 "Requested %s, found %s\n", desired_primary, sasl_primary);
     324             :     }
     325             : 
     326           0 :     if (realm_requested && strcmp(desired_realm, sasl_realm) != 0) {
     327           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     328             :                "Configured SASL realm not found in keytab. "
     329             :                 "Requested %s, found %s\n", desired_realm, sasl_realm);
     330             :     }
     331             : 
     332           0 :     ret = dp_opt_set_string(id_opts->basic,
     333             :                             SDAP_SASL_AUTHID, sasl_primary);
     334           0 :     if (ret != EOK) {
     335           0 :         goto done;
     336             :     }
     337           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
     338             :           id_opts->basic[SDAP_SASL_AUTHID].opt_name,
     339             :           dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID));
     340             : 
     341           0 :     ret = dp_opt_set_string(id_opts->basic,
     342             :                             SDAP_SASL_REALM, sasl_realm);
     343           0 :     if (ret != EOK) {
     344           0 :         goto done;
     345             :     }
     346             : 
     347           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
     348             :           id_opts->basic[SDAP_SASL_REALM].opt_name,
     349             :           dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM));
     350             : 
     351           0 :     ret = EOK;
     352             : done:
     353           0 :     talloc_free(tmp_ctx);
     354           0 :     return ret;
     355             : }
     356             : 
     357             : static const char *
     358           0 : sdap_gssapi_get_default_realm(TALLOC_CTX *mem_ctx)
     359             : {
     360           0 :     char *krb5_realm = NULL;
     361           0 :     const char *realm = NULL;
     362             :     krb5_error_code krberr;
     363           0 :     krb5_context context = NULL;
     364             : 
     365           0 :     krberr = krb5_init_context(&context);
     366           0 :     if (krberr) {
     367           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
     368           0 :         goto done;
     369             :     }
     370             : 
     371           0 :     krberr = krb5_get_default_realm(context, &krb5_realm);
     372           0 :     if (krberr) {
     373           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to get default realm name: %s\n",
     374             :                   sss_krb5_get_error_message(context, krberr));
     375           0 :         goto done;
     376             :     }
     377             : 
     378           0 :     realm = talloc_strdup(mem_ctx, krb5_realm);
     379           0 :     krb5_free_default_realm(context, krb5_realm);
     380           0 :     if (!realm) {
     381           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory\n");
     382           0 :         goto done;
     383             :     }
     384             : 
     385           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Will use default realm %s\n", realm);
     386             : done:
     387           0 :     if (context) krb5_free_context(context);
     388           0 :     return realm;
     389             : }
     390             : 
     391           0 : const char *sdap_gssapi_realm(struct dp_option *opts)
     392             : {
     393             :     const char *realm;
     394             : 
     395           0 :     realm = dp_opt_get_cstring(opts, SDAP_SASL_REALM);
     396           0 :     if (!realm) {
     397           0 :         realm = dp_opt_get_cstring(opts, SDAP_KRB5_REALM);
     398             :     }
     399             : 
     400           0 :     return realm;
     401             : }
     402             : 
     403           0 : int sdap_gssapi_init(TALLOC_CTX *mem_ctx,
     404             :                      struct dp_option *opts,
     405             :                      struct be_ctx *bectx,
     406             :                      struct sdap_service *sdap_service,
     407             :                      struct krb5_service **krb5_service)
     408             : {
     409             :     int ret;
     410             :     const char *krb5_servers;
     411             :     const char *krb5_backup_servers;
     412             :     const char *krb5_realm;
     413             :     const char *krb5_opt_realm;
     414           0 :     struct krb5_service *service = NULL;
     415             :     TALLOC_CTX *tmp_ctx;
     416             : 
     417           0 :     tmp_ctx = talloc_new(NULL);
     418           0 :     if (tmp_ctx == NULL) return ENOMEM;
     419             : 
     420           0 :     krb5_servers = dp_opt_get_string(opts, SDAP_KRB5_KDC);
     421           0 :     krb5_backup_servers = dp_opt_get_string(opts, SDAP_KRB5_BACKUP_KDC);
     422             : 
     423           0 :     krb5_opt_realm = sdap_gssapi_realm(opts);
     424           0 :     if (krb5_opt_realm == NULL) {
     425           0 :         DEBUG(SSSDBG_OP_FAILURE,
     426             :               "Missing krb5_realm option, will use libkrb default\n");
     427           0 :         krb5_realm = sdap_gssapi_get_default_realm(tmp_ctx);
     428           0 :         if (krb5_realm == NULL) {
     429           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     430             :                   "Cannot determine the Kerberos realm, aborting\n");
     431           0 :             ret = EIO;
     432           0 :             goto done;
     433             :         }
     434             :     } else {
     435           0 :         krb5_realm = talloc_strdup(tmp_ctx, krb5_opt_realm);
     436           0 :         if (krb5_realm == NULL) {
     437           0 :             ret = ENOMEM;
     438           0 :             goto done;
     439             :         }
     440             :     }
     441             : 
     442           0 :     ret = krb5_service_init(mem_ctx, bectx,
     443             :                             SSS_KRB5KDC_FO_SRV, krb5_servers,
     444             :                             krb5_backup_servers, krb5_realm,
     445           0 :                             dp_opt_get_bool(opts,
     446             :                                             SDAP_KRB5_USE_KDCINFO),
     447             :                             &service);
     448           0 :     if (ret != EOK) {
     449           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n");
     450           0 :         goto done;
     451             :     }
     452             : 
     453           0 :     ret = sdap_install_sigterm_handler(mem_ctx, bectx->ev, krb5_realm);
     454           0 :     if (ret != EOK) {
     455           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to install sigterm handler\n");
     456           0 :         goto done;
     457             :     }
     458             : 
     459           0 :     ret = sdap_install_offline_callback(mem_ctx, bectx,
     460             :                                         krb5_realm, SSS_KRB5KDC_FO_SRV);
     461           0 :     if (ret != EOK) {
     462           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to install sigterm handler\n");
     463           0 :         goto done;
     464             :     }
     465             : 
     466           0 :     sdap_service->kinit_service_name = talloc_strdup(sdap_service,
     467           0 :                                                      service->name);
     468           0 :     if (sdap_service->kinit_service_name == NULL) {
     469           0 :         ret = ENOMEM;
     470           0 :         goto done;
     471             :     }
     472             : 
     473           0 :     ret = EOK;
     474           0 :     *krb5_service = service;
     475             : done:
     476           0 :     talloc_free(tmp_ctx);
     477           0 :     if (ret != EOK) talloc_free(service);
     478           0 :     return ret;
     479             : }
     480             : 
     481           0 : static errno_t _sdap_urls_init(struct be_ctx *ctx,
     482             :                                struct sdap_service *service,
     483             :                                const char *service_name,
     484             :                                const char *dns_service_name,
     485             :                                const char *urls,
     486             :                                bool primary)
     487             : {
     488             :     TALLOC_CTX *tmp_ctx;
     489             :     char *srv_user_data;
     490           0 :     char **list = NULL;
     491             :     LDAPURLDesc *lud;
     492           0 :     errno_t ret = 0;
     493             :     int i;
     494             : 
     495           0 :     tmp_ctx = talloc_new(NULL);
     496           0 :     if (!tmp_ctx) {
     497           0 :         return ENOMEM;
     498             :     }
     499             : 
     500             : 
     501             :     /* split server parm into a list */
     502           0 :     ret = split_on_separator(tmp_ctx, urls, ',', true, true, &list, NULL);
     503           0 :     if (ret != EOK) {
     504           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n");
     505           0 :         goto done;
     506             :     }
     507             : 
     508             :     /* now for each URI add a new server to the failover service */
     509           0 :     for (i = 0; list[i]; i++) {
     510           0 :         if (be_fo_is_srv_identifier(list[i])) {
     511           0 :             if (!primary) {
     512           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     513             :                       "Failed to add server [%s] to failover service: "
     514             :                        "SRV resolution only allowed for primary servers!\n",
     515             :                        list[i]);
     516           0 :                 continue;
     517             :             }
     518             : 
     519           0 :             if (!dns_service_name) {
     520           0 :                 DEBUG(SSSDBG_FATAL_FAILURE,
     521             :                       "Missing DNS service name for service [%s].\n",
     522             :                           service_name);
     523           0 :                 ret = EINVAL;
     524           0 :                 goto done;
     525             :             }
     526           0 :             srv_user_data = talloc_strdup(service, dns_service_name);
     527           0 :             if (!srv_user_data) {
     528           0 :                 ret = ENOMEM;
     529           0 :                 goto done;
     530             :             }
     531             : 
     532           0 :             ret = be_fo_add_srv_server(ctx, service_name,
     533             :                                        dns_service_name, NULL,
     534             :                                        BE_FO_PROTO_TCP, false, srv_user_data);
     535           0 :             if (ret) {
     536           0 :                 DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add server\n");
     537           0 :                 goto done;
     538             :             }
     539             : 
     540           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Added service lookup\n");
     541           0 :             continue;
     542             :         }
     543             : 
     544           0 :         ret = ldap_url_parse(list[i], &lud);
     545           0 :         if (ret != LDAP_SUCCESS) {
     546           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
     547             :                   "Failed to parse ldap URI (%s)!\n", list[i]);
     548           0 :             ret = EINVAL;
     549           0 :             goto done;
     550             :         }
     551             : 
     552           0 :         if (lud->lud_host == NULL) {
     553           0 :             DEBUG(SSSDBG_OP_FAILURE,
     554             :                   "The LDAP URI (%s) did not contain a host name\n",
     555             :                       list[i]);
     556           0 :             ldap_free_urldesc(lud);
     557           0 :             continue;
     558             :         }
     559             : 
     560           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Added URI %s\n", list[i]);
     561             : 
     562           0 :         talloc_steal(service, list[i]);
     563             : 
     564             :         /* It could be ipv6 address in square brackets. Remove
     565             :          * the brackets if needed. */
     566           0 :         ret = remove_ipv6_brackets(lud->lud_host);
     567           0 :         if (ret != EOK) {
     568           0 :             goto done;
     569             :         }
     570             : 
     571           0 :         ret = be_fo_add_server(ctx, service->name, lud->lud_host,
     572           0 :                                lud->lud_port, list[i], primary);
     573           0 :         ldap_free_urldesc(lud);
     574           0 :         if (ret) {
     575           0 :             goto done;
     576             :         }
     577             :     }
     578             : 
     579             : done:
     580           0 :     talloc_free(tmp_ctx);
     581           0 :     return ret;
     582             : }
     583             : 
     584             : 
     585             : static inline errno_t
     586           0 : sdap_primary_urls_init(struct be_ctx *ctx, struct sdap_service *service,
     587             :                        const char *service_name, const char *dns_service_name,
     588             :                        const char *urls)
     589             : {
     590           0 :     return _sdap_urls_init(ctx, service, service_name,
     591             :                            dns_service_name, urls, true);
     592             : }
     593             : 
     594             : static inline errno_t
     595           0 : sdap_backup_urls_init(struct be_ctx *ctx, struct sdap_service *service,
     596             :                       const char *service_name, const char *dns_service_name,
     597             :                       const char *urls)
     598             : {
     599           0 :     return _sdap_urls_init(ctx, service, service_name,
     600             :                            dns_service_name, urls, false);
     601             : }
     602             : 
     603           0 : static int ldap_user_data_cmp(void *ud1, void *ud2)
     604             : {
     605           0 :     return strcasecmp((char*) ud1, (char*) ud2);
     606             : }
     607             : 
     608           0 : int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     609             :                       const char *service_name, const char *dns_service_name,
     610             :                       const char *urls, const char *backup_urls,
     611             :                       struct sdap_service **_service)
     612             : {
     613             :     TALLOC_CTX *tmp_ctx;
     614             :     struct sdap_service *service;
     615             :     int ret;
     616             : 
     617           0 :     tmp_ctx = talloc_new(NULL);
     618           0 :     if (!tmp_ctx) {
     619           0 :         return ENOMEM;
     620             :     }
     621             : 
     622           0 :     service = talloc_zero(tmp_ctx, struct sdap_service);
     623           0 :     if (!service) {
     624           0 :         ret = ENOMEM;
     625           0 :         goto done;
     626             :     }
     627             : 
     628           0 :     ret = be_fo_add_service(ctx, service_name, ldap_user_data_cmp);
     629           0 :     if (ret != EOK) {
     630           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
     631           0 :         goto done;
     632             :     }
     633             : 
     634           0 :     service->name = talloc_strdup(service, service_name);
     635           0 :     if (!service->name) {
     636           0 :         ret = ENOMEM;
     637           0 :         goto done;
     638             :     }
     639             : 
     640           0 :     if (!urls) {
     641           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     642             :               "No primary servers defined, using service discovery\n");
     643           0 :         urls = BE_SRV_IDENTIFIER;
     644             :     }
     645             : 
     646           0 :     ret = sdap_primary_urls_init(ctx, service, service_name, dns_service_name,
     647             :                                  urls);
     648           0 :     if (ret != EOK) {
     649           0 :         goto done;
     650             :     }
     651             : 
     652           0 :     if (backup_urls) {
     653           0 :         ret = sdap_backup_urls_init(ctx, service, service_name,
     654             :                                     dns_service_name, backup_urls);
     655           0 :         if (ret != EOK) {
     656           0 :             goto done;
     657             :         }
     658             :     }
     659             : 
     660           0 :     ret = be_fo_service_add_callback(memctx, ctx, service->name,
     661             :                                      sdap_uri_callback, service);
     662           0 :     if (ret != EOK) {
     663           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add failover callback!\n");
     664           0 :         goto done;
     665             :     }
     666             : 
     667           0 :     ret = EOK;
     668             : 
     669             : done:
     670           0 :     if (ret == EOK) {
     671           0 :         *_service = talloc_steal(memctx, service);
     672             :     }
     673           0 :     talloc_zfree(tmp_ctx);
     674           0 :     return ret;
     675             : }
     676             : 
     677           0 : errno_t string_to_shadowpw_days(const char *s, long *d)
     678             : {
     679             :     long l;
     680             :     char *endptr;
     681             : 
     682           0 :     if (s == NULL || *s == '\0') {
     683           0 :         *d = -1;
     684           0 :         return EOK;
     685             :     }
     686             : 
     687           0 :     errno = 0;
     688           0 :     l = strtol(s, &endptr, 10);
     689           0 :     if (errno != 0) {
     690           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     691             :               "strtol failed [%d][%s].\n", errno, strerror(errno));
     692           0 :         return errno;
     693             :     }
     694             : 
     695           0 :     if (*endptr != '\0') {
     696           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Input string [%s] is invalid.\n", s);
     697           0 :         return EINVAL;
     698             :     }
     699             : 
     700           0 :     if (l < -1) {
     701           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     702             :               "Input string contains not allowed negative value [%ld].\n",
     703             :                l);
     704           0 :         return EINVAL;
     705             :     }
     706             : 
     707           0 :     *d = l;
     708             : 
     709           0 :     return EOK;
     710             : }
     711             : 
     712           0 : errno_t get_sysdb_attr_name(TALLOC_CTX *mem_ctx,
     713             :                             struct sdap_attr_map *map,
     714             :                             size_t map_size,
     715             :                             const char *ldap_name,
     716             :                             char **sysdb_name)
     717             : {
     718             :     size_t i;
     719             : 
     720           0 :     for (i = 0; i < map_size; i++) {
     721             :         /* Skip map entries with no name (may depend on
     722             :          * schema selected)
     723             :          */
     724           0 :         if (!map[i].name) continue;
     725             : 
     726             :         /* Check if it is a mapped attribute */
     727           0 :         if(strcasecmp(ldap_name, map[i].name) == 0) break;
     728             :     }
     729             : 
     730           0 :     if (i < map_size) {
     731             :         /* We found a mapped name, return that */
     732           0 :         *sysdb_name = talloc_strdup(mem_ctx, map[i].sys_name);
     733             :     } else {
     734             :         /* Not mapped, use the same name */
     735           0 :         *sysdb_name = talloc_strdup(mem_ctx, ldap_name);
     736             :     }
     737             : 
     738           0 :     if (!*sysdb_name) {
     739           0 :         return ENOMEM;
     740             :     }
     741             : 
     742           0 :     return EOK;
     743             : }
     744             : 
     745           0 : errno_t list_missing_attrs(TALLOC_CTX *mem_ctx,
     746             :                            struct sdap_attr_map *map,
     747             :                            size_t map_size,
     748             :                            struct sysdb_attrs *recvd_attrs,
     749             :                            char ***missing_attrs)
     750             : {
     751             :     errno_t ret;
     752           0 :     size_t attr_count = 0;
     753             :     size_t i, j, k;
     754           0 :     char **missing = NULL;
     755             :     const char **expected_attrs;
     756             :     char *sysdb_name;
     757             :     TALLOC_CTX *tmp_ctx;
     758             : 
     759           0 :     if (!recvd_attrs || !missing_attrs) {
     760           0 :         return EINVAL;
     761             :     }
     762             : 
     763           0 :     tmp_ctx = talloc_new(NULL);
     764           0 :     if (!tmp_ctx) {
     765           0 :         return ENOMEM;
     766             :     }
     767             : 
     768           0 :     ret = build_attrs_from_map(tmp_ctx, map, map_size, NULL,
     769             :                                &expected_attrs, &attr_count);
     770           0 :     if (ret != EOK) {
     771           0 :         goto done;
     772             :     }
     773             : 
     774             :     /* Allocate the maximum possible values for missing_attrs, to
     775             :      * be on the safe side
     776             :      */
     777           0 :     missing = talloc_array(tmp_ctx, char *, attr_count + 2);
     778           0 :     if (!missing) {
     779           0 :         ret = ENOMEM;
     780           0 :         goto done;
     781             :     }
     782             : 
     783           0 :     k = 0;
     784             :     /* Check for each expected attribute */
     785           0 :     for (i = 0; i < attr_count; i++) {
     786           0 :         ret = get_sysdb_attr_name(tmp_ctx, map, map_size,
     787           0 :                                   expected_attrs[i],
     788             :                                   &sysdb_name);
     789           0 :         if (ret != EOK) {
     790           0 :             goto done;
     791             :         }
     792             : 
     793             :         /* objectClass is a special-case and we need to
     794             :          * check for it explicitly.
     795             :          */
     796           0 :         if (strcasecmp(sysdb_name, "objectClass") == 0) {
     797           0 :             talloc_free(sysdb_name);
     798           0 :             continue;
     799             :         }
     800             : 
     801             :         /* GECOS is another special case. Its value can come
     802             :          * either from the 'gecos' attribute or the 'cn'
     803             :          * attribute. It's best if we just never remove it.
     804             :          */
     805           0 :         if (strcasecmp(sysdb_name, SYSDB_GECOS) == 0) {
     806           0 :             talloc_free(sysdb_name);
     807           0 :             continue;
     808             :         }
     809             : 
     810           0 :         for (j = 0; j < recvd_attrs->num; j++) {
     811             :             /* Check whether this expected attribute appeared in the
     812             :              * received attributes and had a non-zero number of
     813             :              * values.
     814             :              */
     815           0 :             if ((strcasecmp(recvd_attrs->a[j].name, sysdb_name) == 0) &&
     816           0 :                 (recvd_attrs->a[j].num_values > 0)) {
     817           0 :                 break;
     818             :             }
     819             :         }
     820             : 
     821           0 :         if (j < recvd_attrs->num) {
     822             :             /* Attribute was found, therefore not missing */
     823           0 :             talloc_free(sysdb_name);
     824             :         } else {
     825             :             /* Attribute could not be found. Add to the missing list */
     826           0 :             missing[k] = talloc_steal(missing, sysdb_name);
     827           0 :             k++;
     828             : 
     829             :             /* Remove originalMemberOf as well if MemberOf is missing */
     830           0 :             if (strcmp(sysdb_name, SYSDB_MEMBEROF) == 0) {
     831           0 :                 missing[k] = talloc_strdup(missing, SYSDB_ORIG_MEMBEROF);
     832           0 :                 k++;
     833             :             }
     834             :         }
     835             :     }
     836             : 
     837           0 :     if (k == 0) {
     838           0 :         *missing_attrs = NULL;
     839             :     } else {
     840             :         /* Terminate the list */
     841           0 :         missing[k] = NULL;
     842           0 :         *missing_attrs = talloc_steal(mem_ctx, missing);
     843             :     }
     844           0 :     ret = EOK;
     845             : 
     846             : done:
     847           0 :     talloc_free(tmp_ctx);
     848           0 :     return ret;
     849             : }
     850             : 
     851           0 : bool sdap_is_secure_uri(const char *uri)
     852             : {
     853             :     /* LDAPS URI's are secure channels */
     854           0 :     if (strncasecmp(uri, LDAP_SSL_URI, strlen(LDAP_SSL_URI)) == 0) {
     855           0 :         return true;
     856             :     }
     857           0 :     return false;
     858             : }
     859             : 
     860          10 : char *sdap_get_access_filter(TALLOC_CTX *mem_ctx,
     861             :                              const char *base_filter)
     862             : {
     863          10 :     char *filter = NULL;
     864             : 
     865          10 :     if (base_filter == NULL) return NULL;
     866             : 
     867           9 :     if (base_filter[0] == '(') {
     868             :         /* This filter is wrapped in parentheses.
     869             :          * Pass it as-is to the openldap libraries.
     870             :          */
     871           7 :         filter = talloc_strdup(mem_ctx, base_filter);
     872             :     } else {
     873           2 :         filter = talloc_asprintf(mem_ctx, "(%s)", base_filter);
     874             :     }
     875             : 
     876           9 :     return filter;
     877             : }
     878             : 
     879             : errno_t
     880           0 : sdap_attrs_get_sid_str(TALLOC_CTX *mem_ctx,
     881             :                        struct sdap_idmap_ctx *idmap_ctx,
     882             :                        struct sysdb_attrs *sysdb_attrs,
     883             :                        const char *sid_attr,
     884             :                        char **_sid_str)
     885             : {
     886             :     errno_t ret;
     887             :     enum idmap_error_code err;
     888             :     struct ldb_message_element *el;
     889             :     char *sid_str;
     890             : 
     891           0 :     ret = sysdb_attrs_get_el(sysdb_attrs, sid_attr, &el);
     892           0 :     if (ret != EOK || el->num_values != 1) {
     893           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     894             :               "No [%s] attribute. [%d][%s]\n",
     895             :                sid_attr, el->num_values, strerror(ret));
     896           0 :         return ENOENT;
     897             :     }
     898             : 
     899           0 :     if (el->values[0].length > 2 &&
     900           0 :         el->values[0].data[0] == 'S' &&
     901           0 :         el->values[0].data[1] == '-') {
     902           0 :         sid_str = talloc_strndup(mem_ctx, (char *) el->values[0].data,
     903           0 :                                  el->values[0].length);
     904           0 :         if (sid_str == NULL) {
     905           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     906           0 :             return ENOMEM;
     907             :         }
     908             :     } else {
     909           0 :         err = sss_idmap_bin_sid_to_sid(idmap_ctx->map,
     910           0 :                                        el->values[0].data,
     911           0 :                                        el->values[0].length,
     912             :                                        &sid_str);
     913           0 :         if (err != IDMAP_SUCCESS) {
     914           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     915             :                   "Could not convert SID: [%s]\n",
     916             :                    idmap_error_string(err));
     917           0 :             return EIO;
     918             :         }
     919             :     }
     920             : 
     921           0 :     *_sid_str = talloc_steal(mem_ctx, sid_str);
     922             : 
     923           0 :     return EOK;
     924             : }
     925             : 
     926             : struct sdap_id_conn_ctx *
     927           0 : sdap_id_ctx_conn_add(struct sdap_id_ctx *id_ctx,
     928             :                      struct sdap_service *sdap_service)
     929             : {
     930             :     struct sdap_id_conn_ctx *conn;
     931             :     errno_t ret;
     932             : 
     933           0 :     conn = talloc_zero(id_ctx, struct sdap_id_conn_ctx);
     934           0 :     if (conn == NULL) {
     935           0 :         return NULL;
     936             :     }
     937           0 :     conn->service = talloc_steal(conn, sdap_service);
     938           0 :     conn->id_ctx = id_ctx;
     939             : 
     940             :     /* Create a connection cache */
     941           0 :     ret = sdap_id_conn_cache_create(conn, conn, &conn->conn_cache);
     942           0 :     if (ret != EOK) {
     943           0 :         talloc_free(conn);
     944           0 :         return NULL;
     945             :     }
     946           0 :     DLIST_ADD_END(id_ctx->conn, conn, struct sdap_id_conn_ctx *);
     947             : 
     948           0 :     return conn;
     949             : }
     950             : 
     951             : struct sdap_id_ctx *
     952           0 : sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
     953             :                 struct sdap_service *sdap_service)
     954             : {
     955             :     struct sdap_id_ctx *sdap_ctx;
     956             : 
     957           0 :     sdap_ctx = talloc_zero(mem_ctx, struct sdap_id_ctx);
     958           0 :     if (sdap_ctx == NULL) {
     959           0 :         return NULL;
     960             :     }
     961           0 :     sdap_ctx->be = bectx;
     962             : 
     963             :     /* There should be at least one connection context */
     964           0 :     sdap_ctx->conn = sdap_id_ctx_conn_add(sdap_ctx, sdap_service);
     965           0 :     if (sdap_ctx->conn == NULL) {
     966           0 :         talloc_free(sdap_ctx);
     967           0 :         return NULL;
     968             :     }
     969             : 
     970           0 :     return sdap_ctx;
     971             : }

Generated by: LCOV version 1.10