Line data Source code
1 : /* ldap.c - LDAP access
2 : * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3 : * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2010 g10 Code GmbH
4 : *
5 : * This file is part of DirMngr.
6 : *
7 : * DirMngr 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 2 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * DirMngr 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, write to the Free Software
19 : * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 : */
21 :
22 : #include <config.h>
23 :
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 : #include <errno.h>
28 : #include <unistd.h>
29 : #include <fcntl.h>
30 : #include <time.h>
31 : #include <npth.h>
32 :
33 : #include "dirmngr.h"
34 : #include "exechelp.h"
35 : #include "crlfetch.h"
36 : #include "ldapserver.h"
37 : #include "misc.h"
38 : #include "ldap-wrapper.h"
39 : #include "host2net.h"
40 :
41 :
42 : #define UNENCODED_URL_CHARS "abcdefghijklmnopqrstuvwxyz" \
43 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
44 : "01234567890" \
45 : "$-_.+!*'(),"
46 : #define USERCERTIFICATE "userCertificate"
47 : #define CACERTIFICATE "caCertificate"
48 : #define X509CACERT "x509caCert"
49 : #define USERSMIMECERTIFICATE "userSMIMECertificate"
50 :
51 :
52 : /* Definition for the context of the cert fetch functions. */
53 : struct cert_fetch_context_s
54 : {
55 : ksba_reader_t reader; /* The reader used (shallow copy). */
56 : unsigned char *tmpbuf; /* Helper buffer. */
57 : size_t tmpbufsize; /* Allocated size of tmpbuf. */
58 : int truncated; /* Flag to indicate a truncated output. */
59 : };
60 :
61 :
62 :
63 :
64 : /* Add HOST and PORT to our list of LDAP servers. Fixme: We should
65 : better use an extra list of servers. */
66 : static void
67 0 : add_server_to_servers (const char *host, int port)
68 : {
69 : ldap_server_t server;
70 0 : ldap_server_t last = NULL;
71 : const char *s;
72 :
73 0 : if (!port)
74 0 : port = 389;
75 :
76 0 : for (server=opt.ldapservers; server; server = server->next)
77 : {
78 0 : if (!strcmp (server->host, host) && server->port == port)
79 0 : return; /* already in list... */
80 0 : last = server;
81 : }
82 :
83 : /* We assume that the host names are all supplied by our
84 : configuration files and thus are sane. To keep this assumption
85 : we must reject all invalid host names. */
86 0 : for (s=host; *s; s++)
87 0 : if (!strchr ("abcdefghijklmnopqrstuvwxyz"
88 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
89 0 : "01234567890.-", *s))
90 : {
91 0 : log_error (_("invalid char 0x%02x in host name - not added\n"), *s);
92 0 : return;
93 : }
94 :
95 0 : log_info (_("adding '%s:%d' to the ldap server list\n"), host, port);
96 0 : server = xtrycalloc (1, sizeof *s);
97 0 : if (!server)
98 0 : log_error (_("malloc failed: %s\n"), strerror (errno));
99 : else
100 : {
101 0 : server->host = xstrdup (host);
102 0 : server->port = port;
103 0 : if (last)
104 0 : last->next = server;
105 : else
106 0 : opt.ldapservers = server;
107 : }
108 : }
109 :
110 :
111 :
112 :
113 : /* Perform an LDAP query. Returns an gpg error code or 0 on success.
114 : The function returns a new reader object at READER. */
115 : static gpg_error_t
116 0 : run_ldap_wrapper (ctrl_t ctrl,
117 : int ignore_timeout,
118 : int multi_mode,
119 : const char *proxy,
120 : const char *host, int port,
121 : const char *user, const char *pass,
122 : const char *dn, const char *filter, const char *attr,
123 : const char *url,
124 : ksba_reader_t *reader)
125 : {
126 : const char *argv[40];
127 : int argc;
128 : char portbuf[30], timeoutbuf[30];
129 :
130 :
131 0 : *reader = NULL;
132 :
133 0 : argc = 0;
134 0 : if (pass) /* Note, that the password must be the first item. */
135 : {
136 0 : argv[argc++] = "--pass";
137 0 : argv[argc++] = pass;
138 : }
139 0 : if (opt.verbose)
140 0 : argv[argc++] = "-vv";
141 0 : argv[argc++] = "--log-with-pid";
142 0 : if (multi_mode)
143 0 : argv[argc++] = "--multi";
144 0 : if (opt.ldaptimeout)
145 : {
146 0 : sprintf (timeoutbuf, "%u", opt.ldaptimeout);
147 0 : argv[argc++] = "--timeout";
148 0 : argv[argc++] = timeoutbuf;
149 0 : if (ignore_timeout)
150 0 : argv[argc++] = "--only-search-timeout";
151 : }
152 0 : if (proxy)
153 : {
154 0 : argv[argc++] = "--proxy";
155 0 : argv[argc++] = proxy;
156 : }
157 0 : if (host)
158 : {
159 0 : argv[argc++] = "--host";
160 0 : argv[argc++] = host;
161 : }
162 0 : if (port)
163 : {
164 0 : sprintf (portbuf, "%d", port);
165 0 : argv[argc++] = "--port";
166 0 : argv[argc++] = portbuf;
167 : }
168 0 : if (user)
169 : {
170 0 : argv[argc++] = "--user";
171 0 : argv[argc++] = user;
172 : }
173 0 : if (dn)
174 : {
175 0 : argv[argc++] = "--dn";
176 0 : argv[argc++] = dn;
177 : }
178 0 : if (filter)
179 : {
180 0 : argv[argc++] = "--filter";
181 0 : argv[argc++] = filter;
182 : }
183 0 : if (attr)
184 : {
185 0 : argv[argc++] = "--attr";
186 0 : argv[argc++] = attr;
187 : }
188 0 : argv[argc++] = url? url : "ldap://";
189 0 : argv[argc] = NULL;
190 :
191 0 : return ldap_wrapper (ctrl, reader, argv);
192 : }
193 :
194 :
195 :
196 :
197 : /* Perform a LDAP query using a given URL. On success a new ksba
198 : reader is returned. If HOST or PORT are not 0, they are used to
199 : override the values from the URL. */
200 : gpg_error_t
201 0 : url_fetch_ldap (ctrl_t ctrl, const char *url, const char *host, int port,
202 : ksba_reader_t *reader)
203 : {
204 : gpg_error_t err;
205 :
206 0 : err = run_ldap_wrapper (ctrl,
207 : 1, /* Ignore explicit timeout because CRLs
208 : might be very large. */
209 : 0,
210 : opt.ldap_proxy,
211 : host, port,
212 : NULL, NULL,
213 : NULL, NULL, NULL, url,
214 : reader);
215 :
216 : /* FIXME: This option might be used for DoS attacks. Because it
217 : will enlarge the list of servers to consult without a limit and
218 : all LDAP queries w/o a host are will then try each host in
219 : turn. */
220 0 : if (!err && opt.add_new_ldapservers && !opt.ldap_proxy)
221 : {
222 0 : if (host)
223 0 : add_server_to_servers (host, port);
224 0 : else if (url)
225 : {
226 0 : char *tmp = host_and_port_from_url (url, &port);
227 0 : if (tmp)
228 : {
229 0 : add_server_to_servers (tmp, port);
230 0 : xfree (tmp);
231 : }
232 : }
233 : }
234 :
235 : /* If the lookup failed and we are not only using the proxy, we try
236 : again using our default list of servers. */
237 0 : if (err && !(opt.ldap_proxy && opt.only_ldap_proxy))
238 : {
239 : struct ldapserver_iter iter;
240 :
241 0 : if (DBG_LOOKUP)
242 0 : log_debug ("no hostname in URL or query failed; "
243 : "trying all default hostnames\n");
244 :
245 0 : for (ldapserver_iter_begin (&iter, ctrl);
246 0 : err && ! ldapserver_iter_end_p (&iter);
247 0 : ldapserver_iter_next (&iter))
248 : {
249 0 : ldap_server_t server = iter.server;
250 :
251 0 : err = run_ldap_wrapper (ctrl,
252 : 0,
253 : 0,
254 : NULL,
255 0 : server->host, server->port,
256 : NULL, NULL,
257 : NULL, NULL, NULL, url,
258 : reader);
259 0 : if (!err)
260 0 : break;
261 : }
262 : }
263 :
264 0 : return err;
265 : }
266 :
267 :
268 :
269 : /* Perform an LDAP query on all configured servers. On error the
270 : error code of the last try is returned. */
271 : gpg_error_t
272 0 : attr_fetch_ldap (ctrl_t ctrl,
273 : const char *dn, const char *attr, ksba_reader_t *reader)
274 : {
275 0 : gpg_error_t err = gpg_error (GPG_ERR_CONFIGURATION);
276 : struct ldapserver_iter iter;
277 :
278 0 : *reader = NULL;
279 :
280 : /* FIXME; we might want to look at the Base SN to try matching
281 : servers first. */
282 0 : for (ldapserver_iter_begin (&iter, ctrl); ! ldapserver_iter_end_p (&iter);
283 0 : ldapserver_iter_next (&iter))
284 : {
285 0 : ldap_server_t server = iter.server;
286 :
287 0 : err = run_ldap_wrapper (ctrl,
288 : 0,
289 : 0,
290 : opt.ldap_proxy,
291 0 : server->host, server->port,
292 0 : server->user, server->pass,
293 : dn, "objectClass=*", attr, NULL,
294 : reader);
295 0 : if (!err)
296 0 : break; /* Probably found a result. Ready. */
297 : }
298 0 : return err;
299 : }
300 :
301 :
302 : /* Parse PATTERN and return a new strlist to be used for the actual
303 : LDAP query. Bit 0 of the flags field is set if that pattern is
304 : actually a base specification. Caller must release the returned
305 : strlist. NULL is returned on error.
306 :
307 : * Possible patterns:
308 : *
309 : * KeyID
310 : * Fingerprint
311 : * OpenPGP userid
312 : * x Email address Indicated by a left angle bracket.
313 : * Exact word match in user id or subj. name
314 : * x Subj. DN indicated bu a leading slash
315 : * Issuer DN
316 : * Serial number + subj. DN
317 : * x Substring match indicated by a leading '*; is also the default.
318 : */
319 :
320 : strlist_t
321 0 : parse_one_pattern (const char *pattern)
322 : {
323 0 : strlist_t result = NULL;
324 : char *p;
325 :
326 0 : switch (*pattern)
327 : {
328 : case '<': /* Email. */
329 : {
330 0 : pattern++;
331 0 : result = xmalloc (sizeof *result + 5 + strlen (pattern));
332 0 : result->next = NULL;
333 0 : result->flags = 0;
334 0 : p = stpcpy (stpcpy (result->d, "mail="), pattern);
335 0 : if (p[-1] == '>')
336 0 : *--p = 0;
337 0 : if (!*result->d) /* Error. */
338 : {
339 0 : xfree (result);
340 0 : result = NULL;
341 : }
342 0 : break;
343 : }
344 : case '/': /* Subject DN. */
345 0 : pattern++;
346 0 : if (*pattern)
347 : {
348 0 : result = xmalloc (sizeof *result + strlen (pattern));
349 0 : result->next = NULL;
350 0 : result->flags = 1; /* Base spec. */
351 0 : strcpy (result->d, pattern);
352 : }
353 0 : break;
354 : case '#': /* Issuer DN. */
355 0 : pattern++;
356 0 : if (*pattern == '/') /* Just issuer DN. */
357 : {
358 0 : pattern++;
359 : }
360 : else /* Serial number + issuer DN */
361 : {
362 : }
363 0 : break;
364 : case '*':
365 0 : pattern++;
366 : default: /* Take as substring match. */
367 : {
368 0 : const char format[] = "(|(sn=*%s*)(|(cn=*%s*)(mail=*%s*)))";
369 :
370 0 : if (*pattern)
371 : {
372 0 : result = xmalloc (sizeof *result
373 : + strlen (format) + 3 * strlen (pattern));
374 0 : result->next = NULL;
375 0 : result->flags = 0;
376 0 : sprintf (result->d, format, pattern, pattern, pattern);
377 : }
378 : }
379 0 : break;
380 : }
381 :
382 0 : return result;
383 : }
384 :
385 : /* Take the string STRING and escape it according to the URL rules.
386 : Retun a newly allocated string. */
387 : static char *
388 0 : escape4url (const char *string)
389 : {
390 : const char *s;
391 : char *buf, *p;
392 : size_t n;
393 :
394 0 : if (!string)
395 0 : string = "";
396 :
397 0 : for (s=string,n=0; *s; s++)
398 0 : if (strchr (UNENCODED_URL_CHARS, *s))
399 0 : n++;
400 : else
401 0 : n += 3;
402 :
403 0 : buf = malloc (n+1);
404 0 : if (!buf)
405 0 : return NULL;
406 :
407 0 : for (s=string,p=buf; *s; s++)
408 0 : if (strchr (UNENCODED_URL_CHARS, *s))
409 0 : *p++ = *s;
410 : else
411 : {
412 0 : sprintf (p, "%%%02X", *(const unsigned char *)s);
413 0 : p += 3;
414 : }
415 0 : *p = 0;
416 :
417 0 : return buf;
418 : }
419 :
420 :
421 :
422 : /* Create a LDAP URL from DN and FILTER and return it in URL. We don't
423 : need the host and port because this will be specified using the
424 : override options. */
425 : static gpg_error_t
426 0 : make_url (char **url, const char *dn, const char *filter)
427 : {
428 : gpg_error_t err;
429 : char *u_dn, *u_filter;
430 0 : char const attrs[] = (USERCERTIFICATE ","
431 : /* USERSMIMECERTIFICATE "," */
432 : CACERTIFICATE ","
433 : X509CACERT );
434 :
435 0 : *url = NULL;
436 :
437 0 : u_dn = escape4url (dn);
438 0 : if (!u_dn)
439 0 : return gpg_error_from_errno (errno);
440 :
441 0 : u_filter = escape4url (filter);
442 0 : if (!u_filter)
443 : {
444 0 : err = gpg_error_from_errno (errno);
445 0 : xfree (u_dn);
446 0 : return err;
447 : }
448 0 : *url = malloc ( 8 + strlen (u_dn)
449 0 : + 1 + strlen (attrs)
450 0 : + 5 + strlen (u_filter) + 1 );
451 0 : if (!*url)
452 : {
453 0 : err = gpg_error_from_errno (errno);
454 0 : xfree (u_dn);
455 0 : xfree (u_filter);
456 0 : return err;
457 : }
458 :
459 0 : stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (stpcpy (*url, "ldap:///"),
460 : u_dn),
461 : "?"),
462 : attrs),
463 : "?sub?"),
464 : u_filter);
465 0 : xfree (u_dn);
466 0 : xfree (u_filter);
467 0 : return 0;
468 : }
469 :
470 :
471 : /* Prepare an LDAP query to return the attribute ATTR for the DN. All
472 : configured default servers are queried until one responds. This
473 : function returns an error code or 0 and a CONTEXT on success. */
474 : gpg_error_t
475 0 : start_default_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
476 : const char *dn, const char *attr)
477 : {
478 : gpg_error_t err;
479 : struct ldapserver_iter iter;
480 :
481 0 : *context = xtrycalloc (1, sizeof **context);
482 0 : if (!*context)
483 0 : return gpg_error_from_errno (errno);
484 :
485 : /* FIXME; we might want to look at the Base SN to try matching
486 : servers first. */
487 0 : err = gpg_error (GPG_ERR_CONFIGURATION);
488 :
489 0 : for (ldapserver_iter_begin (&iter, ctrl); ! ldapserver_iter_end_p (&iter);
490 0 : ldapserver_iter_next (&iter))
491 : {
492 0 : ldap_server_t server = iter.server;
493 :
494 0 : err = run_ldap_wrapper (ctrl,
495 : 0,
496 : 1,
497 : opt.ldap_proxy,
498 0 : server->host, server->port,
499 0 : server->user, server->pass,
500 : dn, "objectClass=*", attr, NULL,
501 0 : &(*context)->reader);
502 0 : if (!err)
503 0 : break; /* Probably found a result. */
504 : }
505 :
506 0 : if (err)
507 : {
508 0 : xfree (*context);
509 0 : *context = NULL;
510 : }
511 0 : return err;
512 : }
513 :
514 :
515 : /* Prepare an LDAP query to return certificates matching PATTERNS using
516 : the SERVER. This function returns an error code or 0 and a CONTEXT
517 : on success. */
518 : gpg_error_t
519 0 : start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
520 : strlist_t patterns, const ldap_server_t server)
521 : {
522 : gpg_error_t err;
523 0 : char *proxy = NULL;
524 0 : char *host = NULL;
525 : int port;
526 0 : char *user = NULL;
527 0 : char *pass = NULL;
528 : const char *base;
529 : char *argv[50];
530 0 : int argc = 0;
531 0 : int argc_malloced = 0;
532 : char portbuf[30], timeoutbuf[30];
533 :
534 :
535 0 : *context = NULL;
536 :
537 0 : if (opt.ldap_proxy && !(proxy = xtrystrdup (opt.ldap_proxy)))
538 : {
539 0 : err = gpg_error_from_syserror ();
540 0 : goto leave;
541 : }
542 :
543 0 : if (server)
544 : {
545 0 : if (server->host && !(host = xtrystrdup (server->host)))
546 : {
547 0 : err = gpg_error_from_syserror ();
548 0 : goto leave;
549 : }
550 0 : port = server->port;
551 0 : if (server->user && !(user = xtrystrdup (server->user)))
552 : {
553 0 : err = gpg_error_from_syserror ();
554 0 : goto leave;
555 : }
556 0 : if (server->pass && !(pass = xtrystrdup (server->pass)))
557 : {
558 0 : err = gpg_error_from_syserror ();
559 0 : goto leave;
560 : }
561 0 : base = server->base;
562 :
563 : }
564 : else /* Use a default server. */
565 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
566 :
567 :
568 0 : if (!base)
569 0 : base = "";
570 :
571 0 : if (pass) /* Note: Must be the first item. */
572 : {
573 0 : argv[argc++] = "--pass";
574 0 : argv[argc++] = pass;
575 : }
576 0 : if (opt.verbose)
577 0 : argv[argc++] = "-vv";
578 0 : argv[argc++] = "--log-with-pid";
579 0 : argv[argc++] = "--multi";
580 0 : if (opt.ldaptimeout)
581 : {
582 0 : snprintf (timeoutbuf, sizeof timeoutbuf, "%u", opt.ldaptimeout);
583 0 : argv[argc++] = "--timeout";
584 0 : argv[argc++] = timeoutbuf;
585 : }
586 0 : if (opt.ldap_proxy)
587 : {
588 0 : argv[argc++] = "--proxy";
589 0 : argv[argc++] = proxy;
590 : }
591 0 : if (host)
592 : {
593 0 : argv[argc++] = "--host";
594 0 : argv[argc++] = host;
595 : }
596 0 : if (port)
597 : {
598 0 : snprintf (portbuf, sizeof portbuf, "%d", port);
599 0 : argv[argc++] = "--port";
600 0 : argv[argc++] = portbuf;
601 : }
602 0 : if (user)
603 : {
604 0 : argv[argc++] = "--user";
605 0 : argv[argc++] = user;
606 : }
607 :
608 : /* All entries in argv from this index on are malloc'ed. */
609 0 : argc_malloced = argc;
610 :
611 0 : for (; patterns; patterns = patterns->next)
612 : {
613 : strlist_t sl;
614 : char *url;
615 :
616 0 : if (argc >= DIM (argv) - 1)
617 : {
618 : /* Too many patterns. It does not make sense to allow an
619 : arbitrary number of patters because the length of the
620 : command line is limited anyway. */
621 : /* fixme: cleanup. */
622 0 : return gpg_error (GPG_ERR_RESOURCE_LIMIT);
623 : }
624 0 : sl = parse_one_pattern (patterns->d);
625 0 : if (!sl)
626 : {
627 0 : log_error (_("start_cert_fetch: invalid pattern '%s'\n"),
628 0 : patterns->d);
629 0 : err = gpg_error (GPG_ERR_INV_USER_ID);
630 0 : goto leave;
631 : }
632 0 : if ((sl->flags & 1))
633 0 : err = make_url (&url, sl->d, "objectClass=*");
634 : else
635 0 : err = make_url (&url, base, sl->d);
636 0 : free_strlist (sl);
637 0 : if (err)
638 0 : goto leave;
639 0 : argv[argc++] = url;
640 : }
641 0 : argv[argc] = NULL;
642 :
643 0 : *context = xtrycalloc (1, sizeof **context);
644 0 : if (!*context)
645 : {
646 0 : err = gpg_error_from_errno (errno);
647 0 : goto leave;
648 : }
649 :
650 0 : err = ldap_wrapper (ctrl, &(*context)->reader, (const char**)argv);
651 :
652 0 : if (err)
653 : {
654 0 : xfree (*context);
655 0 : *context = NULL;
656 : }
657 :
658 : leave:
659 0 : for (; argc_malloced < argc; argc_malloced++)
660 0 : xfree (argv[argc_malloced]);
661 0 : xfree (proxy);
662 0 : xfree (host);
663 0 : xfree (user);
664 0 : xfree (pass);
665 0 : return err;
666 : }
667 :
668 :
669 : /* Read a fixed amount of data from READER into BUFFER. */
670 : static gpg_error_t
671 0 : read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
672 : {
673 : gpg_error_t err;
674 : size_t nread;
675 :
676 0 : while (count)
677 : {
678 0 : err = ksba_reader_read (reader, buffer, count, &nread);
679 0 : if (err)
680 0 : return err;
681 0 : buffer += nread;
682 0 : count -= nread;
683 : }
684 0 : return 0;
685 : }
686 :
687 :
688 : /* Fetch the next certificate. Return 0 on success, GPG_ERR_EOF if no
689 : (more) certificates are available or any other error
690 : code. GPG_ERR_TRUNCATED may be returned to indicate that the result
691 : has been truncated. */
692 : gpg_error_t
693 0 : fetch_next_cert_ldap (cert_fetch_context_t context,
694 : unsigned char **value, size_t *valuelen)
695 : {
696 : gpg_error_t err;
697 : unsigned char hdr[5];
698 : char *p, *pend;
699 : unsigned long n;
700 0 : int okay = 0;
701 : /* int is_cms = 0; */
702 :
703 0 : *value = NULL;
704 0 : *valuelen = 0;
705 :
706 0 : err = 0;
707 0 : while (!err)
708 : {
709 0 : err = read_buffer (context->reader, hdr, 5);
710 0 : if (err)
711 0 : break;
712 0 : n = buf32_to_ulong (hdr+1);
713 0 : if (*hdr == 'V' && okay)
714 : {
715 : #if 0 /* That code is not yet ready. */
716 :
717 : if (is_cms)
718 : {
719 : /* The certificate needs to be parsed from CMS data. */
720 : ksba_cms_t cms;
721 : ksba_stop_reason_t stopreason;
722 : int i;
723 :
724 : err = ksba_cms_new (&cms);
725 : if (err)
726 : goto leave;
727 : err = ksba_cms_set_reader_writer (cms, context->reader, NULL);
728 : if (err)
729 : {
730 : log_error ("ksba_cms_set_reader_writer failed: %s\n",
731 : gpg_strerror (err));
732 : goto leave;
733 : }
734 :
735 : do
736 : {
737 : err = ksba_cms_parse (cms, &stopreason);
738 : if (err)
739 : {
740 : log_error ("ksba_cms_parse failed: %s\n",
741 : gpg_strerror (err));
742 : goto leave;
743 : }
744 :
745 : if (stopreason == KSBA_SR_BEGIN_DATA)
746 : log_error ("userSMIMECertificate is not "
747 : "a certs-only message\n");
748 : }
749 : while (stopreason != KSBA_SR_READY);
750 :
751 : for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
752 : {
753 : check_and_store (ctrl, stats, cert, 0);
754 : ksba_cert_release (cert);
755 : cert = NULL;
756 : }
757 : if (!i)
758 : log_error ("no certificate found\n");
759 : else
760 : any = 1;
761 : }
762 : else
763 : #endif
764 : {
765 0 : *value = xtrymalloc (n);
766 0 : if (!*value)
767 0 : return gpg_error_from_errno (errno);
768 0 : *valuelen = n;
769 0 : err = read_buffer (context->reader, *value, n);
770 0 : break; /* Ready or error. */
771 : }
772 : }
773 0 : else if (!n && *hdr == 'A')
774 0 : okay = 0;
775 0 : else if (n)
776 : {
777 0 : if (n > context->tmpbufsize)
778 : {
779 0 : xfree (context->tmpbuf);
780 0 : context->tmpbufsize = 0;
781 0 : context->tmpbuf = xtrymalloc (n+1);
782 0 : if (!context->tmpbuf)
783 0 : return gpg_error_from_errno (errno);
784 0 : context->tmpbufsize = n;
785 : }
786 0 : err = read_buffer (context->reader, context->tmpbuf, n);
787 0 : if (err)
788 0 : break;
789 0 : if (*hdr == 'A')
790 : {
791 0 : p = context->tmpbuf;
792 0 : p[n] = 0; /*(we allocated one extra byte for this.)*/
793 : /* fixme: is_cms = 0; */
794 0 : if ( (pend = strchr (p, ';')) )
795 0 : *pend = 0; /* Strip off the extension. */
796 0 : if (!ascii_strcasecmp (p, USERCERTIFICATE))
797 : {
798 0 : if (DBG_LOOKUP)
799 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
800 : USERCERTIFICATE);
801 0 : okay = 1;
802 : }
803 0 : else if (!ascii_strcasecmp (p, CACERTIFICATE))
804 : {
805 0 : if (DBG_LOOKUP)
806 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
807 : CACERTIFICATE);
808 0 : okay = 1;
809 : }
810 0 : else if (!ascii_strcasecmp (p, X509CACERT))
811 : {
812 0 : if (DBG_LOOKUP)
813 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
814 : CACERTIFICATE);
815 0 : okay = 1;
816 : }
817 : /* else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */
818 : /* { */
819 : /* if (DBG_LOOKUP) */
820 : /* log_debug ("fetch_next_cert_ldap: got attribute '%s'\n", */
821 : /* USERSMIMECERTIFICATE); */
822 : /* okay = 1; */
823 : /* is_cms = 1; */
824 : /* } */
825 : else
826 : {
827 0 : if (DBG_LOOKUP)
828 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'"
829 : " - ignored\n", p);
830 0 : okay = 0;
831 : }
832 : }
833 0 : else if (*hdr == 'E')
834 : {
835 0 : p = context->tmpbuf;
836 0 : p[n] = 0; /*(we allocated one extra byte for this.)*/
837 0 : if (!strcmp (p, "truncated"))
838 : {
839 0 : context->truncated = 1;
840 0 : log_info (_("ldap_search hit the size limit of"
841 : " the server\n"));
842 : }
843 : }
844 : }
845 : }
846 :
847 0 : if (err)
848 : {
849 0 : xfree (*value);
850 0 : *value = NULL;
851 0 : *valuelen = 0;
852 0 : if (gpg_err_code (err) == GPG_ERR_EOF && context->truncated)
853 : {
854 0 : context->truncated = 0; /* So that the next call would return EOF. */
855 0 : err = gpg_error (GPG_ERR_TRUNCATED);
856 : }
857 : }
858 :
859 0 : return err;
860 : }
861 :
862 :
863 : void
864 0 : end_cert_fetch_ldap (cert_fetch_context_t context)
865 : {
866 0 : if (context)
867 : {
868 0 : ksba_reader_t reader = context->reader;
869 :
870 0 : xfree (context->tmpbuf);
871 0 : xfree (context);
872 0 : ldap_wrapper_release_context (reader);
873 0 : ksba_reader_release (reader);
874 : }
875 0 : }
|