LCOV - code coverage report
Current view: top level - util - sss_ldap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 155 23.9 %
Date: 2016-06-29 Functions: 3 10 30.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Sumit Bose <sbose@redhat.com>
       4             : 
       5             :     Copyright (C) 2009 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "config.h"
      22             : #include "util/util.h"
      23             : #include "util/sss_sockets.h"
      24             : #include "util/sss_ldap.h"
      25             : 
      26             : #include "providers/ldap/sdap.h"
      27             : 
      28           1 : const char* sss_ldap_err2string(int err)
      29             : {
      30           1 :     if (IS_SSSD_ERROR(err)) {
      31           0 :         return sss_strerror(err);
      32             :     } else {
      33           1 :         return ldap_err2string(err);
      34             :     }
      35             : }
      36             : 
      37           0 : int sss_ldap_get_diagnostic_msg(TALLOC_CTX *mem_ctx, LDAP *ld, char **_errmsg)
      38             : {
      39           0 :     char *errmsg = NULL;
      40             :     int optret;
      41             : 
      42           0 :     optret = ldap_get_option(ld, SDAP_DIAGNOSTIC_MESSAGE, (void*)&errmsg);
      43           0 :     if (optret != LDAP_SUCCESS) {
      44           0 :         return EINVAL;
      45             :     }
      46             : 
      47           0 :     *_errmsg = talloc_strdup(mem_ctx, errmsg ? errmsg : "unknown error");
      48           0 :     ldap_memfree(errmsg);
      49           0 :     if (*_errmsg == NULL) {
      50           0 :         return ENOMEM;
      51             :     }
      52           0 :     return EOK;
      53             : }
      54             : 
      55           0 : int sss_ldap_control_create(const char *oid, int iscritical,
      56             :                             struct berval *value, int dupval,
      57             :                             LDAPControl **ctrlp)
      58             : {
      59             : #ifdef HAVE_LDAP_CONTROL_CREATE
      60           0 :     return ldap_control_create(oid, iscritical, value, dupval, ctrlp);
      61             : #else
      62             :     LDAPControl *lc = NULL;
      63             : 
      64             :     if (oid == NULL || ctrlp == NULL) {
      65             :         return LDAP_PARAM_ERROR;
      66             :     }
      67             : 
      68             :     lc = calloc(sizeof(LDAPControl), 1);
      69             :     if (lc == NULL) {
      70             :         return LDAP_NO_MEMORY;
      71             :     }
      72             : 
      73             :     lc->ldctl_oid = strdup(oid);
      74             :     if (lc->ldctl_oid == NULL) {
      75             :         free(lc);
      76             :         return LDAP_NO_MEMORY;
      77             :     }
      78             : 
      79             :     if (value != NULL && value->bv_val != NULL) {
      80             :         if (dupval == 0) {
      81             :             lc->ldctl_value = *value;
      82             :         } else {
      83             :             ber_dupbv(&lc->ldctl_value, value);
      84             :             if (lc->ldctl_value.bv_val == NULL) {
      85             :                 free(lc->ldctl_oid);
      86             :                 free(lc);
      87             :                 return LDAP_NO_MEMORY;
      88             :             }
      89             :         }
      90             :     }
      91             : 
      92             :     lc->ldctl_iscritical = iscritical;
      93             : 
      94             :     *ctrlp = lc;
      95             : 
      96             :     return LDAP_SUCCESS;
      97             : #endif
      98             : }
      99             : 
     100             : #ifdef HAVE_LDAP_INIT_FD
     101             : 
     102             : #define LDAP_PROTO_TCP 1 /* ldap://  */
     103             : #define LDAP_PROTO_UDP 2 /* reserved */
     104             : #define LDAP_PROTO_IPC 3 /* ldapi:// */
     105             : #define LDAP_PROTO_EXT 4 /* user-defined socket/sockbuf */
     106             : 
     107             : extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld);
     108             : 
     109             : static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq);
     110             : #endif
     111             : 
     112             : struct sss_ldap_init_state {
     113             :     LDAP *ldap;
     114             :     int sd;
     115             :     const char *uri;
     116             : };
     117             : 
     118           0 : static int sss_ldap_init_state_destructor(void *data)
     119             : {
     120           0 :     struct sss_ldap_init_state *state = (struct sss_ldap_init_state *)data;
     121             : 
     122           0 :     if (state->ldap) {
     123           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     124             :               "calling ldap_unbind_ext for ldap:[%p] sd:[%d]\n",
     125             :               state->ldap, state->sd);
     126           0 :         ldap_unbind_ext(state->ldap, NULL, NULL);
     127             :     }
     128           0 :     if (state->sd != -1) {
     129           0 :         DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);
     130           0 :         close(state->sd);
     131           0 :         state->sd = -1;
     132             :     }
     133             : 
     134           0 :     return 0;
     135             : }
     136             : 
     137             : 
     138           0 : struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
     139             :                                       struct tevent_context *ev,
     140             :                                       const char *uri,
     141             :                                       struct sockaddr_storage *addr,
     142             :                                       int addr_len, int timeout)
     143             : {
     144           0 :     int ret = EOK;
     145             :     struct tevent_req *req;
     146             :     struct sss_ldap_init_state *state;
     147             : 
     148           0 :     req = tevent_req_create(mem_ctx, &state, struct sss_ldap_init_state);
     149           0 :     if (req == NULL) {
     150           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
     151           0 :         return NULL;
     152             :     }
     153             : 
     154           0 :     talloc_set_destructor((TALLOC_CTX *)state, sss_ldap_init_state_destructor);
     155             : 
     156           0 :     state->ldap = NULL;
     157           0 :     state->sd = -1;
     158           0 :     state->uri = uri;
     159             : 
     160             : #ifdef HAVE_LDAP_INIT_FD
     161             :     struct tevent_req *subreq;
     162             : 
     163           0 :     subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout);
     164           0 :     if (subreq == NULL) {
     165           0 :         ret = ENOMEM;
     166           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n");
     167           0 :         goto fail;
     168             :     }
     169             : 
     170           0 :     tevent_req_set_callback(subreq, sss_ldap_init_sys_connect_done, req);
     171           0 :     return req;
     172             : 
     173             : fail:
     174           0 :     tevent_req_error(req, ret);
     175             : #else
     176             :     DEBUG(SSSDBG_MINOR_FAILURE, "ldap_init_fd not available, "
     177             :               "will use ldap_initialize with uri [%s].\n", uri);
     178             :     ret = ldap_initialize(&state->ldap, uri);
     179             :     if (ret == LDAP_SUCCESS) {
     180             :         tevent_req_done(req);
     181             :     } else {
     182             :         DEBUG(SSSDBG_CRIT_FAILURE,
     183             :               "ldap_initialize failed [%s].\n", sss_ldap_err2string(ret));
     184             :         if (ret == LDAP_SERVER_DOWN) {
     185             :             tevent_req_error(req, ETIMEDOUT);
     186             :         } else {
     187             :             tevent_req_error(req, EIO);
     188             :         }
     189             :     }
     190             : #endif
     191             : 
     192           0 :     tevent_req_post(req, ev);
     193           0 :     return req;
     194             : }
     195             : 
     196             : #ifdef HAVE_LDAP_INIT_FD
     197           0 : static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq)
     198             : {
     199           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     200             :                                                       struct tevent_req);
     201           0 :     struct sss_ldap_init_state *state = tevent_req_data(req,
     202             :                                                     struct sss_ldap_init_state);
     203             :     char *tlserr;
     204             :     int ret;
     205             :     int lret;
     206             :     int optret;
     207             : 
     208           0 :     ret = sssd_async_socket_init_recv(subreq, &state->sd);
     209           0 :     talloc_zfree(subreq);
     210           0 :     if (ret != EOK) {
     211           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     212             :               "sssd_async_socket_init request failed: [%d]: %s.\n",
     213             :               ret, sss_strerror(ret));
     214           0 :         goto fail;
     215             :     }
     216             :     /* Initialize LDAP handler */
     217             : 
     218           0 :     lret = ldap_init_fd(state->sd, LDAP_PROTO_TCP, state->uri, &state->ldap);
     219           0 :     if (lret != LDAP_SUCCESS) {
     220           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     221             :               "ldap_init_fd failed: %s. [%d][%s]\n",
     222             :                sss_ldap_err2string(lret), state->sd, state->uri);
     223           0 :         ret = lret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO;
     224           0 :         goto fail;
     225             :     }
     226             : 
     227           0 :     if (ldap_is_ldaps_url(state->uri)) {
     228           0 :         lret = ldap_install_tls(state->ldap);
     229           0 :         if (lret != LDAP_SUCCESS) {
     230           0 :             if (lret == LDAP_LOCAL_ERROR) {
     231           0 :                 DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n");
     232             :             } else {
     233             : 
     234           0 :                 optret = sss_ldap_get_diagnostic_msg(state, state->ldap,
     235             :                                                      &tlserr);
     236           0 :                 if (optret == LDAP_SUCCESS) {
     237           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     238             :                           "ldap_install_tls failed: [%s] [%s]\n",
     239             :                           sss_ldap_err2string(lret), tlserr);
     240           0 :                     sss_log(SSS_LOG_ERR,
     241             :                             "Could not start TLS encryption. %s", tlserr);
     242             :                 } else {
     243           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     244             :                           "ldap_install_tls failed: [%s]\n",
     245             :                           sss_ldap_err2string(lret));
     246           0 :                     sss_log(SSS_LOG_ERR, "Could not start TLS encryption. "
     247             :                                          "Check for certificate issues.");
     248             :                 }
     249             : 
     250           0 :                 ret = EIO;
     251           0 :                 goto fail;
     252             :             }
     253             :         }
     254             :     }
     255             : 
     256           0 :     tevent_req_done(req);
     257           0 :     return;
     258             : 
     259             : fail:
     260           0 :     tevent_req_error(req, ret);
     261             : }
     262             : #endif
     263             : 
     264           0 : int sss_ldap_init_recv(struct tevent_req *req, LDAP **ldap, int *sd)
     265             : {
     266           0 :     struct sss_ldap_init_state *state = tevent_req_data(req,
     267             :                                                     struct sss_ldap_init_state);
     268           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     269             : 
     270             :     /* Everything went well therefore we do not want to release resources */
     271           0 :     talloc_set_destructor(state, NULL);
     272             : 
     273           0 :     *ldap = state->ldap;
     274           0 :     *sd = state->sd;
     275             : 
     276           0 :     return EOK;
     277             : }
     278             : 
     279             : /*
     280             :  * _filter will contain combined filters from all possible search bases
     281             :  * or NULL if it should be empty
     282             :  */
     283             : 
     284             : 
     285         103 : bool sss_ldap_dn_in_search_bases_len(TALLOC_CTX *mem_ctx,
     286             :                                      const char *dn,
     287             :                                      struct sdap_search_base **search_bases,
     288             :                                      char **_filter,
     289             :                                      int *_match_len)
     290             : {
     291             :     struct sdap_search_base *base;
     292             :     int basedn_len, dn_len;
     293             :     int len_diff;
     294             :     int i, j;
     295         103 :     bool base_confirmed = false;
     296         103 :     bool comma_found = false;
     297         103 :     bool backslash_found = false;
     298         103 :     char *filter = NULL;
     299         103 :     bool ret = false;
     300             :     int match_len;
     301             : 
     302         103 :     if (dn == NULL) {
     303           0 :         DEBUG(SSSDBG_FUNC_DATA, "dn is NULL\n");
     304           0 :         ret = false;
     305           0 :         goto done;
     306             :     }
     307             : 
     308         103 :     if (search_bases == NULL) {
     309          30 :         DEBUG(SSSDBG_FUNC_DATA, "search_bases is NULL\n");
     310          30 :         ret = false;
     311          30 :         goto done;
     312             :     }
     313             : 
     314          73 :     dn_len = strlen(dn);
     315          99 :     for (i = 0; search_bases[i] != NULL; i++) {
     316          74 :         base = search_bases[i];
     317          74 :         basedn_len = strlen(base->basedn);
     318             : 
     319          74 :         if (basedn_len > dn_len) {
     320           0 :             continue;
     321             :         }
     322             : 
     323          74 :         len_diff = dn_len - basedn_len;
     324          74 :         base_confirmed = (strncasecmp(&dn[len_diff], base->basedn, basedn_len) == 0);
     325          74 :         if (!base_confirmed) {
     326          26 :             continue;
     327             :         }
     328          48 :         match_len = basedn_len;
     329             : 
     330          48 :         switch (base->scope) {
     331             :         case LDAP_SCOPE_BASE:
     332             :             /* dn > base? */
     333           0 :             if (len_diff != 0) {
     334           0 :                 continue;
     335             :             }
     336           0 :             break;
     337             :         case LDAP_SCOPE_ONELEVEL:
     338           0 :             if (len_diff == 0) {
     339             :                 /* Base object doesn't belong to scope=one
     340             :                  * search */
     341           0 :                 continue;
     342             :             }
     343             : 
     344           0 :             comma_found = false;
     345           0 :             for (j = 0; j < len_diff - 1; j++) { /* ignore comma before base */
     346           0 :                 if (dn[j] == '\\') {
     347           0 :                     backslash_found = true;
     348           0 :                 } else if (dn[j] == ',' && !backslash_found) {
     349           0 :                     comma_found = true;
     350           0 :                     break;
     351             :                 } else {
     352           0 :                     backslash_found = false;
     353             :                 }
     354             :             }
     355             : 
     356             :             /* it has at least one more level */
     357           0 :             if (comma_found) {
     358           0 :                 continue;
     359             :             }
     360             : 
     361           0 :             break;
     362             :         case LDAP_SCOPE_SUBTREE:
     363             :             /* dn length >= base dn length && base_confirmed == true */
     364          48 :             break;
     365             :         default:
     366           0 :             DEBUG(SSSDBG_FUNC_DATA, "Unsupported scope: %d\n", base->scope);
     367           0 :             continue;
     368             :         }
     369             : 
     370             :         /*
     371             :          *  If we get here, the dn is valid.
     372             :          *  If no filter is set, than return true immediately.
     373             :          *  Append filter otherwise.
     374             :          */
     375          48 :         ret = true;
     376          48 :         if (_match_len) {
     377          28 :             *_match_len = match_len;
     378             :         }
     379             : 
     380          48 :         if (base->filter == NULL || _filter == NULL) {
     381             :             goto done;
     382             :         } else {
     383           0 :             filter = talloc_strdup_append(filter, base->filter);
     384           0 :             if (filter == NULL) {
     385           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup_append() failed\n");
     386           0 :                 ret = false;
     387           0 :                 goto done;
     388             :             }
     389             :         }
     390             :     }
     391             : 
     392          25 :     if (_filter != NULL) {
     393          19 :         if (filter != NULL) {
     394           0 :             *_filter = talloc_asprintf(mem_ctx, "(|%s)", filter);
     395           0 :             if (*_filter == NULL) {
     396           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     397             :                       "talloc_asprintf_append() failed\n");
     398           0 :                 ret = false;
     399           0 :                 goto done;
     400             :             }
     401             :         } else {
     402          19 :             *_filter = NULL;
     403             :         }
     404             :     }
     405             : 
     406             : done:
     407         103 :     talloc_free(filter);
     408         103 :     return ret;
     409             : }
     410             : 
     411          40 : bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx,
     412             :                                  const char *dn,
     413             :                                  struct sdap_search_base **search_bases,
     414             :                                  char **_filter)
     415             : {
     416          40 :     return sss_ldap_dn_in_search_bases_len(mem_ctx, dn, search_bases, _filter,
     417             :                                            NULL);
     418             : }
     419             : 
     420           0 : char *sss_ldap_encode_ndr_uint32(TALLOC_CTX *mem_ctx, uint32_t flags)
     421             : {
     422             :     char hex[9]; /* 4 bytes in hex + terminating zero */
     423             :     errno_t ret;
     424             : 
     425           0 :     ret = snprintf(hex, 9, "%08x", flags);
     426           0 :     if (ret != 8) {
     427           0 :         return NULL;
     428             :     }
     429             : 
     430           0 :     return talloc_asprintf(mem_ctx, "\\%c%c\\%c%c\\%c%c\\%c%c",
     431           0 :                            hex[6], hex[7], hex[4], hex[5],
     432           0 :                            hex[2], hex[3], hex[0], hex[1]);
     433             : }

Generated by: LCOV version 1.10