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 function. */
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 continue (we don't want to
549 : possibly 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, NULL, 0);
699 0 : if (!err)
700 : {
701 0 : err = gnupg_create_inbound_pipe (errpipe, NULL, 0);
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 : }
|