Imported Upstream version 2.2.7
[platform/upstream/gpg2.git] / dirmngr / ldap-wrapper.c
1 /* ldap-wrapper.c - LDAP access via a wrapper process
2  * Copyright (C) 2004, 2005, 2007, 2008, 2018 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 <https://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 GNU Pth.  Since 2.1 we use nPth
26  *    instead of GNU Pth which does not have this problem anymore
27  *    because it will use pthreads if the platform supports it.  Thus
28  *    this was a historical reasons.
29  *
30  * 2. It is huge library in particular if TLS comes into play.  So
31  *    problems with unfreed memory might turn up and we don't want
32  *    this in a long running daemon.
33  *
34  * 3. There is no easy way for timeouts. In particular the timeout
35  *    value does not work for DNS lookups (well, this is usual) and it
36  *    seems not to work while loading a large attribute like a
37  *    CRL. Having a separate process allows us to either tell the
38  *    process to commit suicide or have our own housekepping function
39  *    kill it after some time.  The latter also allows proper
40  *    cancellation of a query at any point of time.
41  *
42  * 4. Given that we are going out to the network and usually get back
43  *    a long response, the fork/exec overhead is acceptable.
44  *
45  * Note that under WindowsCE the number of processes is strongly
46  * limited (32 processes including the kernel processes) and thus we
47  * don't use the process approach but implement a different wrapper in
48  * ldap-wrapper-ce.c.
49  */
50
51
52 #include <config.h>
53
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <errno.h>
58 #include <unistd.h>
59 #include <fcntl.h>
60 #include <time.h>
61 #include <npth.h>
62
63 #include "dirmngr.h"
64 #include "../common/exechelp.h"
65 #include "misc.h"
66 #include "ldap-wrapper.h"
67
68
69 #ifdef HAVE_W32_SYSTEM
70 #define setenv(a,b,c) SetEnvironmentVariable ((a),(b))
71 #else
72 #define pth_close(fd) close(fd)
73 #endif
74
75 #ifndef USE_LDAPWRAPPER
76 # error This module is not expected to be build.
77 #endif
78
79 /* In case sysconf does not return a value we need to have a limit. */
80 #ifdef _POSIX_OPEN_MAX
81 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
82 #else
83 #define MAX_OPEN_FDS 20
84 #endif
85
86 #define INACTIVITY_TIMEOUT (opt.ldaptimeout + 60*5)  /* seconds */
87
88 #define TIMERTICK_INTERVAL 2
89
90 /* To keep track of the LDAP wrapper state we use this structure.  */
91 struct wrapper_context_s
92 {
93   struct wrapper_context_s *next;
94
95   pid_t pid;           /* The pid of the wrapper process. */
96   int printable_pid;   /* Helper to print diagnostics after the process has
97                         * been cleaned up. */
98   estream_t fp;        /* Connected with stdout of the ldap wrapper.  */
99   gpg_error_t fp_err;  /* Set to the gpg_error of the last read error
100                         * if any.  */
101   estream_t log_fp;    /* Connected with stderr of the ldap wrapper.  */
102   ctrl_t ctrl;         /* Connection data. */
103   int ready;           /* Internally used to mark to be removed contexts. */
104   ksba_reader_t reader;/* The ksba reader object or NULL. */
105   char *line;          /* Used to print the log lines (malloced). */
106   size_t linesize;     /* Allocated size of LINE.  */
107   size_t linelen;      /* Use size of LINE.  */
108   time_t stamp;        /* The last time we noticed ativity.  */
109   int reaper_idx;      /* Private to ldap_wrapper_thread.   */
110 };
111
112
113
114 /* We keep a global list of spawned wrapper process.  A separate
115  * thread makes use of this list to log error messages and to watch
116  * out for finished processes.  Access to list is protected by a
117  * mutex.  The condition variable is used to wakeup the reaper
118  * thread.  */
119 static struct wrapper_context_s *reaper_list;
120 static npth_mutex_t reaper_list_mutex = NPTH_MUTEX_INITIALIZER;
121 static npth_cond_t  reaper_run_cond  = NPTH_COND_INITIALIZER;
122
123 /* We need to know whether we are shutting down the process.  */
124 static int shutting_down;
125
126
127
128 /* Close the estream fp and set it to NULL.  */
129 #define SAFE_CLOSE(fp) \
130   do { estream_t _fp = fp; es_fclose (_fp); fp = NULL; } while (0)
131
132
133
134 \f
135
136 static void
137 lock_reaper_list (void)
138 {
139   if (npth_mutex_lock (&reaper_list_mutex))
140     log_fatal ("%s: failed to acquire mutex: %s\n", __func__,
141                gpg_strerror (gpg_error_from_syserror ()));
142 }
143
144
145 static void
146 unlock_reaper_list (void)
147 {
148   if (npth_mutex_unlock (&reaper_list_mutex))
149     log_fatal ("%s: failed to release mutex: %s\n", __func__,
150                gpg_strerror (gpg_error_from_syserror ()));
151 }
152
153
154
155 /* Read a fixed amount of data from READER into BUFFER.  */
156 static gpg_error_t
157 read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
158 {
159   gpg_error_t err;
160   size_t nread;
161
162   while (count)
163     {
164       err = ksba_reader_read (reader, buffer, count, &nread);
165       if (err)
166         return err;
167       buffer += nread;
168       count -= nread;
169     }
170   return 0;
171 }
172
173
174 /* Release the wrapper context and kill a running wrapper process. */
175 static void
176 destroy_wrapper (struct wrapper_context_s *ctx)
177 {
178   if (ctx->pid != (pid_t)(-1))
179     {
180       gnupg_kill_process (ctx->pid);
181       gnupg_release_process (ctx->pid);
182     }
183   ksba_reader_release (ctx->reader);
184   SAFE_CLOSE (ctx->fp);
185   SAFE_CLOSE (ctx->log_fp);
186   xfree (ctx->line);
187   xfree (ctx);
188 }
189
190
191 /* Print the content of LINE to thye log stream but make sure to only
192    print complete lines.  Using NULL for LINE will flush any pending
193    output.  LINE may be modified by this function. */
194 static void
195 print_log_line (struct wrapper_context_s *ctx, char *line)
196 {
197   char *s;
198   size_t n;
199
200   if (!line)
201     {
202       if (ctx->line && ctx->linelen)
203         {
204
205           log_info ("%s\n", ctx->line);
206           ctx->linelen = 0;
207         }
208       return;
209     }
210
211   while ((s = strchr (line, '\n')))
212     {
213       *s = 0;
214       if (ctx->line && ctx->linelen)
215         {
216           log_info ("%s", ctx->line);
217           ctx->linelen = 0;
218           log_printf ("%s\n", line);
219         }
220       else
221         log_info ("%s\n", line);
222       line = s + 1;
223     }
224   n = strlen (line);
225   if (n)
226     {
227       if (ctx->linelen + n + 1 >= ctx->linesize)
228         {
229           char *tmp;
230           size_t newsize;
231
232           newsize = ctx->linesize + ((n + 255) & ~255) + 1;
233           tmp = (ctx->line ? xtryrealloc (ctx->line, newsize)
234                            : xtrymalloc (newsize));
235           if (!tmp)
236             {
237               log_error (_("error printing log line: %s\n"), strerror (errno));
238               return;
239             }
240           ctx->line = tmp;
241           ctx->linesize = newsize;
242         }
243       memcpy (ctx->line + ctx->linelen, line, n);
244       ctx->linelen += n;
245       ctx->line[ctx->linelen] = 0;
246     }
247 }
248
249
250 /* Read data from the log stream.  Returns true if the log stream
251  * indicated EOF or error.  */
252 static int
253 read_log_data (struct wrapper_context_s *ctx)
254 {
255   int rc;
256   size_t n;
257   char line[256];
258
259   rc = es_read (ctx->log_fp, line, sizeof line - 1, &n);
260   if (rc || !n)  /* Error or EOF.  */
261     {
262       if (rc)
263         {
264           gpg_error_t err = gpg_error_from_syserror ();
265           if (gpg_err_code (err) == GPG_ERR_EAGAIN)
266             return 0;
267           log_error (_("error reading log from ldap wrapper %d: %s\n"),
268                      (int)ctx->pid, gpg_strerror (err));
269         }
270       print_log_line (ctx, NULL);  /* Flush.  */
271       SAFE_CLOSE (ctx->log_fp);
272       return 1;
273     }
274
275   line[n] = 0;
276   print_log_line (ctx, line);
277   if (ctx->stamp != (time_t)(-1))
278     ctx->stamp = time (NULL);
279   return 0;
280 }
281
282
283 /* This function is run by a separate thread to maintain the list of
284    wrappers and to log error messages from these wrappers.  */
285 void *
286 ldap_reaper_thread (void *dummy)
287 {
288   gpg_error_t err;
289   struct wrapper_context_s *ctx;
290   struct wrapper_context_s *ctx_prev;
291   struct timespec abstime;
292   struct timespec curtime;
293   struct timespec timeout;
294   int millisecs;
295   gpgrt_poll_t *fparray = NULL;
296   int fparraysize = 0;
297   int count, i;
298   int ret;
299   time_t exptime;
300
301   (void)dummy;
302
303   npth_clock_gettime (&abstime);
304   abstime.tv_sec += TIMERTICK_INTERVAL;
305
306   for (;;)
307     {
308       int any_action = 0;
309
310       /* Wait until we are needed and then setup the FPARRAY.  */
311       /* Note: There is one unlock inside the block!  */
312       lock_reaper_list ();
313       {
314         while (!reaper_list && !shutting_down)
315           {
316             if (npth_cond_wait (&reaper_run_cond, &reaper_list_mutex))
317               log_error ("ldap-reaper: waiting on condition failed: %s\n",
318                          gpg_strerror (gpg_error_from_syserror ()));
319           }
320
321         for (count = 0, ctx = reaper_list; ctx; ctx = ctx->next)
322           if (ctx->log_fp)
323             count++;
324         if (count > fparraysize || !fparray)
325           {
326             /* Need to realloc the array.  We simply discard it and
327              * replace it by a new one.  */
328             xfree (fparray);
329             fparray = xtrycalloc (count? count : 1, sizeof *fparray);
330             if (!fparray)
331               {
332                 err = gpg_error_from_syserror ();
333                 log_error ("ldap-reaper can't allocate poll array: %s"
334                            " - waiting 1s\n", gpg_strerror (err));
335                 /* Note: Here we unlock and continue! */
336                 unlock_reaper_list ();
337                 npth_sleep (1);
338                 continue;
339             }
340             fparraysize = count;
341           }
342         for (count = 0, ctx = reaper_list; ctx; ctx = ctx->next)
343           {
344             if (ctx->log_fp)
345               {
346                 log_assert (count < fparraysize);
347                 fparray[count].stream = ctx->log_fp;
348                 fparray[count].want_read = 1;
349                 fparray[count].ignore = 0;
350                 ctx->reaper_idx = count;
351                 count++;
352               }
353             else
354               {
355                 ctx->reaper_idx = -1;
356                 fparray[count].ignore = 1;
357               }
358           }
359         for (i=count; i < fparraysize; i++)
360           fparray[i].ignore = 1;
361       }
362       unlock_reaper_list (); /* Note the one unlock inside the block.  */
363
364       /* Compute the next timeout.  */
365       npth_clock_gettime (&curtime);
366       if (!(npth_timercmp (&curtime, &abstime, <)))
367         {
368           /* Inactivity is checked below.  Nothing else to do.  */
369           npth_clock_gettime (&abstime);
370           abstime.tv_sec += TIMERTICK_INTERVAL;
371         }
372       npth_timersub (&abstime, &curtime, &timeout);
373       millisecs = timeout.tv_sec * 1000;
374       millisecs += timeout.tv_nsec / 1000000;
375       if (millisecs < 0)
376         millisecs = 1;
377
378       if (DBG_EXTPROG)
379         {
380           log_debug ("ldap-reaper: next run (count=%d size=%d, timeout=%d)\n",
381                      count, fparraysize, millisecs);
382           for (count=0; count < fparraysize; count++)
383             if (!fparray[count].ignore)
384               log_debug ("ldap-reaper: fp[%d] stream=%p want=%d\n",
385                          count, fparray[count].stream,fparray[count].want_read);
386         }
387
388       ret = es_poll (fparray, fparraysize, millisecs);
389       if (ret < 0)
390         {
391           err = gpg_error_from_syserror ();
392           log_error ("ldap-reaper failed to poll: %s"
393                      " - waiting 1s\n", gpg_strerror (err));
394           /* In case the reason for the error is a too large array, we
395            * release it so that it will be allocated smaller in the
396            * next round.  */
397           xfree (fparray);
398           fparray = NULL;
399           fparraysize = 0;
400           npth_sleep (1);
401           continue;
402         }
403
404       if (DBG_EXTPROG)
405         {
406           for (count=0; count < fparraysize; count++)
407             if (!fparray[count].ignore)
408               log_debug ("ldap-reaper: fp[%d] stream=%p r=%d %c%c%c%c%c%c%c\n",
409                          count, fparray[count].stream, ret,
410                          fparray[count].got_read? 'r':'-',
411                          fparray[count].got_write?'w':'-',
412                          fparray[count].got_oob?  'o':'-',
413                          fparray[count].got_rdhup?'H':'-',
414                          fparray[count].got_err?  'e':'-',
415                          fparray[count].got_hup?  'h':'-',
416                          fparray[count].got_nval? 'n':'-');
417         }
418
419       /* All timestamps before exptime should be considered expired.  */
420       exptime = time (NULL);
421       if (exptime > INACTIVITY_TIMEOUT)
422         exptime -= INACTIVITY_TIMEOUT;
423
424       lock_reaper_list ();
425       {
426         for (ctx = reaper_list; ctx; ctx = ctx->next)
427           {
428             /* Check whether there is any logging to be done.  We need
429              * to check FPARRAYSIZE because it can be 0 in case
430              * es_poll returned a timeout.  */
431             if (fparraysize && ctx->log_fp && ctx->reaper_idx >= 0)
432               {
433                 log_assert (ctx->reaper_idx < fparraysize);
434                 if (fparray[ctx->reaper_idx].got_read)
435                   {
436                     if (read_log_data (ctx))
437                       {
438                         SAFE_CLOSE (ctx->log_fp);
439                         any_action = 1;
440                       }
441                   }
442               }
443
444             /* Check whether the process is still running.  */
445             if (ctx->pid != (pid_t)(-1))
446               {
447                 int status;
448
449                 err = gnupg_wait_process ("[dirmngr_ldap]", ctx->pid, 0,
450                                           &status);
451                 if (!err)
452                   {
453                     if (DBG_EXTPROG)
454                       log_info (_("ldap wrapper %d ready"), (int)ctx->pid);
455                     ctx->ready = 1;
456                     gnupg_release_process (ctx->pid);
457                     ctx->pid = (pid_t)(-1);
458                     any_action = 1;
459                   }
460                 else if (gpg_err_code (err) == GPG_ERR_GENERAL)
461                   {
462                     if (status == 10)
463                       log_info (_("ldap wrapper %d ready: timeout\n"),
464                                 (int)ctx->pid);
465                     else
466                       log_info (_("ldap wrapper %d ready: exitcode=%d\n"),
467                                 (int)ctx->pid, status);
468                     ctx->ready = 1;
469                     gnupg_release_process (ctx->pid);
470                     ctx->pid = (pid_t)(-1);
471                     any_action = 1;
472                   }
473                 else if (gpg_err_code (err) != GPG_ERR_TIMEOUT)
474                   {
475                     log_error (_("waiting for ldap wrapper %d failed: %s\n"),
476                                (int)ctx->pid, gpg_strerror (err));
477                     any_action = 1;
478                   }
479               }
480
481             /* Check whether we should terminate the process. */
482             if (ctx->pid != (pid_t)(-1)
483                 && ctx->stamp != (time_t)(-1) && ctx->stamp < exptime)
484               {
485                 gnupg_kill_process (ctx->pid);
486                 ctx->stamp = (time_t)(-1);
487                 log_info (_("ldap wrapper %d stalled - killing\n"),
488                           (int)ctx->pid);
489                 /* We need to close the log stream because the cleanup
490                  * loop waits for it.  */
491                 SAFE_CLOSE (ctx->log_fp);
492                 any_action = 1;
493               }
494           }
495
496         /* If something has been printed to the log file or we got an
497          * EOF from a wrapper, we now print the list of active
498          * wrappers.  */
499         if (any_action && DBG_EXTPROG)
500           {
501             log_debug ("ldap worker stati:\n");
502             for (ctx = reaper_list; ctx; ctx = ctx->next)
503               log_debug ("  c=%p pid=%d/%d rdr=%p logfp=%p"
504                          " ctrl=%p/%d la=%lu rdy=%d\n",
505                          ctx,
506                          (int)ctx->pid, (int)ctx->printable_pid,
507                          ctx->reader, ctx->log_fp,
508                          ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0,
509                          (unsigned long)ctx->stamp, ctx->ready);
510           }
511
512         /* An extra loop to check whether ready marked wrappers may be
513          * removed.  We may only do so if the ksba reader object is
514          * not anymore in use or we are in shutdown state.  */
515       again:
516         for (ctx_prev=NULL, ctx=reaper_list; ctx; ctx_prev=ctx, ctx=ctx->next)
517           {
518             if (ctx->ready
519                 && ((!ctx->log_fp && !ctx->reader) || shutting_down))
520               {
521                 if (ctx_prev)
522                   ctx_prev->next = ctx->next;
523                 else
524                   reaper_list = ctx->next;
525                 destroy_wrapper (ctx);
526                 goto again;
527               }
528           }
529       }
530       unlock_reaper_list ();
531     }
532
533   /*NOTREACHED*/
534   return NULL; /* Make the compiler happy.  */
535 }
536
537
538
539 /* Start the reaper thread for the ldap wrapper.  */
540 void
541 ldap_reaper_launch_thread (void)
542 {
543   static int done;
544   npth_attr_t tattr;
545   npth_t thread;
546   int err;
547
548   if (done)
549     return;
550   done = 1;
551
552 #ifdef HAVE_W32_SYSTEM
553   /* Static init does not yet work in W32 nPth.  */
554   if (npth_cond_init (&reaper_run_cond, NULL))
555     log_fatal ("%s: failed to init condition variabale: %s\n",
556                __func__, gpg_strerror (gpg_error_from_syserror ()));
557 #endif
558
559   npth_attr_init (&tattr);
560   npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);
561
562   if (npth_create (&thread, &tattr, ldap_reaper_thread, NULL))
563     {
564       err = gpg_error_from_syserror ();
565       log_error ("error spawning ldap reaper reaper thread: %s\n",
566                  gpg_strerror (err) );
567       dirmngr_exit (1);
568     }
569   npth_setname_np (thread, "ldap-reaper");
570   npth_attr_destroy (&tattr);
571 }
572
573
574
575 /* Wait until all ldap wrappers have terminated.  We assume that the
576    kill has already been sent to all of them.  */
577 void
578 ldap_wrapper_wait_connections ()
579 {
580   lock_reaper_list ();
581   {
582     shutting_down = 1;
583     if (npth_cond_signal (&reaper_run_cond))
584       log_error ("%s: Ooops: signaling condition failed: %s\n",
585                  __func__, gpg_strerror (gpg_error_from_syserror ()));
586   }
587   unlock_reaper_list ();
588   while (reaper_list)
589     npth_usleep (200);
590 }
591
592
593 /* This function is to be used to release a context associated with the
594    given reader object. */
595 void
596 ldap_wrapper_release_context (ksba_reader_t reader)
597 {
598   struct wrapper_context_s *ctx;
599
600   if (!reader )
601     return;
602
603   lock_reaper_list ();
604   {
605     for (ctx=reaper_list; ctx; ctx=ctx->next)
606       if (ctx->reader == reader)
607         {
608           if (DBG_EXTPROG)
609             log_debug ("releasing ldap worker c=%p pid=%d/%d rdr=%p"
610                        " ctrl=%p/%d\n", ctx,
611                        (int)ctx->pid, (int)ctx->printable_pid,
612                        ctx->reader,
613                        ctx->ctrl, ctx->ctrl? ctx->ctrl->refcount:0);
614
615           ctx->reader = NULL;
616           SAFE_CLOSE (ctx->fp);
617           if (ctx->ctrl)
618             {
619               ctx->ctrl->refcount--;
620               ctx->ctrl = NULL;
621             }
622           if (ctx->fp_err)
623             log_info ("%s: reading from ldap wrapper %d failed: %s\n",
624                       __func__, ctx->printable_pid, gpg_strerror (ctx->fp_err));
625           break;
626         }
627   }
628   unlock_reaper_list ();
629 }
630
631
632 /* Cleanup all resources held by the connection associated with
633    CTRL.  This is used after a cancel to kill running wrappers.  */
634 void
635 ldap_wrapper_connection_cleanup (ctrl_t ctrl)
636 {
637   struct wrapper_context_s *ctx;
638
639   lock_reaper_list ();
640   {
641     for (ctx=reaper_list; ctx; ctx=ctx->next)
642       if (ctx->ctrl && ctx->ctrl == ctrl)
643         {
644           ctx->ctrl->refcount--;
645           ctx->ctrl = NULL;
646           if (ctx->pid != (pid_t)(-1))
647             gnupg_kill_process (ctx->pid);
648           if (ctx->fp_err)
649             log_info ("%s: reading from ldap wrapper %d failed: %s\n",
650                       __func__, ctx->printable_pid, gpg_strerror (ctx->fp_err));
651         }
652   }
653   unlock_reaper_list ();
654 }
655
656
657 /* This is the callback used by the ldap wrapper to feed the ksba
658  * reader with the wrapper's stdout.  See the description of
659  * ksba_reader_set_cb for details.  */
660 static int
661 reader_callback (void *cb_value, char *buffer, size_t count,  size_t *nread)
662 {
663   struct wrapper_context_s *ctx = cb_value;
664   size_t nleft = count;
665   struct timespec abstime;
666   struct timespec curtime;
667   struct timespec timeout;
668   int millisecs;
669   gpgrt_poll_t fparray[1];
670   int ret;
671   gpg_error_t err;
672
673
674   /* FIXME: We might want to add some internal buffering because the
675      ksba code does not do any buffering for itself (because a ksba
676      reader may be detached from another stream to read other data and
677      then it would be cumbersome to get back already buffered stuff).  */
678
679   if (!buffer && !count && !nread)
680     return -1; /* Rewind is not supported. */
681
682   /* If we ever encountered a read error, don't continue (we don't want to
683      possibly overwrite the last error cause).  Bail out also if the
684      file descriptor has been closed. */
685   if (ctx->fp_err || !ctx->fp)
686     {
687       *nread = 0;
688       return -1;
689     }
690
691   memset (fparray, 0, sizeof fparray);
692   fparray[0].stream = ctx->fp;
693   fparray[0].want_read = 1;
694
695   npth_clock_gettime (&abstime);
696   abstime.tv_sec += TIMERTICK_INTERVAL;
697
698   while (nleft > 0)
699     {
700       npth_clock_gettime (&curtime);
701       if (!(npth_timercmp (&curtime, &abstime, <)))
702         {
703           err = dirmngr_tick (ctx->ctrl);
704           if (err)
705             {
706               ctx->fp_err = err;
707               SAFE_CLOSE (ctx->fp);
708               return -1;
709             }
710           npth_clock_gettime (&abstime);
711           abstime.tv_sec += TIMERTICK_INTERVAL;
712         }
713       npth_timersub (&abstime, &curtime, &timeout);
714       millisecs = timeout.tv_sec * 1000;
715       millisecs += timeout.tv_nsec / 1000000;
716       if (millisecs < 0)
717         millisecs = 1;
718
719       if (DBG_EXTPROG)
720         {
721           log_debug ("%s: fp[0] stream=%p want=%d\n",
722                      __func__, fparray[0].stream,fparray[0].want_read);
723         }
724
725       ret = es_poll (fparray, DIM (fparray), millisecs);
726       if (ret < 0)
727         {
728           ctx->fp_err = gpg_error_from_syserror ();
729           log_error ("error polling stdout of ldap wrapper %d: %s\n",
730                      ctx->printable_pid, gpg_strerror (ctx->fp_err));
731           SAFE_CLOSE (ctx->fp);
732           return -1;
733         }
734       if (DBG_EXTPROG)
735         {
736           log_debug ("%s: fp[0] stream=%p r=%d %c%c%c%c%c%c%c\n",
737                      __func__, fparray[0].stream, ret,
738                      fparray[0].got_read? 'r':'-',
739                      fparray[0].got_write?'w':'-',
740                      fparray[0].got_oob?  'o':'-',
741                      fparray[0].got_rdhup?'H':'-',
742                      fparray[0].got_err?  'e':'-',
743                      fparray[0].got_hup?  'h':'-',
744                      fparray[0].got_nval? 'n':'-');
745         }
746       if (!ret)
747         {
748           /* Timeout.  Will be handled when calculating the next timeout.  */
749           continue;
750         }
751
752       if (fparray[0].got_read)
753         {
754           size_t n;
755
756           if (es_read (ctx->fp, buffer, nleft, &n))
757             {
758               ctx->fp_err = gpg_error_from_syserror ();
759               if (gpg_err_code (ctx->fp_err) == GPG_ERR_EAGAIN)
760                 ctx->fp_err = 0;
761               else
762                 {
763                   log_error ("%s: error reading: %s (%d)\n",
764                              __func__, gpg_strerror (ctx->fp_err), ctx->fp_err);
765                   SAFE_CLOSE (ctx->fp);
766                   return -1;
767                 }
768             }
769           else if (!n) /* EOF */
770             {
771               if (nleft == count)
772                 return -1; /* EOF. */
773               break;
774             }
775           nleft -= n;
776           buffer += n;
777           if (n > 0 && ctx->stamp != (time_t)(-1))
778             ctx->stamp = time (NULL);
779         }
780     }
781   *nread = count - nleft;
782
783   return 0;
784 }
785
786
787 /* Fork and exec the LDAP wrapper and return a new libksba reader
788    object at READER.  ARGV is a NULL terminated list of arguments for
789    the wrapper.  The function returns 0 on success or an error code.
790
791    Special hack to avoid passing a password through the command line
792    which is globally visible: If the first element of ARGV is "--pass"
793    it will be removed and instead the environment variable
794    DIRMNGR_LDAP_PASS will be set to the next value of ARGV.  On modern
795    OSes the environment is not visible to other users.  For those old
796    systems where it can't be avoided, we don't want to go into the
797    hassle of passing the password via stdin; it's just too complicated
798    and an LDAP password used for public directory lookups should not
799    be that confidential.  */
800 gpg_error_t
801 ldap_wrapper (ctrl_t ctrl, ksba_reader_t *reader, const char *argv[])
802 {
803   gpg_error_t err;
804   pid_t pid;
805   struct wrapper_context_s *ctx;
806   int i;
807   int j;
808   const char **arg_list;
809   const char *pgmname;
810   estream_t outfp, errfp;
811
812   /* It would be too simple to connect stderr just to our logging
813      stream.  The problem is that if we are running multi-threaded
814      everything gets intermixed.  Clearly we don't want this.  So the
815      only viable solutions are either to have another thread
816      responsible for logging the messages or to add an option to the
817      wrapper module to do the logging on its own.  Given that we anyway
818      need a way to reap the child process and this is best done using a
819      general reaping thread, that thread can do the logging too. */
820   ldap_reaper_launch_thread ();
821
822   *reader = NULL;
823
824   /* Files: We need to prepare stdin and stdout.  We get stderr from
825      the function.  */
826   if (!opt.ldap_wrapper_program || !*opt.ldap_wrapper_program)
827     pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR_LDAP);
828   else
829     pgmname = opt.ldap_wrapper_program;
830
831   /* Create command line argument array.  */
832   for (i = 0; argv[i]; i++)
833     ;
834   arg_list = xtrycalloc (i + 2, sizeof *arg_list);
835   if (!arg_list)
836     {
837       err = gpg_error_from_syserror ();
838       log_error (_("error allocating memory: %s\n"), strerror (errno));
839       return err;
840     }
841   for (i = j = 0; argv[i]; i++, j++)
842     if (!i && argv[i + 1] && !strcmp (*argv, "--pass"))
843       {
844         arg_list[j] = "--env-pass";
845         setenv ("DIRMNGR_LDAP_PASS", argv[1], 1);
846         i++;
847       }
848     else
849       arg_list[j] = (char*) argv[i];
850
851   ctx = xtrycalloc (1, sizeof *ctx);
852   if (!ctx)
853     {
854       err = gpg_error_from_syserror ();
855       log_error (_("error allocating memory: %s\n"), strerror (errno));
856       xfree (arg_list);
857       return err;
858     }
859
860   err = gnupg_spawn_process (pgmname, arg_list,
861                              NULL, NULL, GNUPG_SPAWN_NONBLOCK,
862                              NULL, &outfp, &errfp, &pid);
863   xfree (arg_list);
864   if (err)
865     {
866       xfree (ctx);
867       log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
868       return err;
869     }
870
871   ctx->pid = pid;
872   ctx->printable_pid = (int) pid;
873   ctx->fp = outfp;
874   ctx->log_fp = errfp;
875   ctx->ctrl = ctrl;
876   ctrl->refcount++;
877   ctx->stamp = time (NULL);
878
879   err = ksba_reader_new (reader);
880   if (!err)
881     err = ksba_reader_set_cb (*reader, reader_callback, ctx);
882   if (err)
883     {
884       log_error (_("error initializing reader object: %s\n"),
885                  gpg_strerror (err));
886       destroy_wrapper (ctx);
887       ksba_reader_release (*reader);
888       *reader = NULL;
889       return err;
890     }
891
892   /* Hook the context into our list of running wrappers.  */
893   lock_reaper_list ();
894   {
895     ctx->reader = *reader;
896     ctx->next = reaper_list;
897     reaper_list = ctx;
898     if (npth_cond_signal (&reaper_run_cond))
899       log_error ("ldap-wrapper: Ooops: signaling condition failed: %s (%d)\n",
900                  gpg_strerror (gpg_error_from_syserror ()), errno);
901   }
902   unlock_reaper_list ();
903
904   if (DBG_EXTPROG)
905     log_debug ("ldap wrapper %d started (%p, %s)\n",
906                (int)ctx->pid, ctx->reader, pgmname);
907
908   /* Need to wait for the first byte so we are able to detect an empty
909      output and not let the consumer see an EOF without further error
910      indications.  The CRL loading logic assumes that after return
911      from this function, a failed search (e.g. host not found ) is
912      indicated right away. */
913   {
914     unsigned char c;
915
916     err = read_buffer (*reader, &c, 1);
917     if (err)
918       {
919         ldap_wrapper_release_context (*reader);
920         ksba_reader_release (*reader);
921         *reader = NULL;
922         if (gpg_err_code (err) == GPG_ERR_EOF)
923           return gpg_error (GPG_ERR_NO_DATA);
924         else
925           return err;
926       }
927     ksba_reader_unread (*reader, &c, 1);
928   }
929
930   return 0;
931 }