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 accoring 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 maching 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 : const char *host;
524 : int port;
525 : const char *user;
526 : const char *pass;
527 : const char *base;
528 : const char *argv[50];
529 : int argc;
530 : char portbuf[30], timeoutbuf[30];
531 :
532 :
533 0 : *context = NULL;
534 0 : if (server)
535 : {
536 0 : host = server->host;
537 0 : port = server->port;
538 0 : user = server->user;
539 0 : pass = server->pass;
540 0 : base = server->base;
541 : }
542 : else /* Use a default server. */
543 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
544 :
545 0 : if (!base)
546 0 : base = "";
547 :
548 0 : argc = 0;
549 0 : if (pass) /* Note: Must be the first item. */
550 : {
551 0 : argv[argc++] = "--pass";
552 0 : argv[argc++] = pass;
553 : }
554 0 : if (opt.verbose)
555 0 : argv[argc++] = "-vv";
556 0 : argv[argc++] = "--log-with-pid";
557 0 : argv[argc++] = "--multi";
558 0 : if (opt.ldaptimeout)
559 : {
560 0 : sprintf (timeoutbuf, "%u", opt.ldaptimeout);
561 0 : argv[argc++] = "--timeout";
562 0 : argv[argc++] = timeoutbuf;
563 : }
564 0 : if (opt.ldap_proxy)
565 : {
566 0 : argv[argc++] = "--proxy";
567 0 : argv[argc++] = opt.ldap_proxy;
568 : }
569 0 : if (host)
570 : {
571 0 : argv[argc++] = "--host";
572 0 : argv[argc++] = host;
573 : }
574 0 : if (port)
575 : {
576 0 : sprintf (portbuf, "%d", port);
577 0 : argv[argc++] = "--port";
578 0 : argv[argc++] = portbuf;
579 : }
580 0 : if (user)
581 : {
582 0 : argv[argc++] = "--user";
583 0 : argv[argc++] = user;
584 : }
585 :
586 :
587 0 : for (; patterns; patterns = patterns->next)
588 : {
589 : strlist_t sl;
590 : char *url;
591 :
592 0 : if (argc >= DIM (argv) - 1)
593 : {
594 : /* Too many patterns. It does not make sense to allow an
595 : arbitrary number of patters because the length of the
596 : command line is limited anyway. */
597 : /* fixme: cleanup. */
598 0 : return gpg_error (GPG_ERR_RESOURCE_LIMIT);
599 : }
600 0 : sl = parse_one_pattern (patterns->d);
601 0 : if (!sl)
602 : {
603 0 : log_error (_("start_cert_fetch: invalid pattern '%s'\n"),
604 0 : patterns->d);
605 : /* fixme: cleanup argv. */
606 0 : return gpg_error (GPG_ERR_INV_USER_ID);
607 : }
608 0 : if ((sl->flags & 1))
609 0 : err = make_url (&url, sl->d, "objectClass=*");
610 : else
611 0 : err = make_url (&url, base, sl->d);
612 0 : free_strlist (sl);
613 0 : if (err)
614 : {
615 : /* fixme: cleanup argv. */
616 0 : return err;
617 : }
618 0 : argv[argc++] = url;
619 : }
620 0 : argv[argc] = NULL;
621 :
622 0 : *context = xtrycalloc (1, sizeof **context);
623 0 : if (!*context)
624 0 : return gpg_error_from_errno (errno);
625 :
626 0 : err = ldap_wrapper (ctrl, &(*context)->reader, argv);
627 :
628 0 : if (err)
629 : {
630 0 : xfree (*context);
631 0 : *context = NULL;
632 : }
633 :
634 0 : return err;
635 : }
636 :
637 :
638 : /* Read a fixed amount of data from READER into BUFFER. */
639 : static gpg_error_t
640 0 : read_buffer (ksba_reader_t reader, unsigned char *buffer, size_t count)
641 : {
642 : gpg_error_t err;
643 : size_t nread;
644 :
645 0 : while (count)
646 : {
647 0 : err = ksba_reader_read (reader, buffer, count, &nread);
648 0 : if (err)
649 0 : return err;
650 0 : buffer += nread;
651 0 : count -= nread;
652 : }
653 0 : return 0;
654 : }
655 :
656 :
657 : /* Fetch the next certificate. Return 0 on success, GPG_ERR_EOF if no
658 : (more) certificates are available or any other error
659 : code. GPG_ERR_TRUNCATED may be returned to indicate that the result
660 : has been truncated. */
661 : gpg_error_t
662 0 : fetch_next_cert_ldap (cert_fetch_context_t context,
663 : unsigned char **value, size_t *valuelen)
664 : {
665 : gpg_error_t err;
666 : unsigned char hdr[5];
667 : char *p, *pend;
668 : unsigned long n;
669 0 : int okay = 0;
670 : /* int is_cms = 0; */
671 :
672 0 : *value = NULL;
673 0 : *valuelen = 0;
674 :
675 0 : err = 0;
676 0 : while (!err)
677 : {
678 0 : err = read_buffer (context->reader, hdr, 5);
679 0 : if (err)
680 0 : break;
681 0 : n = buf32_to_ulong (hdr+1);
682 0 : if (*hdr == 'V' && okay)
683 : {
684 : #if 0 /* That code is not yet ready. */
685 :
686 : if (is_cms)
687 : {
688 : /* The certificate needs to be parsed from CMS data. */
689 : ksba_cms_t cms;
690 : ksba_stop_reason_t stopreason;
691 : int i;
692 :
693 : err = ksba_cms_new (&cms);
694 : if (err)
695 : goto leave;
696 : err = ksba_cms_set_reader_writer (cms, context->reader, NULL);
697 : if (err)
698 : {
699 : log_error ("ksba_cms_set_reader_writer failed: %s\n",
700 : gpg_strerror (err));
701 : goto leave;
702 : }
703 :
704 : do
705 : {
706 : err = ksba_cms_parse (cms, &stopreason);
707 : if (err)
708 : {
709 : log_error ("ksba_cms_parse failed: %s\n",
710 : gpg_strerror (err));
711 : goto leave;
712 : }
713 :
714 : if (stopreason == KSBA_SR_BEGIN_DATA)
715 : log_error ("userSMIMECertificate is not "
716 : "a certs-only message\n");
717 : }
718 : while (stopreason != KSBA_SR_READY);
719 :
720 : for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
721 : {
722 : check_and_store (ctrl, stats, cert, 0);
723 : ksba_cert_release (cert);
724 : cert = NULL;
725 : }
726 : if (!i)
727 : log_error ("no certificate found\n");
728 : else
729 : any = 1;
730 : }
731 : else
732 : #endif
733 : {
734 0 : *value = xtrymalloc (n);
735 0 : if (!*value)
736 0 : return gpg_error_from_errno (errno);
737 0 : *valuelen = n;
738 0 : err = read_buffer (context->reader, *value, n);
739 0 : break; /* Ready or error. */
740 : }
741 : }
742 0 : else if (!n && *hdr == 'A')
743 0 : okay = 0;
744 0 : else if (n)
745 : {
746 0 : if (n > context->tmpbufsize)
747 : {
748 0 : xfree (context->tmpbuf);
749 0 : context->tmpbufsize = 0;
750 0 : context->tmpbuf = xtrymalloc (n+1);
751 0 : if (!context->tmpbuf)
752 0 : return gpg_error_from_errno (errno);
753 0 : context->tmpbufsize = n;
754 : }
755 0 : err = read_buffer (context->reader, context->tmpbuf, n);
756 0 : if (err)
757 0 : break;
758 0 : if (*hdr == 'A')
759 : {
760 0 : p = context->tmpbuf;
761 0 : p[n] = 0; /*(we allocated one extra byte for this.)*/
762 : /* fixme: is_cms = 0; */
763 0 : if ( (pend = strchr (p, ';')) )
764 0 : *pend = 0; /* Strip off the extension. */
765 0 : if (!ascii_strcasecmp (p, USERCERTIFICATE))
766 : {
767 0 : if (DBG_LOOKUP)
768 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
769 : USERCERTIFICATE);
770 0 : okay = 1;
771 : }
772 0 : else if (!ascii_strcasecmp (p, CACERTIFICATE))
773 : {
774 0 : if (DBG_LOOKUP)
775 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
776 : CACERTIFICATE);
777 0 : okay = 1;
778 : }
779 0 : else if (!ascii_strcasecmp (p, X509CACERT))
780 : {
781 0 : if (DBG_LOOKUP)
782 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
783 : CACERTIFICATE);
784 0 : okay = 1;
785 : }
786 : /* else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */
787 : /* { */
788 : /* if (DBG_LOOKUP) */
789 : /* log_debug ("fetch_next_cert_ldap: got attribute '%s'\n", */
790 : /* USERSMIMECERTIFICATE); */
791 : /* okay = 1; */
792 : /* is_cms = 1; */
793 : /* } */
794 : else
795 : {
796 0 : if (DBG_LOOKUP)
797 0 : log_debug ("fetch_next_cert_ldap: got attribute '%s'"
798 : " - ignored\n", p);
799 0 : okay = 0;
800 : }
801 : }
802 0 : else if (*hdr == 'E')
803 : {
804 0 : p = context->tmpbuf;
805 0 : p[n] = 0; /*(we allocated one extra byte for this.)*/
806 0 : if (!strcmp (p, "truncated"))
807 : {
808 0 : context->truncated = 1;
809 0 : log_info (_("ldap_search hit the size limit of"
810 : " the server\n"));
811 : }
812 : }
813 : }
814 : }
815 :
816 0 : if (err)
817 : {
818 0 : xfree (*value);
819 0 : *value = NULL;
820 0 : *valuelen = 0;
821 0 : if (gpg_err_code (err) == GPG_ERR_EOF && context->truncated)
822 : {
823 0 : context->truncated = 0; /* So that the next call would return EOF. */
824 0 : err = gpg_error (GPG_ERR_TRUNCATED);
825 : }
826 : }
827 :
828 0 : return err;
829 : }
830 :
831 :
832 : void
833 0 : end_cert_fetch_ldap (cert_fetch_context_t context)
834 : {
835 0 : if (context)
836 : {
837 0 : ksba_reader_t reader = context->reader;
838 :
839 0 : xfree (context->tmpbuf);
840 0 : xfree (context);
841 0 : ldap_wrapper_release_context (reader);
842 0 : ksba_reader_release (reader);
843 : }
844 0 : }
|