LCOV - code coverage report
Current view: top level - dirmngr - ldap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 330 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 12 0.0 %

          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 : }

Generated by: LCOV version 1.11