LCOV - code coverage report
Current view: top level - dirmngr - ldap-wrapper.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 298 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /* ldap-wrapper.c - LDAP access via a wrapper process
       2             :  * Copyright (C) 2004, 2005, 2007, 2008 g10 Code GmbH
       3             :  * Copyright (C) 2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG 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             :  * GnuPG 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             : /*
      22             :    We can't use LDAP directly for these reasons:
      23             : 
      24             :    1. On some systems the LDAP library uses (indirectly) pthreads and
      25             :       that is not compatible with PTh.
      26             : 
      27             :    2. It is huge library in particular if TLS comes into play.  So
      28             :       problems with unfreed memory might turn up and we don't want
      29             :       this in a long running daemon.
      30             : 
      31             :    3. There is no easy way for timeouts. In particular the timeout
      32             :       value does not work for DNS lookups (well, this is usual) and it
      33             :       seems not to work while loading a large attribute like a
      34             :       CRL. Having a separate process allows us to either tell the
      35             :       process to commit suicide or have our own housekepping function
      36             :       kill it after some time.  The latter also allows proper
      37             :       cancellation of a query at any point of time.
      38             : 
      39             :    4. Given that we are going out to the network and usually get back
      40             :       a long response, the fork/exec overhead is acceptable.
      41             : 
      42             :    Note that under WindowsCE the number of processes is strongly
      43             :    limited (32 processes including the kernel processes) and thus we
      44             :    don't use the process approach but implement a different wrapper in
      45             :    ldap-wrapper-ce.c.
      46             : */
      47             : 
      48             : 
      49             : #include <config.h>
      50             : 
      51             : #include <stdio.h>
      52             : #include <stdlib.h>
      53             : #include <string.h>
      54             : #include <errno.h>
      55             : #include <unistd.h>
      56             : #include <fcntl.h>
      57             : #include <time.h>
      58             : #include <npth.h>
      59             : 
      60             : #include "dirmngr.h"
      61             : #include "exechelp.h"
      62             : #include "misc.h"
      63             : #include "ldap-wrapper.h"
      64             : 
      65             : 
      66             : #ifdef HAVE_W32_SYSTEM
      67             : #define setenv(a,b,c) SetEnvironmentVariable ((a),(b))
      68             : #else
      69             : #define pth_close(fd) close(fd)
      70             : #endif
      71             : 
      72             : #ifndef USE_LDAPWRAPPER
      73             : # error This module is not expected to be build.
      74             : #endif
      75             : 
      76             : /* In case sysconf does not return a value we need to have a limit. */
      77             : #ifdef _POSIX_OPEN_MAX
      78             : #define MAX_OPEN_FDS _POSIX_OPEN_MAX
      79             : #else
      80             : #define MAX_OPEN_FDS 20
      81             : #endif
      82             : 
      83             : #define INACTIVITY_TIMEOUT (opt.ldaptimeout + 60*5)  /* seconds */
      84             : 
      85             : #define TIMERTICK_INTERVAL 2
      86             : 
      87             : /* To keep track of the LDAP wrapper state we use this structure.  */
      88             : struct wrapper_context_s
      89             : {
      90             :   struct wrapper_context_s *next;
      91             : 
      92             :   pid_t pid;    /* The pid of the wrapper process. */
      93             :   int printable_pid; /* Helper to print diagnostics after the process has
      94             :                         been cleaned up. */
      95             :   int fd;       /* Connected with stdout of the ldap wrapper.  */
      96             :   gpg_error_t fd_error; /* Set to the gpg_error of the last read error
      97             :                            if any.  */
      98             :   int log_fd;   /* Connected with stderr of the ldap wrapper.  */
      99             :   ctrl_t ctrl;  /* Connection data. */
     100             :   int ready;    /* Internally used to mark to be removed contexts. */
     101             :   ksba_reader_t reader; /* The ksba reader object or NULL. */
     102             :   char *line;     /* Used to print the log lines (malloced). */
     103             :   size_t linesize;/* Allocated size of LINE.  */
     104             :   size_t linelen; /* Use size of LINE.  */
     105             :   time_t stamp;   /* The last time we noticed ativity.  */
     106             : };
     107             : 
     108             : 
     109             : 
     110             : /* We keep a global list of spawed wrapper process.  A separate thread
     111             :    makes use of this list to log error messages and to watch out for
     112             :    finished processes. */
     113             : static struct wrapper_context_s *wrapper_list;
     114             : 
     115             : /* We need to know whether we are shutting down the process.  */
     116             : static int shutting_down;
     117             : 
     118             : /* Close the pth file descriptor FD and set it to -1.  */
     119             : #define SAFE_CLOSE(fd) \
     120             :   do { int _fd = fd; if (_fd != -1) { close (_fd); fd = -1;} } while (0)
     121             : 
     122             : 
     123             : 
     124             : 
     125             : /* Read a fixed amount of data from READER into BUFFER.  */
     126             : static gpg_error_t
     127           0 : read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
     128             : {
     129             :   gpg_error_t err;
     130             :   size_t nread;
     131             : 
     132           0 :   while (count)
     133             :     {
     134           0 :       err = ksba_reader_read (reader, buffer, count, &nread);
     135           0 :       if (err)
     136           0 :         return err;
     137           0 :       buffer += nread;
     138           0 :       count -= nread;
     139             :     }
     140           0 :   return 0;
     141             : }
     142             : 
     143             : 
     144             : /* Release the wrapper context and kill a running wrapper process. */
     145             : static void
     146           0 : destroy_wrapper (struct wrapper_context_s *ctx)
     147             : {
     148           0 :   if (ctx->pid != (pid_t)(-1))
     149             :     {
     150           0 :       gnupg_kill_process (ctx->pid);
     151           0 :       gnupg_release_process (ctx->pid);
     152             :     }
     153           0 :   ksba_reader_release (ctx->reader);
     154           0 :   SAFE_CLOSE (ctx->fd);
     155           0 :   SAFE_CLOSE (ctx->log_fd);
     156           0 :   xfree (ctx->line);
     157           0 :   xfree (ctx);
     158           0 : }
     159             : 
     160             : 
     161             : /* Print the content of LINE to thye log stream but make sure to only
     162             :    print complete lines.  Using NULL for LINE will flush any pending
     163             :    output.  LINE may be modified by this fucntion. */
     164             : static void
     165           0 : print_log_line (struct wrapper_context_s *ctx, char *line)
     166             : {
     167             :   char *s;
     168             :   size_t n;
     169             : 
     170           0 :   if (!line)
     171             :     {
     172           0 :       if (ctx->line && ctx->linelen)
     173             :         {
     174             : 
     175           0 :           log_info ("%s\n", ctx->line);
     176           0 :           ctx->linelen = 0;
     177             :         }
     178           0 :       return;
     179             :     }
     180             : 
     181           0 :   while ((s = strchr (line, '\n')))
     182             :     {
     183           0 :       *s = 0;
     184           0 :       if (ctx->line && ctx->linelen)
     185             :         {
     186           0 :           log_info ("%s", ctx->line);
     187           0 :           ctx->linelen = 0;
     188           0 :           log_printf ("%s\n", line);
     189             :         }
     190             :       else
     191           0 :         log_info ("%s\n", line);
     192           0 :       line = s + 1;
     193             :     }
     194           0 :   n = strlen (line);
     195           0 :   if (n)
     196             :     {
     197           0 :       if (ctx->linelen + n + 1 >= ctx->linesize)
     198             :         {
     199             :           char *tmp;
     200             :           size_t newsize;
     201             : 
     202           0 :           newsize = ctx->linesize + ((n + 255) & ~255) + 1;
     203           0 :           tmp = (ctx->line ? xtryrealloc (ctx->line, newsize)
     204             :                            : xtrymalloc (newsize));
     205           0 :           if (!tmp)
     206             :             {
     207           0 :               log_error (_("error printing log line: %s\n"), strerror (errno));
     208           0 :               return;
     209             :             }
     210           0 :           ctx->line = tmp;
     211           0 :           ctx->linesize = newsize;
     212             :         }
     213           0 :       memcpy (ctx->line + ctx->linelen, line, n);
     214           0 :       ctx->linelen += n;
     215           0 :       ctx->line[ctx->linelen] = 0;
     216             :     }
     217             : }
     218             : 
     219             : 
     220             : /* Read data from the log stream.  Returns true if the log stream
     221             :    indicated EOF or error.  */
     222             : static int
     223           0 : read_log_data (struct wrapper_context_s *ctx)
     224             : {
     225             :   int n;
     226             :   char line[256];
     227             : 
     228             :   /* We must use the npth_read function for pipes, always.  */
     229             :   do
     230           0 :     n = npth_read (ctx->log_fd, line, sizeof line - 1);
     231           0 :   while (n < 0 && errno == EINTR);
     232             : 
     233           0 :   if (n <= 0) /* EOF or error. */
     234             :     {
     235           0 :       if (n < 0)
     236           0 :         log_error (_("error reading log from ldap wrapper %d: %s\n"),
     237           0 :                    (int)ctx->pid, strerror (errno));
     238           0 :       print_log_line (ctx, NULL);
     239           0 :       SAFE_CLOSE (ctx->log_fd);
     240           0 :       return 1;
     241             :     }
     242             : 
     243           0 :   line[n] = 0;
     244           0 :   print_log_line (ctx, line);
     245           0 :   if (ctx->stamp != (time_t)(-1))
     246           0 :     ctx->stamp = time (NULL);
     247           0 :   return 0;
     248             : }
     249             : 
     250             : 
     251             : /* This function is run by a separate thread to maintain the list of
     252             :    wrappers and to log error messages from these wrappers.  */
     253             : void *
     254           0 : ldap_wrapper_thread (void *dummy)
     255             : {
     256             :   int nfds;
     257             :   struct wrapper_context_s *ctx;
     258             :   struct wrapper_context_s *ctx_prev;
     259             :   struct timespec abstime;
     260             :   struct timespec curtime;
     261             :   struct timespec timeout;
     262             :   fd_set fdset;
     263             :   int ret;
     264             :   time_t exptime;
     265             : 
     266             :   (void)dummy;
     267             : 
     268           0 :   npth_clock_gettime (&abstime);
     269           0 :   abstime.tv_sec += TIMERTICK_INTERVAL;
     270             : 
     271             :   for (;;)
     272             :     {
     273           0 :       int any_action = 0;
     274             : 
     275           0 :       npth_clock_gettime (&curtime);
     276           0 :       if (!(npth_timercmp (&curtime, &abstime, <)))
     277             :         {
     278             :           /* Inactivity is checked below.  Nothing else to do.  */
     279           0 :           npth_clock_gettime (&abstime);
     280           0 :           abstime.tv_sec += TIMERTICK_INTERVAL;
     281             :         }
     282           0 :       npth_timersub (&abstime, &curtime, &timeout);
     283             : 
     284           0 :       FD_ZERO (&fdset);
     285           0 :       nfds = -1;
     286           0 :       for (ctx = wrapper_list; ctx; ctx = ctx->next)
     287             :         {
     288           0 :           if (ctx->log_fd != -1)
     289             :             {
     290           0 :               FD_SET (ctx->log_fd, &fdset);
     291           0 :               if (ctx->log_fd > nfds)
     292           0 :                 nfds = ctx->log_fd;
     293             :             }
     294             :         }
     295           0 :       nfds++;
     296             : 
     297             :       /* FIXME: For Windows, we have to use a reader thread on the
     298             :          pipe that signals an event (and a npth_select_ev variant).  */
     299           0 :       ret = npth_pselect (nfds + 1, &fdset, NULL, NULL, &timeout, NULL);
     300           0 :       if (ret == -1)
     301             :         {
     302           0 :           if (errno != EINTR)
     303             :             {
     304           0 :               log_error (_("npth_select failed: %s - waiting 1s\n"),
     305           0 :                          strerror (errno));
     306           0 :               npth_sleep (1);
     307             :             }
     308           0 :           continue;
     309             :         }
     310             : 
     311             :       /* All timestamps before exptime should be considered expired.  */
     312           0 :       exptime = time (NULL);
     313           0 :       if (exptime > INACTIVITY_TIMEOUT)
     314           0 :         exptime -= INACTIVITY_TIMEOUT;
     315             : 
     316             :       /* Note that there is no need to lock the list because we always
     317             :          add entries at the head (with a pending event status) and
     318             :          thus traversing the list will even work if we have a context
     319             :          switch in waitpid (which should anyway only happen with Pth's
     320             :          hard system call mapping).  */
     321           0 :       for (ctx = wrapper_list; ctx; ctx = ctx->next)
     322             :         {
     323             :           /* Check whether there is any logging to be done. */
     324           0 :           if (nfds && ctx->log_fd != -1 && FD_ISSET (ctx->log_fd, &fdset))
     325             :             {
     326           0 :               if (read_log_data (ctx))
     327             :                 {
     328           0 :                   SAFE_CLOSE (ctx->log_fd);
     329           0 :                   any_action = 1;
     330             :                 }
     331             :             }
     332             : 
     333             :           /* Check whether the process is still running.  */
     334           0 :           if (ctx->pid != (pid_t)(-1))
     335             :             {
     336             :               gpg_error_t err;
     337             :               int status;
     338             : 
     339           0 :               err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
     340             :                                         &status);
     341           0 :               if (!err)
     342             :                 {
     343           0 :                   log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
     344           0 :                   ctx->ready = 1;
     345           0 :                   gnupg_release_process (ctx->pid);
     346           0 :                   ctx->pid = (pid_t)(-1);
     347           0 :                   any_action = 1;
     348             :                 }
     349           0 :               else if (gpg_err_code (err) == GPG_ERR_GENERAL)
     350             :                 {
     351           0 :                   if (status == 10)
     352           0 :                     log_info (_("ldap wrapper %d ready: timeout\n"),
     353             :                               (int)ctx->pid);
     354             :                   else
     355           0 :                     log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
     356             :                               (int)ctx->pid, status);
     357           0 :                   ctx->ready = 1;
     358           0 :                   gnupg_release_process (ctx->pid);
     359           0 :                   ctx->pid = (pid_t)(-1);
     360           0 :                   any_action = 1;
     361             :                 }
     362           0 :               else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
     363             :                 {
     364           0 :                   log_error (_("waiting for ldap wrapper %d failed: %s\n"),
     365             :                              (int)ctx->pid, gpg_strerror (err));
     366           0 :                   any_action = 1;
     367             :                 }
     368             :             }
     369             : 
     370             :           /* Check whether we should terminate the process. */
     371           0 :           if (ctx->pid != (pid_t)(-1)
     372           0 :               && ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
     373             :             {
     374           0 :               gnupg_kill_process (ctx->pid);
     375           0 :               ctx->stamp = (time_t)(-1);
     376           0 :               log_info (_("ldap wrapper %d stalled - killing\n"),
     377             :                         (int)ctx->pid);
     378             :               /* We need to close the log fd because the cleanup loop
     379             :                  waits for it.  */
     380           0 :               SAFE_CLOSE (ctx->log_fd);
     381           0 :               any_action = 1;
     382             :             }
     383             :         }
     384             : 
     385             :       /* If something has been printed to the log file or we got an
     386             :          EOF from a wrapper, we now print the list of active
     387             :          wrappers.  */
     388           0 :       if (any_action && DBG_LOOKUP)
     389             :         {
     390           0 :           log_info ("ldap worker stati:\n");
     391           0 :           for (ctx = wrapper_list; ctx; ctx = ctx->next)
     392           0 :             log_info ("  c=%p pid=%d/%d rdr=%p ctrl=%p/%d la=%lu rdy=%d\n",
     393             :                       ctx,
     394             :                       (int)ctx->pid, (int)ctx->printable_pid,
     395             :                       ctx->reader,
     396           0 :                       ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
     397           0 :                       (unsigned long)ctx->stamp, ctx->ready);
     398             :         }
     399             : 
     400             : 
     401             :       /* Use a separate loop to check whether ready marked wrappers
     402             :          may be removed.  We may only do so if the ksba reader object
     403             :          is not anymore in use or we are in shutdown state.  */
     404             :      again:
     405           0 :       for (ctx_prev=NULL, ctx=wrapper_list; ctx; ctx_prev=ctx, ctx=ctx->next)
     406           0 :         if (ctx->ready
     407           0 :             && ((ctx->log_fd == -1 && !ctx->reader) || shutting_down))
     408             :           {
     409           0 :             if (ctx_prev)
     410           0 :               ctx_prev->next = ctx->next;
     411             :             else
     412           0 :               wrapper_list = ctx->next;
     413           0 :             destroy_wrapper (ctx);
     414             :             /* We need to restart because destroy_wrapper might have
     415             :                done a context switch. */
     416           0 :             goto again;
     417             :           }
     418           0 :     }
     419             :   /*NOTREACHED*/
     420             :   return NULL; /* Make the compiler happy.  */
     421             : }
     422             : 
     423             : 
     424             : 
     425             : /* Start the reaper thread for the ldap wrapper.  */
     426             : void
     427           0 : ldap_wrapper_launch_thread (void)
     428             : {
     429             :   static int done;
     430             :   npth_attr_t tattr;
     431             :   npth_t thread;
     432             :   int err;
     433             : 
     434           0 :   if (done)
     435           0 :     return;
     436           0 :   done = 1;
     437             : 
     438           0 :   npth_attr_init (&tattr);
     439           0 :   npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
     440             : 
     441           0 :   err = npth_create (&thread, &tattr, ldap_wrapper_thread, NULL);
     442           0 :   if (err)
     443             :     {
     444           0 :       log_error (_("error spawning ldap wrapper reaper thread: %s\n"),
     445             :                  strerror (err) );
     446           0 :       dirmngr_exit (1);
     447             :     }
     448           0 :   npth_setname_np (thread, "ldap-reaper");
     449           0 :   npth_attr_destroy (&tattr);
     450             : }
     451             : 
     452             : 
     453             : 
     454             : 
     455             : 
     456             : /* Wait until all ldap wrappers have terminated.  We assume that the
     457             :    kill has already been sent to all of them.  */
     458             : void
     459           0 : ldap_wrapper_wait_connections ()
     460             : {
     461           0 :   shutting_down = 1;
     462             :   /* FIXME: This is a busy wait.  */
     463           0 :   while (wrapper_list)
     464           0 :     npth_usleep (200);
     465           0 : }
     466             : 
     467             : 
     468             : /* This function is to be used to release a context associated with the
     469             :    given reader object. */
     470             : void
     471           0 : ldap_wrapper_release_context (ksba_reader_t reader)
     472             : {
     473             :   struct wrapper_context_s *ctx;
     474             : 
     475           0 :   if (!reader )
     476           0 :     return;
     477             : 
     478           0 :   for (ctx=wrapper_list; ctx; ctx=ctx->next)
     479           0 :     if (ctx->reader == reader)
     480             :       {
     481           0 :         if (DBG_LOOKUP)
     482           0 :           log_info ("releasing ldap worker c=%p pid=%d/%d rdr=%p ctrl=%p/%d\n",
     483             :                     ctx,
     484             :                     (int)ctx->pid, (int)ctx->printable_pid,
     485             :                     ctx->reader,
     486           0 :                     ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
     487             : 
     488           0 :         ctx->reader = NULL;
     489           0 :         SAFE_CLOSE (ctx->fd);
     490           0 :         if (ctx->ctrl)
     491             :           {
     492           0 :             ctx->ctrl->refcount--;
     493           0 :             ctx->ctrl = NULL;
     494             :           }
     495           0 :         if (ctx->fd_error)
     496           0 :           log_info (_("reading from ldap wrapper %d failed: %s\n"),
     497             :                     ctx->printable_pid, gpg_strerror (ctx->fd_error));
     498           0 :         break;
     499             :       }
     500             : }
     501             : 
     502             : /* Cleanup all resources held by the connection associated with
     503             :    CTRL.  This is used after a cancel to kill running wrappers.  */
     504             : void
     505           0 : ldap_wrapper_connection_cleanup (ctrl_t ctrl)
     506             : {
     507             :   struct wrapper_context_s *ctx;
     508             : 
     509           0 :   for (ctx=wrapper_list; ctx; ctx=ctx->next)
     510           0 :     if (ctx->ctrl && ctx->ctrl == ctrl)
     511             :       {
     512           0 :         ctx->ctrl->refcount--;
     513           0 :         ctx->ctrl = NULL;
     514           0 :         if (ctx->pid != (pid_t)(-1))
     515           0 :           gnupg_kill_process (ctx->pid);
     516           0 :         if (ctx->fd_error)
     517           0 :           log_info (_("reading from ldap wrapper %d failed: %s\n"),
     518             :                     ctx->printable_pid, gpg_strerror (ctx->fd_error));
     519             :       }
     520           0 : }
     521             : 
     522             : 
     523             : /* This is the callback used by the ldap wrapper to feed the ksba
     524             :    reader with the wrappers stdout.  See the description of
     525             :    ksba_reader_set_cb for details.  */
     526             : static int
     527           0 : reader_callback (void *cb_value, char *buffer, size_t count,  size_t *nread)
     528             : {
     529           0 :   struct wrapper_context_s *ctx = cb_value;
     530           0 :   size_t nleft = count;
     531             :   int nfds;
     532             :   struct timespec abstime;
     533             :   struct timespec curtime;
     534             :   struct timespec timeout;
     535             :   int saved_errno;
     536             :   fd_set fdset, read_fdset;
     537             :   int ret;
     538             : 
     539             :   /* FIXME: We might want to add some internal buffering because the
     540             :      ksba code does not do any buffering for itself (because a ksba
     541             :      reader may be detached from another stream to read other data and
     542             :      the it would be cumbersome to get back already buffered
     543             :      stuff).  */
     544             : 
     545           0 :   if (!buffer && !count && !nread)
     546           0 :     return -1; /* Rewind is not supported. */
     547             : 
     548             :   /* If we ever encountered a read error don't allow to continue and
     549             :      possible overwrite the last error cause.  Bail out also if the
     550             :      file descriptor has been closed. */
     551           0 :   if (ctx->fd_error || ctx->fd == -1)
     552             :     {
     553           0 :       *nread = 0;
     554           0 :       return -1;
     555             :     }
     556             : 
     557           0 :   FD_ZERO (&fdset);
     558           0 :   FD_SET (ctx->fd, &fdset);
     559           0 :   nfds = ctx->fd + 1;
     560             : 
     561           0 :   npth_clock_gettime (&abstime);
     562           0 :   abstime.tv_sec += TIMERTICK_INTERVAL;
     563             : 
     564           0 :   while (nleft > 0)
     565             :     {
     566             :       int n;
     567             :       gpg_error_t err;
     568             : 
     569           0 :       npth_clock_gettime (&curtime);
     570           0 :       if (!(npth_timercmp (&curtime, &abstime, <)))
     571             :         {
     572           0 :           err = dirmngr_tick (ctx->ctrl);
     573           0 :           if (err)
     574             :             {
     575           0 :               ctx->fd_error = err;
     576           0 :               SAFE_CLOSE (ctx->fd);
     577           0 :               return -1;
     578             :             }
     579           0 :           npth_clock_gettime (&abstime);
     580           0 :           abstime.tv_sec += TIMERTICK_INTERVAL;
     581             :         }
     582           0 :       npth_timersub (&abstime, &curtime, &timeout);
     583             : 
     584           0 :       read_fdset = fdset;
     585           0 :       ret = npth_pselect (nfds, &read_fdset, NULL, NULL, &timeout, NULL);
     586           0 :       saved_errno = errno;
     587             : 
     588           0 :       if (ret == -1 && saved_errno != EINTR)
     589             :         {
     590           0 :           ctx->fd_error = gpg_error_from_errno (errno);
     591           0 :           SAFE_CLOSE (ctx->fd);
     592           0 :           return -1;
     593             :         }
     594           0 :       if (ret <= 0)
     595             :         /* Timeout.  Will be handled when calculating the next timeout.  */
     596           0 :         continue;
     597             : 
     598             :       /* This should not block now that select returned with a file
     599             :          descriptor.  So it shouldn't be necessary to use npth_read
     600             :          (and it is slightly dangerous in the sense that a concurrent
     601             :          thread might (accidentially?) change the status of ctx->fd
     602             :          before we read.  FIXME: Set ctx->fd to nonblocking?  */
     603           0 :       n = read (ctx->fd, buffer, nleft);
     604           0 :       if (n < 0)
     605             :         {
     606           0 :           ctx->fd_error = gpg_error_from_errno (errno);
     607           0 :           SAFE_CLOSE (ctx->fd);
     608           0 :           return -1;
     609             :         }
     610           0 :       else if (!n)
     611             :         {
     612           0 :           if (nleft == count)
     613           0 :             return -1; /* EOF. */
     614           0 :           break;
     615             :         }
     616           0 :       nleft -= n;
     617           0 :       buffer += n;
     618           0 :       if (n > 0 && ctx->stamp != (time_t)(-1))
     619           0 :         ctx->stamp = time (NULL);
     620             :     }
     621           0 :   *nread = count - nleft;
     622             : 
     623           0 :   return 0;
     624             : }
     625             : 
     626             : /* Fork and exec the LDAP wrapper and return a new libksba reader
     627             :    object at READER.  ARGV is a NULL terminated list of arguments for
     628             :    the wrapper.  The function returns 0 on success or an error code.
     629             : 
     630             :    Special hack to avoid passing a password through the command line
     631             :    which is globally visible: If the first element of ARGV is "--pass"
     632             :    it will be removed and instead the environment variable
     633             :    DIRMNGR_LDAP_PASS will be set to the next value of ARGV.  On modern
     634             :    OSes the environment is not visible to other users.  For those old
     635             :    systems where it can't be avoided, we don't want to go into the
     636             :    hassle of passing the password via stdin; it's just too complicated
     637             :    and an LDAP password used for public directory lookups should not
     638             :    be that confidential.  */
     639             : gpg_error_t
     640           0 : ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
     641             : {
     642             :   gpg_error_t err;
     643             :   pid_t pid;
     644             :   struct wrapper_context_s *ctx;
     645             :   int i;
     646             :   int j;
     647             :   const char **arg_list;
     648             :   const char *pgmname;
     649             :   int outpipe[2], errpipe[2];
     650             : 
     651             :   /* It would be too simple to connect stderr just to our logging
     652             :      stream.  The problem is that if we are running multi-threaded
     653             :      everything gets intermixed.  Clearly we don't want this.  So the
     654             :      only viable solutions are either to have another thread
     655             :      responsible for logging the messages or to add an option to the
     656             :      wrapper module to do the logging on its own.  Given that we anyway
     657             :      need a way to rip the child process and this is best done using a
     658             :      general ripping thread, that thread can do the logging too. */
     659             : 
     660           0 :   *reader = NULL;
     661             : 
     662             :   /* Files: We need to prepare stdin and stdout.  We get stderr from
     663             :      the function.  */
     664           0 :   if (!opt.ldap_wrapper_program || !*opt.ldap_wrapper_program)
     665           0 :     pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR_LDAP);
     666             :   else
     667           0 :     pgmname = opt.ldap_wrapper_program;
     668             : 
     669             :   /* Create command line argument array.  */
     670           0 :   for (i = 0; argv[i]; i++)
     671             :     ;
     672           0 :   arg_list = xtrycalloc (i + 2, sizeof *arg_list);
     673           0 :   if (!arg_list)
     674             :     {
     675           0 :       err = gpg_error_from_syserror ();
     676           0 :       log_error (_("error allocating memory: %s\n"), strerror (errno));
     677           0 :       return err;
     678             :     }
     679           0 :   for (i = j = 0; argv[i]; i++, j++)
     680           0 :     if (!i && argv[i + 1] && !strcmp (*argv, "--pass"))
     681             :       {
     682           0 :         arg_list[j] = "--env-pass";
     683           0 :         setenv ("DIRMNGR_LDAP_PASS", argv[1], 1);
     684           0 :         i++;
     685             :       }
     686             :     else
     687           0 :       arg_list[j] = (char*) argv[i];
     688             : 
     689           0 :   ctx = xtrycalloc (1, sizeof *ctx);
     690           0 :   if (!ctx)
     691             :     {
     692           0 :       err = gpg_error_from_syserror ();
     693           0 :       log_error (_("error allocating memory: %s\n"), strerror (errno));
     694           0 :       xfree (arg_list);
     695           0 :       return err;
     696             :     }
     697             : 
     698           0 :   err = gnupg_create_inbound_pipe (outpipe);
     699           0 :   if (!err)
     700             :     {
     701           0 :       err = gnupg_create_inbound_pipe (errpipe);
     702           0 :       if (err)
     703             :         {
     704           0 :           close (outpipe[0]);
     705           0 :           close (outpipe[1]);
     706             :         }
     707             :     }
     708           0 :   if (err)
     709             :     {
     710           0 :       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
     711           0 :       xfree (arg_list);
     712           0 :       xfree (ctx);
     713           0 :       return err;
     714             :     }
     715             : 
     716           0 :   err = gnupg_spawn_process_fd (pgmname, arg_list,
     717             :                                 -1, outpipe[1], errpipe[1], &pid);
     718           0 :   xfree (arg_list);
     719           0 :   close (outpipe[1]);
     720           0 :   close (errpipe[1]);
     721           0 :   if (err)
     722             :     {
     723           0 :       close (outpipe[0]);
     724           0 :       close (errpipe[0]);
     725           0 :       xfree (ctx);
     726           0 :       return err;
     727             :     }
     728             : 
     729           0 :   ctx->pid = pid;
     730           0 :   ctx->printable_pid = (int) pid;
     731           0 :   ctx->fd = outpipe[0];
     732           0 :   ctx->log_fd = errpipe[0];
     733           0 :   ctx->ctrl = ctrl;
     734           0 :   ctrl->refcount++;
     735           0 :   ctx->stamp = time (NULL);
     736             : 
     737           0 :   err = ksba_reader_new (reader);
     738           0 :   if (!err)
     739           0 :     err = ksba_reader_set_cb (*reader, reader_callback, ctx);
     740           0 :   if (err)
     741             :     {
     742           0 :       log_error (_("error initializing reader object: %s\n"),
     743             :                  gpg_strerror (err));
     744           0 :       destroy_wrapper (ctx);
     745           0 :       ksba_reader_release (*reader);
     746           0 :       *reader = NULL;
     747           0 :       return err;
     748             :     }
     749             : 
     750             :   /* Hook the context into our list of running wrappers.  */
     751           0 :   ctx->reader = *reader;
     752           0 :   ctx->next = wrapper_list;
     753           0 :   wrapper_list = ctx;
     754           0 :   if (opt.verbose)
     755           0 :     log_info ("ldap wrapper %d started (reader %p)\n",
     756             :               (int)ctx->pid, ctx->reader);
     757             : 
     758             :   /* Need to wait for the first byte so we are able to detect an empty
     759             :      output and not let the consumer see an EOF without further error
     760             :      indications.  The CRL loading logic assumes that after return
     761             :      from this function, a failed search (e.g. host not found ) is
     762             :      indicated right away. */
     763             :   {
     764             :     unsigned char c;
     765             : 
     766           0 :     err = read_buffer (*reader, &c, 1);
     767           0 :     if (err)
     768             :       {
     769           0 :         ldap_wrapper_release_context (*reader);
     770           0 :         ksba_reader_release (*reader);
     771           0 :         *reader = NULL;
     772           0 :         if (gpg_err_code (err) == GPG_ERR_EOF)
     773           0 :           return gpg_error (GPG_ERR_NO_DATA);
     774             :         else
     775           0 :           return err;
     776             :       }
     777           0 :     ksba_reader_unread (*reader, &c, 1);
     778             :   }
     779             : 
     780           0 :   return 0;
     781             : }

Generated by: LCOV version 1.11