LCOV - code coverage report
Current view: top level - providers/ldap - sdap_fd_events.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 116 0.0 %
Date: 2016-06-29 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Helper routines for file descriptor events
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 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 "util/util.h"
      26             : #include "providers/ldap/sdap_async_private.h"
      27             : 
      28             : struct sdap_fd_events {
      29             : #ifdef HAVE_LDAP_CONNCB
      30             :     struct ldap_conncb *conncb;
      31             : #else
      32             :     struct tevent_fd *fde;
      33             : #endif
      34             : };
      35             : 
      36           0 : int get_fd_from_ldap(LDAP *ldap, int *fd)
      37             : {
      38             :     int ret;
      39             : 
      40           0 :     ret = ldap_get_option(ldap, LDAP_OPT_DESC, fd);
      41           0 :     if (ret != LDAP_OPT_SUCCESS || *fd < 0) {
      42           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get fd from ldap!!\n");
      43           0 :         *fd = -1;
      44           0 :         return EIO;
      45             :     }
      46             : 
      47           0 :     return EOK;
      48             : }
      49             : 
      50           0 : int remove_ldap_connection_callbacks(struct sdap_handle *sh)
      51             : {
      52             :     /* sdap_fd_events might be NULL here if the back end was marked offline
      53             :      * before a connection was established.
      54             :      */
      55           0 :     if (sh->sdap_fd_events) {
      56             : #ifdef HAVE_LDAP_CONNCB
      57           0 :         talloc_zfree(sh->sdap_fd_events->conncb);
      58             : #else
      59             :         talloc_zfree(sh->sdap_fd_events->fde);
      60             : #endif
      61             :     }
      62           0 :     return EOK;
      63             : }
      64             : 
      65             : #ifdef HAVE_LDAP_CONNCB
      66             : 
      67           0 : static int remove_connection_callback(TALLOC_CTX *mem_ctx)
      68             : {
      69             :     int lret;
      70           0 :     struct ldap_conncb *conncb = talloc_get_type(mem_ctx, struct ldap_conncb);
      71             : 
      72           0 :     struct ldap_cb_data *cb_data = talloc_get_type(conncb->lc_arg,
      73             :                                                    struct ldap_cb_data);
      74             : 
      75           0 :     lret = ldap_get_option(cb_data->sh->ldap, LDAP_OPT_CONNECT_CB, conncb);
      76           0 :     if (lret != LDAP_OPT_SUCCESS) {
      77           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to remove connection callback.\n");
      78             :     } else {
      79           0 :         DEBUG(SSSDBG_TRACE_ALL, "Successfully removed connection callback.\n");
      80             :     }
      81           0 :     return EOK;
      82             : }
      83             : 
      84           0 : static int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb,
      85             :                                           LDAPURLDesc *srv,
      86             :                                           struct sockaddr *addr,
      87             :                                           struct ldap_conncb *ctx)
      88             : {
      89             :     int ret;
      90             :     ber_socket_t ber_fd;
      91             :     struct fd_event_item *fd_event_item;
      92           0 :     struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
      93             :                                                    struct ldap_cb_data);
      94             : 
      95           0 :     if (cb_data == NULL) {
      96           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      97             :               "sdap_ldap_connect_callback_add called without "
      98             :                   "callback data.\n");
      99           0 :         return EINVAL;
     100             :     }
     101             : 
     102           0 :     ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
     103           0 :     if (ret == -1) {
     104           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ber_sockbuf_ctrl failed.\n");
     105           0 :         return EINVAL;
     106             :     }
     107             : 
     108           0 :     if (DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {
     109           0 :         char *uri = ldap_url_desc2str(srv);
     110           0 :         DEBUG(SSSDBG_TRACE_LIBS, "New LDAP connection to [%s] with fd [%d].\n",
     111             :                   uri, ber_fd);
     112           0 :         free(uri);
     113             :     }
     114             : 
     115           0 :     fd_event_item = talloc_zero(cb_data, struct fd_event_item);
     116           0 :     if (fd_event_item == NULL) {
     117           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
     118           0 :         return ENOMEM;
     119             :     }
     120             : 
     121           0 :     fd_event_item->fde = tevent_add_fd(cb_data->ev, fd_event_item, ber_fd,
     122             :                                        TEVENT_FD_READ, sdap_ldap_result,
     123             :                                        cb_data->sh);
     124           0 :     if (fd_event_item->fde == NULL) {
     125           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
     126           0 :         talloc_free(fd_event_item);
     127           0 :         return ENOMEM;
     128             :     }
     129           0 :     fd_event_item->fd = ber_fd;
     130             : 
     131           0 :     DLIST_ADD(cb_data->fd_list, fd_event_item);
     132             : 
     133           0 :     return LDAP_SUCCESS;
     134             : }
     135             : 
     136           0 : static void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb,
     137             :                                            struct ldap_conncb *ctx)
     138             : {
     139             :     int ret;
     140             :     ber_socket_t ber_fd;
     141             :     struct fd_event_item *fd_event_item;
     142           0 :     struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
     143             :                                                    struct ldap_cb_data);
     144             : 
     145           0 :     if (sb == NULL || cb_data == NULL) {
     146           0 :         return;
     147             :     }
     148             : 
     149           0 :     ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
     150           0 :     if (ret == -1) {
     151           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ber_sockbuf_ctrl failed.\n");
     152           0 :         return;
     153             :     }
     154           0 :     DEBUG(SSSDBG_TRACE_ALL, "Closing LDAP connection with fd [%d].\n", ber_fd);
     155             : 
     156           0 :     DLIST_FOR_EACH(fd_event_item, cb_data->fd_list) {
     157           0 :         if (fd_event_item->fd == ber_fd) {
     158           0 :             break;
     159             :         }
     160             :     }
     161           0 :     if (fd_event_item == NULL) {
     162           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "No event for fd [%d] found.\n", ber_fd);
     163           0 :         return;
     164             :     }
     165             : 
     166           0 :     DLIST_REMOVE(cb_data->fd_list, fd_event_item);
     167           0 :     talloc_zfree(fd_event_item);
     168             : 
     169           0 :     return;
     170             : }
     171             : 
     172             : #else
     173             : 
     174             : static int sdap_install_ldap_callbacks(struct sdap_handle *sh,
     175             :                                        struct tevent_context *ev)
     176             : {
     177             :     int fd;
     178             :     int ret;
     179             : 
     180             :     if (sh->sdap_fd_events) {
     181             :         DEBUG(SSSDBG_CRIT_FAILURE,
     182             :               "sdap_install_ldap_callbacks is called with already "
     183             :                   "initialized sdap_fd_events.\n");
     184             :         return EINVAL;
     185             :     }
     186             : 
     187             :     sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events);
     188             :     if (!sh->sdap_fd_events) {
     189             :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     190             :         return ENOMEM;
     191             :     }
     192             : 
     193             :     ret = get_fd_from_ldap(sh->ldap, &fd);
     194             :     if (ret) return ret;
     195             : 
     196             :     sh->sdap_fd_events->fde = tevent_add_fd(ev, sh->sdap_fd_events, fd,
     197             :                                             TEVENT_FD_READ, sdap_ldap_result,
     198             :                                             sh);
     199             :     if (!sh->sdap_fd_events->fde) {
     200             :         talloc_zfree(sh->sdap_fd_events);
     201             :         return ENOMEM;
     202             :     }
     203             : 
     204             :     DEBUG(SSSDBG_TRACE_INTERNAL,
     205             :           "Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
     206             :               sh, (int)sh->connected, sh->ops, sh->sdap_fd_events->fde,
     207             :               sh->ldap);
     208             : 
     209             :     return EOK;
     210             : }
     211             : 
     212             : #endif
     213             : 
     214             : 
     215           0 : errno_t setup_ldap_connection_callbacks(struct sdap_handle *sh,
     216             :                                         struct tevent_context *ev)
     217             : {
     218             : #ifdef HAVE_LDAP_CONNCB
     219             :     int ret;
     220             :     struct ldap_cb_data *cb_data;
     221             : 
     222           0 :     sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events);
     223           0 :     if (sh->sdap_fd_events == NULL) {
     224           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     225           0 :         ret = ENOMEM;
     226           0 :         goto fail;
     227             :     }
     228             : 
     229           0 :     sh->sdap_fd_events->conncb = talloc_zero(sh->sdap_fd_events,
     230             :                                              struct ldap_conncb);
     231           0 :     if (sh->sdap_fd_events->conncb == NULL) {
     232           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     233           0 :         ret = ENOMEM;
     234           0 :         goto fail;
     235             :     }
     236             : 
     237           0 :     cb_data = talloc_zero(sh->sdap_fd_events->conncb, struct ldap_cb_data);
     238           0 :     if (cb_data == NULL) {
     239           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     240           0 :         ret = ENOMEM;
     241           0 :         goto fail;
     242             :     }
     243           0 :     cb_data->sh = sh;
     244           0 :     cb_data->ev = ev;
     245             : 
     246           0 :     sh->sdap_fd_events->conncb->lc_add = sdap_ldap_connect_callback_add;
     247           0 :     sh->sdap_fd_events->conncb->lc_del = sdap_ldap_connect_callback_del;
     248           0 :     sh->sdap_fd_events->conncb->lc_arg = cb_data;
     249             : 
     250           0 :     ret = ldap_set_option(sh->ldap, LDAP_OPT_CONNECT_CB,
     251           0 :                           sh->sdap_fd_events->conncb);
     252           0 :     if (ret != LDAP_OPT_SUCCESS) {
     253           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set connection callback\n");
     254           0 :         ret = EFAULT;
     255           0 :         goto fail;
     256             :     }
     257             : 
     258           0 :     talloc_set_destructor((TALLOC_CTX *) sh->sdap_fd_events->conncb,
     259             :                           remove_connection_callback);
     260             : 
     261           0 :     return EOK;
     262             : 
     263             : fail:
     264           0 :     talloc_zfree(sh->sdap_fd_events);
     265           0 :     return ret;
     266             : #else
     267             :     DEBUG(SSSDBG_TRACE_ALL, "LDAP connection callbacks are not supported.\n");
     268             :     return EOK;
     269             : #endif
     270             : }
     271             : 
     272           0 : errno_t sdap_set_connected(struct sdap_handle *sh, struct tevent_context *ev)
     273             : {
     274           0 :     int ret = EOK;
     275             : 
     276           0 :     sh->connected = true;
     277             : 
     278             : #ifndef HAVE_LDAP_CONNCB
     279             :     ret = sdap_install_ldap_callbacks(sh, ev);
     280             : #endif
     281             : 
     282           0 :     return ret;
     283             : }
     284             : 
     285           0 : errno_t sdap_call_conn_cb(const char *uri,int fd, struct sdap_handle *sh)
     286             : {
     287             : #ifdef HAVE_LDAP_CONNCB
     288             :     int ret;
     289             :     Sockbuf *sb;
     290             :     LDAPURLDesc *lud;
     291             : 
     292           0 :     sb = ber_sockbuf_alloc();
     293           0 :     if (sb == NULL) {
     294           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ber_sockbuf_alloc failed.\n");
     295           0 :         return ENOMEM;
     296             :     }
     297             : 
     298           0 :     ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_SET_FD, &fd);
     299           0 :     if (ret != 1) {
     300           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "ber_sockbuf_ctrl failed.\n");
     301           0 :         return EFAULT;
     302             :     }
     303             : 
     304           0 :     ret = ldap_url_parse(uri, &lud);
     305           0 :     if (ret != 0) {
     306           0 :         ber_sockbuf_free(sb);
     307           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     308             :               "ldap_url_parse failed to validate [%s] on fd [%d].\n",
     309             :                uri, fd);
     310           0 :         return EFAULT;
     311             :     }
     312             : 
     313           0 :     ret = sdap_ldap_connect_callback_add(NULL, sb, lud, NULL,
     314           0 :                                          sh->sdap_fd_events->conncb);
     315             : 
     316           0 :     ldap_free_urldesc(lud);
     317           0 :     ber_sockbuf_free(sb);
     318           0 :     return ret;
     319             : #else
     320             :     DEBUG(SSSDBG_TRACE_ALL, "LDAP connection callbacks are not supported.\n");
     321             :     return EOK;
     322             : #endif
     323             : }

Generated by: LCOV version 1.10