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