LCOV - code coverage report
Current view: top level - providers/ldap - ldap_common.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 59 424 13.9 %
Date: 2015-10-19 Functions: 5 25 20.0 %

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

Generated by: LCOV version 1.10