LCOV - code coverage report
Current view: top level - dirmngr - ks-engine-ldap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 820 0.0 %
Date: 2016-09-12 13:01:59 Functions: 0 18 0.0 %

          Line data    Source code
       1             : /* ks-engine-ldap.c - talk to a LDAP keyserver
       2             :  * Copyright (C) 2001, 2002, 2004, 2005, 2006
       3             :  *               2007  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2015  g10 Code GmbH
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <string.h>
      25             : #include <time.h>
      26             : #include <unistd.h>
      27             : #ifdef HAVE_GETOPT_H
      28             : # include <getopt.h>
      29             : #endif
      30             : #include <stdlib.h>
      31             : #include <errno.h>
      32             : #include <assert.h>
      33             : 
      34             : #ifdef _WIN32
      35             : # include <winsock2.h>
      36             : # include <winldap.h>
      37             : #else
      38             : # ifdef NEED_LBER_H
      39             : #  include <lber.h>
      40             : # endif
      41             : /* For OpenLDAP, to enable the API that we're using. */
      42             : # define LDAP_DEPRECATED 1
      43             : # include <ldap.h>
      44             : #endif
      45             : 
      46             : #include "dirmngr.h"
      47             : #include "misc.h"
      48             : #include "userids.h"
      49             : #include "ks-engine.h"
      50             : #include "ldap-parse-uri.h"
      51             : 
      52             : #ifndef HAVE_TIMEGM
      53             : time_t timegm(struct tm *tm);
      54             : #endif
      55             : 
      56             : /* Convert an LDAP error to a GPG error.  */
      57             : static int
      58           0 : ldap_err_to_gpg_err (int code)
      59             : {
      60             :   gpg_err_code_t ec;
      61             : 
      62           0 :   switch (code)
      63             :     {
      64             : #ifdef LDAP_X_CONNECTING
      65           0 :     case LDAP_X_CONNECTING: ec = GPG_ERR_LDAP_X_CONNECTING; break;
      66             : #endif
      67             : 
      68           0 :     case LDAP_REFERRAL_LIMIT_EXCEEDED: ec = GPG_ERR_LDAP_REFERRAL_LIMIT; break;
      69           0 :     case LDAP_CLIENT_LOOP: ec = GPG_ERR_LDAP_CLIENT_LOOP; break;
      70           0 :     case LDAP_NO_RESULTS_RETURNED: ec = GPG_ERR_LDAP_NO_RESULTS; break;
      71           0 :     case LDAP_CONTROL_NOT_FOUND: ec = GPG_ERR_LDAP_CONTROL_NOT_FOUND; break;
      72           0 :     case LDAP_NOT_SUPPORTED: ec = GPG_ERR_LDAP_NOT_SUPPORTED; break;
      73           0 :     case LDAP_CONNECT_ERROR: ec = GPG_ERR_LDAP_CONNECT; break;
      74           0 :     case LDAP_NO_MEMORY: ec = GPG_ERR_LDAP_NO_MEMORY; break;
      75           0 :     case LDAP_PARAM_ERROR: ec = GPG_ERR_LDAP_PARAM; break;
      76           0 :     case LDAP_USER_CANCELLED: ec = GPG_ERR_LDAP_USER_CANCELLED; break;
      77           0 :     case LDAP_FILTER_ERROR: ec = GPG_ERR_LDAP_FILTER; break;
      78           0 :     case LDAP_AUTH_UNKNOWN: ec = GPG_ERR_LDAP_AUTH_UNKNOWN; break;
      79           0 :     case LDAP_TIMEOUT: ec = GPG_ERR_LDAP_TIMEOUT; break;
      80           0 :     case LDAP_DECODING_ERROR: ec = GPG_ERR_LDAP_DECODING; break;
      81           0 :     case LDAP_ENCODING_ERROR: ec = GPG_ERR_LDAP_ENCODING; break;
      82           0 :     case LDAP_LOCAL_ERROR: ec = GPG_ERR_LDAP_LOCAL; break;
      83           0 :     case LDAP_SERVER_DOWN: ec = GPG_ERR_LDAP_SERVER_DOWN; break;
      84             : 
      85           0 :     case LDAP_SUCCESS: ec = GPG_ERR_LDAP_SUCCESS; break;
      86             : 
      87           0 :     case LDAP_OPERATIONS_ERROR: ec = GPG_ERR_LDAP_OPERATIONS; break;
      88           0 :     case LDAP_PROTOCOL_ERROR: ec = GPG_ERR_LDAP_PROTOCOL; break;
      89           0 :     case LDAP_TIMELIMIT_EXCEEDED: ec = GPG_ERR_LDAP_TIMELIMIT; break;
      90           0 :     case LDAP_SIZELIMIT_EXCEEDED: ec = GPG_ERR_LDAP_SIZELIMIT; break;
      91           0 :     case LDAP_COMPARE_FALSE: ec = GPG_ERR_LDAP_COMPARE_FALSE; break;
      92           0 :     case LDAP_COMPARE_TRUE: ec = GPG_ERR_LDAP_COMPARE_TRUE; break;
      93           0 :     case LDAP_AUTH_METHOD_NOT_SUPPORTED: ec=GPG_ERR_LDAP_UNSUPPORTED_AUTH;break;
      94           0 :     case LDAP_STRONG_AUTH_REQUIRED: ec = GPG_ERR_LDAP_STRONG_AUTH_RQRD; break;
      95           0 :     case LDAP_PARTIAL_RESULTS: ec = GPG_ERR_LDAP_PARTIAL_RESULTS; break;
      96           0 :     case LDAP_REFERRAL: ec = GPG_ERR_LDAP_REFERRAL; break;
      97             : 
      98             : #ifdef LDAP_ADMINLIMIT_EXCEEDED
      99           0 :     case LDAP_ADMINLIMIT_EXCEEDED: ec = GPG_ERR_LDAP_ADMINLIMIT; break;
     100             : #endif
     101             : 
     102             : #ifdef LDAP_UNAVAILABLE_CRITICAL_EXTENSION
     103             :     case LDAP_UNAVAILABLE_CRITICAL_EXTENSION:
     104           0 :                                ec = GPG_ERR_LDAP_UNAVAIL_CRIT_EXTN; break;
     105             : #endif
     106             : 
     107           0 :     case LDAP_CONFIDENTIALITY_REQUIRED: ec = GPG_ERR_LDAP_CONFIDENT_RQRD; break;
     108           0 :     case LDAP_SASL_BIND_IN_PROGRESS: ec = GPG_ERR_LDAP_SASL_BIND_INPROG; break;
     109           0 :     case LDAP_NO_SUCH_ATTRIBUTE: ec = GPG_ERR_LDAP_NO_SUCH_ATTRIBUTE; break;
     110           0 :     case LDAP_UNDEFINED_TYPE: ec = GPG_ERR_LDAP_UNDEFINED_TYPE; break;
     111           0 :     case LDAP_INAPPROPRIATE_MATCHING: ec = GPG_ERR_LDAP_BAD_MATCHING; break;
     112           0 :     case LDAP_CONSTRAINT_VIOLATION: ec = GPG_ERR_LDAP_CONST_VIOLATION; break;
     113             : 
     114             : #ifdef LDAP_TYPE_OR_VALUE_EXISTS
     115           0 :     case LDAP_TYPE_OR_VALUE_EXISTS: ec = GPG_ERR_LDAP_TYPE_VALUE_EXISTS; break;
     116             : #endif
     117             : 
     118           0 :     case LDAP_INVALID_SYNTAX: ec = GPG_ERR_LDAP_INV_SYNTAX; break;
     119           0 :     case LDAP_NO_SUCH_OBJECT: ec = GPG_ERR_LDAP_NO_SUCH_OBJ; break;
     120           0 :     case LDAP_ALIAS_PROBLEM: ec = GPG_ERR_LDAP_ALIAS_PROBLEM; break;
     121           0 :     case LDAP_INVALID_DN_SYNTAX: ec = GPG_ERR_LDAP_INV_DN_SYNTAX; break;
     122           0 :     case LDAP_IS_LEAF: ec = GPG_ERR_LDAP_IS_LEAF; break;
     123           0 :     case LDAP_ALIAS_DEREF_PROBLEM: ec = GPG_ERR_LDAP_ALIAS_DEREF; break;
     124             : 
     125             : #ifdef LDAP_X_PROXY_AUTHZ_FAILURE
     126           0 :     case LDAP_X_PROXY_AUTHZ_FAILURE: ec = GPG_ERR_LDAP_X_PROXY_AUTH_FAIL; break;
     127             : #endif
     128             : 
     129           0 :     case LDAP_INAPPROPRIATE_AUTH: ec = GPG_ERR_LDAP_BAD_AUTH; break;
     130           0 :     case LDAP_INVALID_CREDENTIALS: ec = GPG_ERR_LDAP_INV_CREDENTIALS; break;
     131             : 
     132             : #ifdef LDAP_INSUFFICIENT_ACCESS
     133           0 :     case LDAP_INSUFFICIENT_ACCESS: ec = GPG_ERR_LDAP_INSUFFICIENT_ACC; break;
     134             : #endif
     135             : 
     136           0 :     case LDAP_BUSY: ec = GPG_ERR_LDAP_BUSY; break;
     137           0 :     case LDAP_UNAVAILABLE: ec = GPG_ERR_LDAP_UNAVAILABLE; break;
     138           0 :     case LDAP_UNWILLING_TO_PERFORM: ec = GPG_ERR_LDAP_UNWILL_TO_PERFORM; break;
     139           0 :     case LDAP_LOOP_DETECT: ec = GPG_ERR_LDAP_LOOP_DETECT; break;
     140           0 :     case LDAP_NAMING_VIOLATION: ec = GPG_ERR_LDAP_NAMING_VIOLATION; break;
     141           0 :     case LDAP_OBJECT_CLASS_VIOLATION: ec = GPG_ERR_LDAP_OBJ_CLS_VIOLATION; break;
     142           0 :     case LDAP_NOT_ALLOWED_ON_NONLEAF: ec=GPG_ERR_LDAP_NOT_ALLOW_NONLEAF;break;
     143           0 :     case LDAP_NOT_ALLOWED_ON_RDN: ec = GPG_ERR_LDAP_NOT_ALLOW_ON_RDN; break;
     144           0 :     case LDAP_ALREADY_EXISTS: ec = GPG_ERR_LDAP_ALREADY_EXISTS; break;
     145           0 :     case LDAP_NO_OBJECT_CLASS_MODS: ec = GPG_ERR_LDAP_NO_OBJ_CLASS_MODS; break;
     146           0 :     case LDAP_RESULTS_TOO_LARGE: ec = GPG_ERR_LDAP_RESULTS_TOO_LARGE; break;
     147           0 :     case LDAP_AFFECTS_MULTIPLE_DSAS: ec = GPG_ERR_LDAP_AFFECTS_MULT_DSAS; break;
     148             : 
     149             : #ifdef LDAP_VLV_ERROR
     150           0 :     case LDAP_VLV_ERROR: ec = GPG_ERR_LDAP_VLV; break;
     151             : #endif
     152             : 
     153           0 :     case LDAP_OTHER: ec = GPG_ERR_LDAP_OTHER; break;
     154             : 
     155             : #ifdef LDAP_CUP_RESOURCES_EXHAUSTED
     156           0 :     case LDAP_CUP_RESOURCES_EXHAUSTED: ec=GPG_ERR_LDAP_CUP_RESOURCE_LIMIT;break;
     157           0 :     case LDAP_CUP_SECURITY_VIOLATION: ec=GPG_ERR_LDAP_CUP_SEC_VIOLATION; break;
     158           0 :     case LDAP_CUP_INVALID_DATA: ec = GPG_ERR_LDAP_CUP_INV_DATA; break;
     159           0 :     case LDAP_CUP_UNSUPPORTED_SCHEME: ec = GPG_ERR_LDAP_CUP_UNSUP_SCHEME; break;
     160           0 :     case LDAP_CUP_RELOAD_REQUIRED: ec = GPG_ERR_LDAP_CUP_RELOAD; break;
     161             : #endif
     162             : 
     163             : #ifdef LDAP_CANCELLED
     164           0 :     case LDAP_CANCELLED: ec = GPG_ERR_LDAP_CANCELLED; break;
     165             : #endif
     166             : 
     167             : #ifdef LDAP_NO_SUCH_OPERATION
     168           0 :     case LDAP_NO_SUCH_OPERATION: ec = GPG_ERR_LDAP_NO_SUCH_OPERATION; break;
     169             : #endif
     170             : 
     171             : #ifdef LDAP_TOO_LATE
     172           0 :     case LDAP_TOO_LATE: ec = GPG_ERR_LDAP_TOO_LATE; break;
     173             : #endif
     174             : 
     175             : #ifdef LDAP_CANNOT_CANCEL
     176           0 :     case LDAP_CANNOT_CANCEL: ec = GPG_ERR_LDAP_CANNOT_CANCEL; break;
     177             : #endif
     178             : 
     179             : #ifdef LDAP_ASSERTION_FAILED
     180           0 :     case LDAP_ASSERTION_FAILED: ec = GPG_ERR_LDAP_ASSERTION_FAILED; break;
     181             : #endif
     182             : 
     183             : #ifdef LDAP_PROXIED_AUTHORIZATION_DENIED
     184             :     case LDAP_PROXIED_AUTHORIZATION_DENIED:
     185           0 :                                       ec = GPG_ERR_LDAP_PROX_AUTH_DENIED; break;
     186             : #endif
     187             : 
     188             :     default:
     189             : #if defined(LDAP_E_ERROR) && defined(LDAP_X_ERROR)
     190           0 :       if (LDAP_E_ERROR (code))
     191           0 :         ec = GPG_ERR_LDAP_E_GENERAL;
     192           0 :       else if (LDAP_X_ERROR (code))
     193           0 :         ec = GPG_ERR_LDAP_X_GENERAL;
     194             :       else
     195             : #endif
     196           0 :         ec = GPG_ERR_LDAP_GENERAL;
     197           0 :       break;
     198             :     }
     199             : 
     200           0 :   return ec;
     201             : }
     202             : 
     203             : /* Retrieve an LDAP error and return it's GPG equivalent.  */
     204             : static int
     205           0 : ldap_to_gpg_err (LDAP *ld)
     206             : {
     207             : #if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER)
     208             :   int err;
     209             : 
     210           0 :   if (ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &err) == 0)
     211           0 :     return ldap_err_to_gpg_err (err);
     212             :   else
     213           0 :     return GPG_ERR_GENERAL;
     214             : #elif defined(HAVE_LDAP_LD_ERRNO)
     215             :   return ldap_err_to_gpg_err (ld->ld_errno);
     216             : #else
     217             :   /* We should never get here since the LDAP library should always
     218             :      have either ldap_get_option or ld_errno, but just in case... */
     219             :   return GPG_ERR_INTERNAL;
     220             : #endif
     221             : }
     222             : 
     223             : static time_t
     224           0 : ldap2epochtime (const char *timestr)
     225             : {
     226             :   struct tm pgptime;
     227             :   time_t answer;
     228             : 
     229           0 :   memset (&pgptime, 0, sizeof(pgptime));
     230             : 
     231             :   /* YYYYMMDDHHmmssZ */
     232             : 
     233           0 :   sscanf (timestr, "%4d%2d%2d%2d%2d%2d",
     234             :           &pgptime.tm_year,
     235             :           &pgptime.tm_mon,
     236             :           &pgptime.tm_mday,
     237             :           &pgptime.tm_hour,
     238             :           &pgptime.tm_min,
     239             :           &pgptime.tm_sec);
     240             : 
     241           0 :   pgptime.tm_year -= 1900;
     242           0 :   pgptime.tm_isdst = -1;
     243           0 :   pgptime.tm_mon--;
     244             : 
     245             :   /* mktime() takes the timezone into account, so we use timegm() */
     246             : 
     247           0 :   answer = timegm (&pgptime);
     248             : 
     249           0 :   return answer;
     250             : }
     251             : 
     252             : /* Caller must free the result.  */
     253             : static char *
     254           0 : tm2ldaptime (struct tm *tm)
     255             : {
     256           0 :   struct tm tmp = *tm;
     257             :   char buf[16];
     258             : 
     259             :   /* YYYYMMDDHHmmssZ */
     260             : 
     261           0 :   tmp.tm_year += 1900;
     262           0 :   tmp.tm_mon ++;
     263             : 
     264           0 :   snprintf (buf, sizeof buf, "%04d%02d%02d%02d%02d%02dZ",
     265             :            tmp.tm_year,
     266             :            tmp.tm_mon,
     267             :            tmp.tm_mday,
     268             :            tmp.tm_hour,
     269             :            tmp.tm_min,
     270             :            tmp.tm_sec);
     271             : 
     272           0 :   return xstrdup (buf);
     273             : }
     274             : 
     275             : #if 0
     276             : /* Caller must free */
     277             : static char *
     278             : epoch2ldaptime (time_t stamp)
     279             : {
     280             :   struct tm tm;
     281             :   if (gmtime_r (&stamp, &tm))
     282             :     return tm2ldaptime (&tm);
     283             :   else
     284             :     return xstrdup ("INVALID TIME");
     285             : }
     286             : #endif
     287             : 
     288             : /* Print a help output for the schemata supported by this module. */
     289             : gpg_error_t
     290           0 : ks_ldap_help (ctrl_t ctrl, parsed_uri_t uri)
     291             : {
     292           0 :   const char const data[] =
     293             :     "Handler for LDAP URLs:\n"
     294             :     "  ldap://host:port/[BASEDN]???[bindname=BINDNAME,password=PASSWORD]\n"
     295             :     "\n"
     296             :     "Note: basedn, bindname and password need to be percent escaped. In\n"
     297             :     "particular, spaces need to be replaced with %20 and commas with %2c.\n"
     298             :     "bindname will typically be of the form:\n"
     299             :     "\n"
     300             :     "  uid=user%2cou=PGP%20Users%2cdc=EXAMPLE%2cdc=ORG\n"
     301             :     "\n"
     302             :     "The ldaps:// and ldapi:// schemes are also supported.  If ldaps is used\n"
     303             :     "then the server's certificate will be checked.  If it is not valid, any\n"
     304             :     "operation will be aborted.\n"
     305             :     "\n"
     306             :     "Supported methods: search, get, put\n";
     307             :   gpg_error_t err;
     308             : 
     309           0 :   if(!uri)
     310           0 :     err = ks_print_help (ctrl, "  ldap");
     311           0 :   else if (strcmp (uri->scheme, "ldap") == 0
     312           0 :       || strcmp (uri->scheme, "ldaps") == 0
     313           0 :       || strcmp (uri->scheme, "ldapi") == 0)
     314           0 :     err = ks_print_help (ctrl, data);
     315             :   else
     316           0 :     err = 0;
     317             : 
     318           0 :   return err;
     319             : }
     320             : 
     321             : /* Convert a keyspec to a filter.  Return an error if the keyspec is
     322             :    bad or is not supported.  The filter is escaped and returned in
     323             :    *filter.  It is the caller's responsibility to free *filter.
     324             :    *filter is only set if this function returns success (i.e., 0).  */
     325             : static gpg_error_t
     326           0 : keyspec_to_ldap_filter (const char *keyspec, char **filter, int only_exact)
     327             : {
     328             :   /* Remove search type indicator and adjust PATTERN accordingly.
     329             :      Note: don't include a preceding 0x when searching by keyid.  */
     330             : 
     331             :   /* XXX: Should we include disabled / revoke options?  */
     332             :   KEYDB_SEARCH_DESC desc;
     333           0 :   char *f = NULL;
     334           0 :   char *freeme = NULL;
     335             : 
     336           0 :   gpg_error_t err = classify_user_id (keyspec, &desc, 1);
     337           0 :   if (err)
     338           0 :     return err;
     339             : 
     340           0 :   switch (desc.mode)
     341             :     {
     342             :     case KEYDB_SEARCH_MODE_EXACT:
     343           0 :       f = xasprintf ("(pgpUserID=%s)",
     344           0 :                      (freeme = ldap_escape_filter (desc.u.name)));
     345           0 :       break;
     346             : 
     347             :     case KEYDB_SEARCH_MODE_SUBSTR:
     348           0 :       if (! only_exact)
     349           0 :         f = xasprintf ("(pgpUserID=*%s*)",
     350           0 :                        (freeme = ldap_escape_filter (desc.u.name)));
     351           0 :       break;
     352             : 
     353             :     case KEYDB_SEARCH_MODE_MAIL:
     354           0 :       if (! only_exact)
     355           0 :         f = xasprintf ("(pgpUserID=*<%s>*)",
     356           0 :                        (freeme = ldap_escape_filter (desc.u.name)));
     357           0 :       break;
     358             : 
     359             :     case KEYDB_SEARCH_MODE_MAILSUB:
     360           0 :       if (! only_exact)
     361           0 :         f = xasprintf ("(pgpUserID=*<*%s*>*)",
     362           0 :                        (freeme = ldap_escape_filter (desc.u.name)));
     363           0 :       break;
     364             : 
     365             :     case KEYDB_SEARCH_MODE_MAILEND:
     366           0 :       if (! only_exact)
     367           0 :         f = xasprintf ("(pgpUserID=*<*%s>*)",
     368           0 :                        (freeme = ldap_escape_filter (desc.u.name)));
     369           0 :       break;
     370             : 
     371             :     case KEYDB_SEARCH_MODE_SHORT_KID:
     372           0 :       f = xasprintf ("(pgpKeyID=%08lX)", (ulong) desc.u.kid[1]);
     373           0 :       break;
     374             :     case KEYDB_SEARCH_MODE_LONG_KID:
     375           0 :       f = xasprintf ("(pgpCertID=%08lX%08lX)",
     376           0 :                      (ulong) desc.u.kid[0], (ulong) desc.u.kid[1]);
     377           0 :       break;
     378             : 
     379             :     case KEYDB_SEARCH_MODE_FPR16:
     380             :     case KEYDB_SEARCH_MODE_FPR20:
     381             :     case KEYDB_SEARCH_MODE_FPR:
     382             :     case KEYDB_SEARCH_MODE_ISSUER:
     383             :     case KEYDB_SEARCH_MODE_ISSUER_SN:
     384             :     case KEYDB_SEARCH_MODE_SN:
     385             :     case KEYDB_SEARCH_MODE_SUBJECT:
     386             :     case KEYDB_SEARCH_MODE_KEYGRIP:
     387             :     case KEYDB_SEARCH_MODE_WORDS:
     388             :     case KEYDB_SEARCH_MODE_FIRST:
     389             :     case KEYDB_SEARCH_MODE_NEXT:
     390             :     default:
     391           0 :       break;
     392             :     }
     393             : 
     394           0 :   xfree (freeme);
     395             : 
     396           0 :   if (! f)
     397             :     {
     398           0 :       log_error ("Unsupported search mode.\n");
     399           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     400             :     }
     401             : 
     402           0 :   *filter = f;
     403             : 
     404           0 :   return 0;
     405             : }
     406             : 
     407             : 
     408             : 
     409             : /* Connect to an LDAP server and interrogate it.
     410             : 
     411             :      - uri describes the server to connect to and various options
     412             :        including whether to use TLS and the username and password (see
     413             :        ldap_parse_uri for a description of the various fields).
     414             : 
     415             :    This function returns:
     416             : 
     417             :      - The ldap connection handle in *LDAP_CONNP.
     418             : 
     419             :      - The base DN for the PGP key space by querying the
     420             :        pgpBaseKeySpaceDN attribute (This is normally
     421             :        'ou=PGP Keys,dc=EXAMPLE,dc=ORG').
     422             : 
     423             :      - The attribute to lookup to find the pgp key.  This is either
     424             :        'pgpKey' or 'pgpKeyV2'.
     425             : 
     426             :      - Whether this is a real ldap server.  (It's unclear what this
     427             :        exactly means.)
     428             : 
     429             :    The values are returned in the passed variables.  If you pass NULL,
     430             :    then the value won't be returned.  It is the caller's
     431             :    responsibility to release *LDAP_CONNP with ldap_unbind and xfree
     432             :    *BASEDNP and *PGPKEYATTRP.
     433             : 
     434             :    If this function successfully interrogated the server, it returns
     435             :    0.  If there was an LDAP error, it returns the LDAP error code.  If
     436             :    an error occurred, *basednp, etc., are undefined (and don't need to
     437             :    be freed.)
     438             : 
     439             :    If no LDAP error occurred, you still need to check that *basednp is
     440             :    valid.  If it is NULL, then the server does not appear to be an
     441             :    OpenPGP Keyserver.  In this case, you also do not need to xfree
     442             :    *pgpkeyattrp.  */
     443             : static int
     444           0 : my_ldap_connect (parsed_uri_t uri, LDAP **ldap_connp,
     445             :                  char **basednp, char **pgpkeyattrp, int *real_ldapp)
     446             : {
     447           0 :   int err = 0;
     448             : 
     449           0 :   LDAP *ldap_conn = NULL;
     450             : 
     451           0 :   char *user = uri->auth;
     452           0 :   struct uri_tuple_s *password_param = uri_query_lookup (uri, "password");
     453           0 :   char *password = password_param ? password_param->value : NULL;
     454             : 
     455           0 :   char *basedn = NULL;
     456             :   /* Whether to look for the pgpKey or pgpKeyv2 attribute.  */
     457           0 :   char *pgpkeyattr = "pgpKey";
     458           0 :   int real_ldap = 0;
     459             : 
     460           0 :   log_debug ("my_ldap_connect(%s:%d/%s????%s%s%s%s%s)\n",
     461           0 :              uri->host, uri->port,
     462           0 :              uri->path ?: "",
     463           0 :              uri->auth ? "bindname=" : "", uri->auth ?: "",
     464           0 :              uri->auth && password ? "," : "",
     465           0 :              password ? "password=" : "", password ?: "");
     466             : 
     467             :   /* If the uri specifies a secure connection and we don't support
     468             :      TLS, then fail; don't silently revert to an insecure
     469             :      connection.  */
     470           0 :   if (uri->use_tls)
     471             :     {
     472             : #ifndef HAVE_LDAP_START_TLS_S
     473             :       log_error ("Can't use LDAP to connect to the server: no TLS support.");
     474             :       err = GPG_ERR_LDAP_NOT_SUPPORTED;
     475             :       goto out;
     476             : #endif
     477             :     }
     478             : 
     479           0 :   ldap_conn = ldap_init (uri->host, uri->port);
     480           0 :   if (! ldap_conn)
     481             :     {
     482           0 :       err = gpg_err_code_from_syserror ();
     483           0 :       log_error ("Failed to open connection to LDAP server (%s://%s:%d)\n",
     484           0 :                  uri->scheme, uri->host, uri->port);
     485           0 :       goto out;
     486             :     }
     487             : 
     488             : #ifdef HAVE_LDAP_SET_OPTION
     489             :   {
     490           0 :     int ver = LDAP_VERSION3;
     491             : 
     492           0 :     err = ldap_set_option (ldap_conn, LDAP_OPT_PROTOCOL_VERSION, &ver);
     493           0 :     if (err != LDAP_SUCCESS)
     494             :       {
     495           0 :         log_error ("gpgkeys: unable to go to LDAP 3: %s\n",
     496             :                    ldap_err2string (err));
     497           0 :         goto out;
     498             :       }
     499             :   }
     500             : #endif
     501             : 
     502             :   /* XXX: It would be nice to have an option to provide the server's
     503             :      certificate.  */
     504             : #if 0
     505             : #if defined(LDAP_OPT_X_TLS_CACERTFILE) && defined(HAVE_LDAP_SET_OPTION)
     506             :   err = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, ca_cert_file);
     507             :   if (err)
     508             :     {
     509             :       log_error ("unable to set ca-cert-file to '%s': %s\n",
     510             :                  ca_cert_file, ldap_err2string (err));
     511             :       goto out;
     512             :     }
     513             : #endif /* LDAP_OPT_X_TLS_CACERTFILE && HAVE_LDAP_SET_OPTION */
     514             : #endif
     515             : 
     516             : #ifndef HAVE_LDAP_START_TLS_S
     517             :   if (uri->use_tls)
     518             :     {
     519             :       /* XXX: We need an option to determine whether to abort if the
     520             :          certificate is bad or not.  Right now we conservatively
     521             :          default to checking the certificate and aborting.  */
     522             :       int check_cert = LDAP_OPT_X_TLS_HARD; /* LDAP_OPT_X_TLS_NEVER */
     523             : 
     524             :       err = ldap_set_option (ldap_conn,
     525             :                              LDAP_OPT_X_TLS_REQUIRE_CERT, &check_cert);
     526             :       if (err)
     527             :         {
     528             :           log_error ("Failed to set TLS option on LDAP connection.\n");
     529             :           goto out;
     530             :         }
     531             : 
     532             :       err = ldap_start_tls_s (ldap_conn, NULL, NULL);
     533             :       if (err)
     534             :         {
     535             :           log_error ("Failed to connect to LDAP server with TLS.\n");
     536             :           goto out;
     537             :         }
     538             :     }
     539             : #endif
     540             : 
     541             :   /* By default we don't bind as there is usually no need to.  */
     542           0 :   if (uri->auth)
     543             :     {
     544           0 :       log_debug ("LDAP bind to %s, password %s\n",
     545             :                  user, password ? ">not shown<" : ">none<");
     546             : 
     547           0 :       err = ldap_simple_bind_s (ldap_conn, user, password);
     548           0 :       if (err != LDAP_SUCCESS)
     549             :         {
     550           0 :           log_error ("Internal LDAP bind error: %s\n",
     551             :                      ldap_err2string (err));
     552           0 :           goto out;
     553             :         }
     554             :     }
     555             : 
     556           0 :   if (uri->path && *uri->path)
     557             :     /* User specified base DN.  */
     558             :     {
     559           0 :       basedn = xstrdup (uri->path);
     560             : 
     561             :       /* If the user specifies a base DN, then we know the server is a
     562             :          real LDAP server.  */
     563           0 :       real_ldap = 1;
     564             :     }
     565             :   else
     566             :     {
     567           0 :       LDAPMessage *res = NULL;
     568             :       /* Look for namingContexts.  */
     569           0 :       char *attr[] = { "namingContexts", NULL };
     570             : 
     571           0 :       err = ldap_search_s (ldap_conn, "", LDAP_SCOPE_BASE,
     572             :                            "(objectClass=*)", attr, 0, &res);
     573           0 :       if (err == LDAP_SUCCESS)
     574             :         {
     575           0 :           char **context = ldap_get_values (ldap_conn, res, "namingContexts");
     576           0 :           if (context)
     577             :             /* We found some, so try each namingContext as the search
     578             :                base and look for pgpBaseKeySpaceDN.  Because we found
     579             :                this, we know we're talking to a regular-ish LDAP
     580             :                server and not an LDAP keyserver.  */
     581             :             {
     582             :               int i;
     583           0 :               char *attr2[] =
     584             :                 { "pgpBaseKeySpaceDN", "pgpVersion", "pgpSoftware", NULL };
     585             : 
     586           0 :               real_ldap = 1;
     587             : 
     588           0 :               for (i = 0; context[i] && ! basedn; i++)
     589             :                 {
     590             :                   char **vals;
     591             :                   LDAPMessage *si_res;
     592             : 
     593             :                   {
     594           0 :                     char *object = xasprintf ("cn=pgpServerInfo,%s",
     595           0 :                                               context[i]);
     596           0 :                     err = ldap_search_s (ldap_conn, object, LDAP_SCOPE_BASE,
     597             :                                          "(objectClass=*)", attr2, 0, &si_res);
     598           0 :                     xfree (object);
     599             :                   }
     600             : 
     601           0 :                   if (err == LDAP_SUCCESS)
     602             :                     {
     603           0 :                       vals = ldap_get_values (ldap_conn, si_res,
     604             :                                               "pgpBaseKeySpaceDN");
     605           0 :                       if (vals)
     606             :                         {
     607           0 :                           basedn = xtrystrdup (vals[0]);
     608           0 :                           ldap_value_free (vals);
     609             :                         }
     610             : 
     611           0 :                       vals = ldap_get_values (ldap_conn, si_res,
     612             :                                               "pgpSoftware");
     613           0 :                       if (vals)
     614             :                         {
     615           0 :                           log_debug ("Server: \t%s\n", vals[0]);
     616           0 :                           ldap_value_free (vals);
     617             :                         }
     618             : 
     619           0 :                       vals = ldap_get_values (ldap_conn, si_res,
     620             :                                               "pgpVersion");
     621           0 :                       if (vals)
     622             :                         {
     623           0 :                           log_debug ("Version:\t%s\n", vals[0]);
     624           0 :                           ldap_value_free (vals);
     625             :                         }
     626             :                     }
     627             : 
     628             :                   /* From man ldap_search_s: "res parameter of
     629             :                      ldap_search_ext_s() and ldap_search_s() should be
     630             :                      freed with ldap_msgfree() regardless of return
     631             :                      value of these functions.  */
     632           0 :                   ldap_msgfree (si_res);
     633             :                 }
     634             : 
     635           0 :               ldap_value_free (context);
     636             :             }
     637             :         }
     638             :       else
     639             :         {
     640             :           /* We don't have an answer yet, which means the server might
     641             :              be an LDAP keyserver. */
     642             :           char **vals;
     643           0 :           LDAPMessage *si_res = NULL;
     644             : 
     645           0 :           char *attr2[] = { "pgpBaseKeySpaceDN", "version", "software", NULL };
     646             : 
     647           0 :           err = ldap_search_s (ldap_conn, "cn=pgpServerInfo", LDAP_SCOPE_BASE,
     648             :                                "(objectClass=*)", attr2, 0, &si_res);
     649           0 :           if (err == LDAP_SUCCESS)
     650             :             {
     651             :               /* For the LDAP keyserver, this is always
     652             :                  "OU=ACTIVE,O=PGP KEYSPACE,C=US", but it might not be
     653             :                  in the future. */
     654             : 
     655           0 :               vals = ldap_get_values (ldap_conn, si_res, "baseKeySpaceDN");
     656           0 :               if (vals)
     657             :                 {
     658           0 :                   basedn = xtrystrdup (vals[0]);
     659           0 :                   ldap_value_free (vals);
     660             :                 }
     661             : 
     662           0 :               vals = ldap_get_values (ldap_conn, si_res, "software");
     663           0 :               if (vals)
     664             :                 {
     665           0 :                   log_debug ("ldap: Server: \t%s\n", vals[0]);
     666           0 :                   ldap_value_free (vals);
     667             :                 }
     668             : 
     669           0 :               vals = ldap_get_values (ldap_conn, si_res, "version");
     670           0 :               if (vals)
     671             :                 {
     672           0 :                   log_debug ("ldap: Version:\t%s\n", vals[0]);
     673             : 
     674             :                   /* If the version is high enough, use the new
     675             :                      pgpKeyV2 attribute.  This design is iffy at best,
     676             :                      but it matches how PGP does it.  I figure the NAI
     677             :                      folks assumed that there would never be an LDAP
     678             :                      keyserver vendor with a different numbering
     679             :                      scheme. */
     680           0 :                   if (atoi (vals[0]) > 1)
     681           0 :                     pgpkeyattr = "pgpKeyV2";
     682             : 
     683           0 :                   ldap_value_free (vals);
     684             :                 }
     685             :             }
     686             : 
     687           0 :           ldap_msgfree (si_res);
     688             :         }
     689             : 
     690             :       /* From man ldap_search_s: "res parameter of ldap_search_ext_s()
     691             :          and ldap_search_s() should be freed with ldap_msgfree()
     692             :          regardless of return value of these functions.  */
     693           0 :       ldap_msgfree (res);
     694             :     }
     695             : 
     696             :  out:
     697           0 :   if (! err)
     698             :     {
     699           0 :       log_debug ("ldap_conn: %p\n", ldap_conn);
     700           0 :       log_debug ("real_ldap: %d\n", real_ldap);
     701           0 :       log_debug ("basedn: %s\n", basedn);
     702           0 :       log_debug ("pgpkeyattr: %s\n", pgpkeyattr);
     703             :     }
     704             : 
     705           0 :   if (! err && real_ldapp)
     706           0 :     *real_ldapp = real_ldap;
     707             : 
     708           0 :   if (err)
     709           0 :     xfree (basedn);
     710             :   else
     711             :     {
     712           0 :       if (pgpkeyattrp)
     713             :         {
     714           0 :           if (basedn)
     715           0 :             *pgpkeyattrp = xstrdup (pgpkeyattr);
     716             :           else
     717           0 :             *pgpkeyattrp = NULL;
     718             :         }
     719             : 
     720           0 :       if (basednp)
     721           0 :         *basednp = basedn;
     722             :       else
     723           0 :         xfree (basedn);
     724             :     }
     725             : 
     726           0 :   if (err)
     727             :     {
     728           0 :       if (ldap_conn)
     729           0 :         ldap_unbind (ldap_conn);
     730             :     }
     731             :   else
     732           0 :     *ldap_connp = ldap_conn;
     733             : 
     734           0 :   return err;
     735             : }
     736             : 
     737             : /* Extract keys from an LDAP reply and write them out to the output
     738             :    stream OUTPUT in a format GnuPG can import (either the OpenPGP
     739             :    binary format or armored format).  */
     740             : static void
     741           0 : extract_keys (estream_t output,
     742             :               LDAP *ldap_conn, const char *certid, LDAPMessage *message)
     743             : {
     744             :   char **vals;
     745             : 
     746           0 :   es_fprintf (output, "INFO %s BEGIN\n", certid);
     747           0 :   es_fprintf (output, "pub:%s:", certid);
     748             : 
     749             :   /* Note: ldap_get_values returns a NULL terminates array of
     750             :      strings.  */
     751           0 :   vals = ldap_get_values (ldap_conn, message, "pgpkeytype");
     752           0 :   if (vals && vals[0])
     753             :     {
     754           0 :       if (strcmp (vals[0], "RSA") == 0)
     755           0 :         es_fprintf  (output, "1");
     756           0 :       else if (strcmp (vals[0],"DSS/DH") == 0)
     757           0 :         es_fprintf (output, "17");
     758           0 :       ldap_value_free (vals);
     759             :     }
     760             : 
     761           0 :   es_fprintf (output, ":");
     762             : 
     763           0 :   vals = ldap_get_values (ldap_conn, message, "pgpkeysize");
     764           0 :   if (vals && vals[0])
     765             :     {
     766           0 :       int v = atoi (vals[0]);
     767           0 :       if (v > 0)
     768           0 :         es_fprintf (output, "%d", v);
     769           0 :       ldap_value_free (vals);
     770             :     }
     771             : 
     772           0 :   es_fprintf (output, ":");
     773             : 
     774           0 :   vals = ldap_get_values (ldap_conn, message, "pgpkeycreatetime");
     775           0 :   if (vals && vals[0])
     776             :     {
     777           0 :       if (strlen (vals[0]) == 15)
     778           0 :         es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
     779           0 :       ldap_value_free (vals);
     780             :     }
     781             : 
     782           0 :   es_fprintf (output, ":");
     783             : 
     784           0 :   vals = ldap_get_values (ldap_conn, message, "pgpkeyexpiretime");
     785           0 :   if (vals && vals[0])
     786             :     {
     787           0 :       if (strlen (vals[0]) == 15)
     788           0 :         es_fprintf (output, "%u", (unsigned int) ldap2epochtime (vals[0]));
     789           0 :       ldap_value_free (vals);
     790             :     }
     791             : 
     792           0 :   es_fprintf (output, ":");
     793             : 
     794           0 :   vals = ldap_get_values (ldap_conn, message, "pgprevoked");
     795           0 :   if (vals && vals[0])
     796             :     {
     797           0 :       if (atoi (vals[0]) == 1)
     798           0 :         es_fprintf (output, "r");
     799           0 :       ldap_value_free (vals);
     800             :     }
     801             : 
     802           0 :   es_fprintf (output, "\n");
     803             : 
     804           0 :   vals = ldap_get_values (ldap_conn, message, "pgpuserid");
     805           0 :   if (vals && vals[0])
     806             :     {
     807             :       int i;
     808           0 :       for (i = 0; vals[i]; i++)
     809           0 :         es_fprintf (output, "uid:%s\n", vals[i]);
     810           0 :       ldap_value_free (vals);
     811             :     }
     812             : 
     813           0 :   es_fprintf (output, "INFO %s END\n", certid);
     814           0 : }
     815             : 
     816             : /* Get the key described key the KEYSPEC string from the keyserver
     817             :    identified by URI.  On success R_FP has an open stream to read the
     818             :    data.  */
     819             : gpg_error_t
     820           0 : ks_ldap_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec,
     821             :              estream_t *r_fp)
     822             : {
     823           0 :   gpg_error_t err = 0;
     824             :   int ldap_err;
     825             : 
     826           0 :   char *filter = NULL;
     827             : 
     828           0 :   LDAP *ldap_conn = NULL;
     829             : 
     830           0 :   char *basedn = NULL;
     831           0 :   char *pgpkeyattr = NULL;
     832             : 
     833           0 :   estream_t fp = NULL;
     834             : 
     835           0 :   LDAPMessage *message = NULL;
     836             : 
     837             :   (void) ctrl;
     838             : 
     839           0 :   if (opt.use_tor)
     840             :     {
     841             :       /* For now we do not support LDAP over Tor.  */
     842           0 :       log_error (_("LDAP access not possible due to Tor mode\n"));
     843           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     844             :     }
     845             : 
     846             :   /* Before connecting to the server, make sure we have a sane
     847             :      keyspec.  If not, there is no need to establish a network
     848             :      connection.  */
     849           0 :   err = keyspec_to_ldap_filter (keyspec, &filter, 1);
     850           0 :   if (err)
     851           0 :     return (err);
     852             : 
     853             :   /* Make sure we are talking to an OpenPGP LDAP server.  */
     854           0 :   ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, &pgpkeyattr, NULL);
     855           0 :   if (ldap_err || !basedn)
     856             :     {
     857           0 :       if (ldap_err)
     858           0 :         err = ldap_err_to_gpg_err (ldap_err);
     859             :       else
     860           0 :         err = GPG_ERR_GENERAL;
     861           0 :       goto out;
     862             :     }
     863             : 
     864             :   {
     865             :     /* The ordering is significant.  Specifically, "pgpcertid" needs
     866             :        to be the second item in the list, since everything after it
     867             :        may be discarded we aren't in verbose mode. */
     868           0 :     char *attrs[] =
     869             :       {
     870             :         pgpkeyattr,
     871             :         "pgpcertid", "pgpuserid", "pgpkeyid", "pgprevoked", "pgpdisabled",
     872             :         "pgpkeycreatetime", "modifytimestamp", "pgpkeysize", "pgpkeytype",
     873             :         NULL
     874             :       };
     875             :     /* 1 if we want just attribute types; 0 if we want both attribute
     876             :        types and values.  */
     877           0 :     int attrsonly = 0;
     878             : 
     879             :     int count;
     880             : 
     881           0 :     ldap_err = ldap_search_s (ldap_conn, basedn, LDAP_SCOPE_SUBTREE,
     882             :                               filter, attrs, attrsonly, &message);
     883           0 :     if (ldap_err)
     884             :       {
     885           0 :         err = ldap_err_to_gpg_err (ldap_err);
     886             : 
     887           0 :         log_error ("gpgkeys: LDAP search error: %s\n",
     888             :                    ldap_err2string (ldap_err));
     889           0 :         goto out;
     890             :       }
     891             : 
     892           0 :     count = ldap_count_entries (ldap_conn, message);
     893           0 :     if (count < 1)
     894             :       {
     895           0 :         log_error ("gpgkeys: key %s not found on keyserver\n", keyspec);
     896             : 
     897           0 :         if (count == -1)
     898           0 :           err = ldap_to_gpg_err (ldap_conn);
     899             :         else
     900           0 :           err = gpg_error (GPG_ERR_NO_DATA);
     901             : 
     902           0 :         goto out;
     903             :       }
     904             : 
     905             :     {
     906             :       /* There may be more than one unique result for a given keyID,
     907             :          so we should fetch them all (test this by fetching short key
     908             :          id 0xDEADBEEF). */
     909             : 
     910             :       /* The set of entries that we've seen.  */
     911           0 :       strlist_t seen = NULL;
     912             :       LDAPMessage *each;
     913             : 
     914           0 :       for (each = ldap_first_entry (ldap_conn, message);
     915             :            each;
     916           0 :            each = ldap_next_entry (ldap_conn, each))
     917             :         {
     918             :           char **vals;
     919             :           char **certid;
     920             : 
     921             :           /* Use the long keyid to remove duplicates.  The LDAP
     922             :              server returns the same keyid more than once if there
     923             :              are multiple user IDs on the key.  Note that this does
     924             :              NOT mean that a keyid that exists multiple times on the
     925             :              keyserver will not be fetched.  It means that each KEY,
     926             :              no matter how many user IDs share its keyid, will be
     927             :              fetched only once.  If a keyid that belongs to more
     928             :              than one key is fetched, the server quite properly
     929             :              responds with all matching keys. -ds */
     930             : 
     931           0 :           certid = ldap_get_values (ldap_conn, each, "pgpcertid");
     932           0 :           if (certid && certid[0])
     933             :             {
     934           0 :               if (! strlist_find (seen, certid[0]))
     935             :                 {
     936             :                   /* It's not a duplicate, add it */
     937             : 
     938           0 :                   add_to_strlist (&seen, certid[0]);
     939             : 
     940           0 :                   if (! fp)
     941           0 :                     fp = es_fopenmem(0, "rw");
     942             : 
     943           0 :                   extract_keys (fp, ldap_conn, certid[0], each);
     944             : 
     945           0 :                   vals = ldap_get_values (ldap_conn, each, pgpkeyattr);
     946           0 :                   if (! vals)
     947             :                     {
     948           0 :                       err = ldap_to_gpg_err (ldap_conn);
     949           0 :                       log_error("gpgkeys: unable to retrieve key %s "
     950             :                                 "from keyserver\n", certid[0]);
     951           0 :                       goto out;
     952             :                     }
     953             :                   else
     954             :                     {
     955             :                       /* We should strip the new lines.  */
     956           0 :                       es_fprintf (fp, "KEY 0x%s BEGIN\n", certid[0]);
     957           0 :                       es_fputs (vals[0], fp);
     958           0 :                       es_fprintf (fp, "\nKEY 0x%s END\n", certid[0]);
     959             : 
     960           0 :                       ldap_value_free (vals);
     961             :                     }
     962             :                 }
     963             :             }
     964             : 
     965           0 :           ldap_value_free (certid);
     966             :         }
     967             : 
     968           0 :       free_strlist (seen);
     969             : 
     970           0 :       if (! fp)
     971           0 :         err = gpg_error (GPG_ERR_NO_DATA);
     972             :     }
     973             :   }
     974             : 
     975             :  out:
     976           0 :   if (message)
     977           0 :     ldap_msgfree (message);
     978             : 
     979           0 :   if (err)
     980             :     {
     981           0 :       if (fp)
     982           0 :         es_fclose (fp);
     983             :     }
     984             :   else
     985             :     {
     986           0 :       if (fp)
     987           0 :         es_fseek (fp, 0, SEEK_SET);
     988             : 
     989           0 :       *r_fp = fp;
     990             :     }
     991             : 
     992           0 :   xfree (pgpkeyattr);
     993           0 :   xfree (basedn);
     994             : 
     995           0 :   if (ldap_conn)
     996           0 :     ldap_unbind (ldap_conn);
     997             : 
     998           0 :   xfree (filter);
     999             : 
    1000           0 :   return err;
    1001             : }
    1002             : 
    1003             : /* Search the keyserver identified by URI for keys matching PATTERN.
    1004             :    On success R_FP has an open stream to read the data.  */
    1005             : gpg_error_t
    1006           0 : ks_ldap_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
    1007             :                 estream_t *r_fp)
    1008             : {
    1009             :   gpg_error_t err;
    1010             :   int ldap_err;
    1011             : 
    1012           0 :   char *filter = NULL;
    1013             : 
    1014           0 :   LDAP *ldap_conn = NULL;
    1015             : 
    1016           0 :   char *basedn = NULL;
    1017             : 
    1018           0 :   estream_t fp = NULL;
    1019             : 
    1020             :   (void) ctrl;
    1021             : 
    1022           0 :   if (opt.use_tor)
    1023             :     {
    1024             :       /* For now we do not support LDAP over Tor.  */
    1025           0 :       log_error (_("LDAP access not possible due to Tor mode\n"));
    1026           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
    1027             :     }
    1028             : 
    1029             :   /* Before connecting to the server, make sure we have a sane
    1030             :      keyspec.  If not, there is no need to establish a network
    1031             :      connection.  */
    1032           0 :   err = keyspec_to_ldap_filter (pattern, &filter, 0);
    1033           0 :   if (err)
    1034             :     {
    1035           0 :       log_error ("Bad search pattern: '%s'\n", pattern);
    1036           0 :       return (err);
    1037             :     }
    1038             : 
    1039             :   /* Make sure we are talking to an OpenPGP LDAP server.  */
    1040           0 :   ldap_err = my_ldap_connect (uri, &ldap_conn, &basedn, NULL, NULL);
    1041           0 :   if (ldap_err || !basedn)
    1042             :     {
    1043           0 :       if (ldap_err)
    1044           0 :         err = ldap_err_to_gpg_err (ldap_err);
    1045             :       else
    1046           0 :         err = GPG_ERR_GENERAL;
    1047           0 :       goto out;
    1048             :     }
    1049             : 
    1050             :   /* Even if we have no results, we want to return a stream.  */
    1051           0 :   fp = es_fopenmem(0, "rw");
    1052           0 :   if (!fp)
    1053             :     {
    1054           0 :       err = gpg_error_from_syserror ();
    1055           0 :       goto out;
    1056             :     }
    1057             : 
    1058             :   {
    1059             :     char **vals;
    1060             :     LDAPMessage *res, *each;
    1061           0 :     int count = 0;
    1062           0 :     strlist_t dupelist = NULL;
    1063             : 
    1064             :     /* The maximum size of the search, including the optional stuff
    1065             :        and the trailing \0 */
    1066           0 :     char *attrs[] =
    1067             :       {
    1068             :         "pgpcertid", "pgpuserid", "pgprevoked", "pgpdisabled",
    1069             :         "pgpkeycreatetime", "pgpkeyexpiretime", "modifytimestamp",
    1070             :         "pgpkeysize", "pgpkeytype", NULL
    1071             :       };
    1072             : 
    1073           0 :     log_debug ("SEARCH '%s' => '%s' BEGIN\n", pattern, filter);
    1074             : 
    1075           0 :     ldap_err = ldap_search_s (ldap_conn, basedn,
    1076             :                               LDAP_SCOPE_SUBTREE, filter, attrs, 0, &res);
    1077             : 
    1078           0 :     xfree (filter);
    1079           0 :     filter = NULL;
    1080             : 
    1081           0 :     if (ldap_err != LDAP_SUCCESS && ldap_err != LDAP_SIZELIMIT_EXCEEDED)
    1082             :       {
    1083           0 :         err = ldap_err_to_gpg_err (ldap_err);
    1084             : 
    1085           0 :         log_error ("SEARCH %s FAILED %d\n", pattern, err);
    1086           0 :         log_error ("gpgkeys: LDAP search error: %s\n",
    1087             :                    ldap_err2string (err));
    1088           0 :         goto out;
    1089             :     }
    1090             : 
    1091             :     /* The LDAP server doesn't return a real count of unique keys, so we
    1092             :        can't use ldap_count_entries here. */
    1093           0 :     for (each = ldap_first_entry (ldap_conn, res);
    1094             :          each;
    1095           0 :          each = ldap_next_entry (ldap_conn, each))
    1096             :       {
    1097           0 :         char **certid = ldap_get_values (ldap_conn, each, "pgpcertid");
    1098           0 :         if (certid && certid[0] && ! strlist_find (dupelist, certid[0]))
    1099             :           {
    1100           0 :             add_to_strlist (&dupelist, certid[0]);
    1101           0 :             count++;
    1102             :           }
    1103             :       }
    1104             : 
    1105           0 :     if (ldap_err == LDAP_SIZELIMIT_EXCEEDED)
    1106             :       {
    1107           0 :         if (count == 1)
    1108           0 :           log_error ("gpgkeys: search results exceeded server limit."
    1109             :                      "  First 1 result shown.\n");
    1110             :         else
    1111           0 :           log_error ("gpgkeys: search results exceeded server limit."
    1112             :                      "  First %d results shown.\n", count);
    1113             :       }
    1114             : 
    1115           0 :     free_strlist (dupelist);
    1116           0 :     dupelist = NULL;
    1117             : 
    1118           0 :     if (count < 1)
    1119           0 :       es_fputs ("info:1:0\n", fp);
    1120             :     else
    1121             :       {
    1122           0 :         es_fprintf (fp, "info:1:%d\n", count);
    1123             : 
    1124           0 :         for (each = ldap_first_entry (ldap_conn, res);
    1125             :              each;
    1126           0 :              each = ldap_next_entry (ldap_conn, each))
    1127             :           {
    1128             :             char **certid;
    1129             :             LDAPMessage *uids;
    1130             : 
    1131           0 :             certid = ldap_get_values (ldap_conn, each, "pgpcertid");
    1132           0 :             if (! certid || ! certid[0])
    1133           0 :               continue;
    1134             : 
    1135             :             /* Have we seen this certid before? */
    1136           0 :             if (! strlist_find (dupelist, certid[0]))
    1137             :               {
    1138           0 :                 add_to_strlist (&dupelist, certid[0]);
    1139             : 
    1140           0 :                 es_fprintf (fp, "pub:%s:",certid[0]);
    1141             : 
    1142           0 :                 vals = ldap_get_values (ldap_conn, each, "pgpkeytype");
    1143           0 :                 if (vals)
    1144             :                   {
    1145             :                     /* The LDAP server doesn't exactly handle this
    1146             :                        well. */
    1147           0 :                     if (strcasecmp (vals[0], "RSA") == 0)
    1148           0 :                       es_fputs ("1", fp);
    1149           0 :                     else if (strcasecmp (vals[0], "DSS/DH") == 0)
    1150           0 :                       es_fputs ("17", fp);
    1151           0 :                     ldap_value_free (vals);
    1152             :                   }
    1153             : 
    1154           0 :                 es_fputc (':', fp);
    1155             : 
    1156           0 :                 vals = ldap_get_values (ldap_conn, each, "pgpkeysize");
    1157           0 :                 if (vals)
    1158             :                   {
    1159             :                     /* Not sure why, but some keys are listed with a
    1160             :                        key size of 0.  Treat that like an unknown. */
    1161           0 :                     if (atoi (vals[0]) > 0)
    1162           0 :                       es_fprintf (fp, "%d", atoi (vals[0]));
    1163           0 :                     ldap_value_free (vals);
    1164             :                   }
    1165             : 
    1166           0 :                 es_fputc (':', fp);
    1167             : 
    1168             :                 /* YYYYMMDDHHmmssZ */
    1169             : 
    1170           0 :                 vals = ldap_get_values (ldap_conn, each, "pgpkeycreatetime");
    1171           0 :                 if(vals && strlen (vals[0]) == 15)
    1172             :                   {
    1173           0 :                     es_fprintf (fp, "%u",
    1174           0 :                                 (unsigned int) ldap2epochtime(vals[0]));
    1175           0 :                     ldap_value_free (vals);
    1176             :                   }
    1177             : 
    1178           0 :                 es_fputc (':', fp);
    1179             : 
    1180           0 :                 vals = ldap_get_values (ldap_conn, each, "pgpkeyexpiretime");
    1181           0 :                 if (vals && strlen (vals[0]) == 15)
    1182             :                   {
    1183           0 :                     es_fprintf (fp, "%u",
    1184           0 :                                 (unsigned int) ldap2epochtime (vals[0]));
    1185           0 :                     ldap_value_free (vals);
    1186             :                   }
    1187             : 
    1188           0 :                 es_fputc (':', fp);
    1189             : 
    1190           0 :                 vals = ldap_get_values (ldap_conn, each, "pgprevoked");
    1191           0 :                 if (vals)
    1192             :                   {
    1193           0 :                     if (atoi (vals[0]) == 1)
    1194           0 :                       es_fprintf (fp, "r");
    1195           0 :                     ldap_value_free (vals);
    1196             :                   }
    1197             : 
    1198           0 :                 vals = ldap_get_values (ldap_conn, each, "pgpdisabled");
    1199           0 :                 if (vals)
    1200             :                   {
    1201           0 :                     if (atoi (vals[0]) ==1)
    1202           0 :                       es_fprintf (fp, "d");
    1203           0 :                     ldap_value_free (vals);
    1204             :                   }
    1205             : 
    1206             : #if 0
    1207             :                 /* This is not yet specified in the keyserver
    1208             :                    protocol, but may be someday. */
    1209             :                 es_fputc (':', fp);
    1210             : 
    1211             :                 vals = ldap_get_values (ldap_conn, each, "modifytimestamp");
    1212             :                 if(vals && strlen (vals[0]) == 15)
    1213             :                   {
    1214             :                     es_fprintf (fp, "%u",
    1215             :                                 (unsigned int) ldap2epochtime (vals[0]));
    1216             :                     ldap_value_free (vals);
    1217             :                   }
    1218             : #endif
    1219             : 
    1220           0 :                 es_fprintf (fp, "\n");
    1221             : 
    1222             :                 /* Now print all the uids that have this certid */
    1223           0 :                 for (uids = ldap_first_entry (ldap_conn, res);
    1224             :                      uids;
    1225           0 :                      uids = ldap_next_entry (ldap_conn, uids))
    1226             :                   {
    1227           0 :                     vals = ldap_get_values (ldap_conn, uids, "pgpcertid");
    1228           0 :                     if (! vals)
    1229           0 :                       continue;
    1230             : 
    1231           0 :                     if (strcasecmp (certid[0], vals[0]) == 0)
    1232             :                       {
    1233             :                         char **uidvals;
    1234             : 
    1235           0 :                         es_fprintf (fp, "uid:");
    1236             : 
    1237           0 :                         uidvals = ldap_get_values (ldap_conn,
    1238             :                                                    uids, "pgpuserid");
    1239           0 :                         if (uidvals)
    1240             :                           {
    1241             :                             /* Need to escape any colons */
    1242           0 :                             char *quoted = percent_escape (uidvals[0], NULL);
    1243           0 :                             es_fputs (quoted, fp);
    1244           0 :                             xfree (quoted);
    1245           0 :                             ldap_value_free (uidvals);
    1246             :                           }
    1247             : 
    1248           0 :                         es_fprintf (fp, "\n");
    1249             :                       }
    1250             : 
    1251           0 :                     ldap_value_free(vals);
    1252             :                   }
    1253             :               }
    1254             : 
    1255           0 :               ldap_value_free (certid);
    1256             :           }
    1257             :       }
    1258             : 
    1259           0 :     ldap_msgfree (res);
    1260           0 :     free_strlist (dupelist);
    1261             :   }
    1262             : 
    1263           0 :   log_debug ("SEARCH %s END\n", pattern);
    1264             : 
    1265             :  out:
    1266           0 :   if (err)
    1267             :     {
    1268           0 :       if (fp)
    1269           0 :         es_fclose (fp);
    1270             :     }
    1271             :   else
    1272             :     {
    1273             :       /* Return the read stream.  */
    1274           0 :       if (fp)
    1275           0 :         es_fseek (fp, 0, SEEK_SET);
    1276             : 
    1277           0 :       *r_fp = fp;
    1278             :     }
    1279             : 
    1280           0 :   xfree (basedn);
    1281             : 
    1282           0 :   if (ldap_conn)
    1283           0 :     ldap_unbind (ldap_conn);
    1284             : 
    1285           0 :   xfree (filter);
    1286             : 
    1287           0 :   return err;
    1288             : }
    1289             : 
    1290             : 
    1291             : 
    1292             : /* A modlist describes a set of changes to an LDAP entry.  (An entry
    1293             :    consists of 1 or more attributes.  Attributes are <name, value>
    1294             :    pairs.  Note: an attribute may be multi-valued in which case
    1295             :    multiple values are associated with a single name.)
    1296             : 
    1297             :    A modlist is a NULL terminated array of struct LDAPMod's.
    1298             : 
    1299             :    Thus, if we have:
    1300             : 
    1301             :      LDAPMod **modlist;
    1302             : 
    1303             :    Then:
    1304             : 
    1305             :      modlist[i]
    1306             : 
    1307             :    Is the ith modification.
    1308             : 
    1309             :    Each LDAPMod describes a change to a single attribute.  Further,
    1310             :    there is one modification for each attribute that we want to
    1311             :    change.  The attribute's new value is stored in LDAPMod.mod_values.
    1312             :    If the attribute is multi-valued, we still only use a single
    1313             :    LDAPMod structure: mod_values is a NULL-terminated array of
    1314             :    strings.  To delete an attribute from an entry, we set mod_values
    1315             :    to NULL.
    1316             : 
    1317             :    Thus, if:
    1318             : 
    1319             :      modlist[i]->mod_values == NULL
    1320             : 
    1321             :    then we remove the attribute.
    1322             : 
    1323             :    (Using LDAP_MOD_DELETE doesn't work here as we don't know if the
    1324             :    attribute in question exists or not.)
    1325             : 
    1326             :    Note: this function does NOT copy or free ATTR.  It does copy
    1327             :    VALUE.  */
    1328             : static void
    1329           0 : modlist_add (LDAPMod ***modlistp, char *attr, const char *value)
    1330             : {
    1331           0 :   LDAPMod **modlist = *modlistp;
    1332             : 
    1333             :   LDAPMod **m;
    1334           0 :   int nummods = 0;
    1335             : 
    1336             :   /* Search modlist for the attribute we're playing with.  If modlist
    1337             :      is NULL, then the list is empty.  Recall: modlist is a NULL
    1338             :      terminated array.  */
    1339           0 :   for (m = modlist; m && *m; m++, nummods ++)
    1340             :     {
    1341             :       /* The attribute is already on the list.  */
    1342             :       char **ptr;
    1343           0 :       int numvalues = 0;
    1344             : 
    1345           0 :       if (strcasecmp ((*m)->mod_type, attr) != 0)
    1346           0 :         continue;
    1347             : 
    1348             :       /* We have this attribute already, so when the REPLACE happens,
    1349             :          the server attributes will be replaced anyway. */
    1350           0 :       if (! value)
    1351           0 :         return;
    1352             : 
    1353             :       /* Attributes can be multi-valued.  See if the value is already
    1354             :          present.  mod_values is a NULL terminated array of pointers.
    1355             :          Note: mod_values can be NULL.  */
    1356           0 :       for (ptr = (*m)->mod_values; ptr && *ptr; ptr++)
    1357             :         {
    1358           0 :           if (strcmp (*ptr, value) == 0)
    1359             :             /* Duplicate value, we're done.  */
    1360           0 :             return;
    1361           0 :           numvalues ++;
    1362             :         }
    1363             : 
    1364             :       /* Append the value.  */
    1365           0 :       ptr = xrealloc ((*m)->mod_values, sizeof (char *) * (numvalues + 2));
    1366             : 
    1367           0 :       (*m)->mod_values = ptr;
    1368           0 :       ptr[numvalues] = xstrdup (value);
    1369             : 
    1370           0 :       ptr[numvalues + 1] = NULL;
    1371             : 
    1372           0 :       return;
    1373             :     }
    1374             : 
    1375             :   /* We didn't find the attr, so make one and add it to the end */
    1376             : 
    1377             :   /* Like attribute values, the list of attributes is NULL terminated
    1378             :      array of pointers.  */
    1379           0 :   modlist = xrealloc (modlist, sizeof (LDAPMod *) * (nummods + 2));
    1380             : 
    1381           0 :   *modlistp = modlist;
    1382           0 :   modlist[nummods] = xmalloc (sizeof (LDAPMod));
    1383             : 
    1384           0 :   modlist[nummods]->mod_op = LDAP_MOD_REPLACE;
    1385           0 :   modlist[nummods]->mod_type = attr;
    1386           0 :   if (value)
    1387             :     {
    1388           0 :       modlist[nummods]->mod_values = xmalloc (sizeof(char *) * 2);
    1389             : 
    1390           0 :       modlist[nummods]->mod_values[0] = xstrdup (value);
    1391           0 :       modlist[nummods]->mod_values[1] = NULL;
    1392             :     }
    1393             :   else
    1394           0 :     modlist[nummods]->mod_values = NULL;
    1395             : 
    1396           0 :   modlist[nummods + 1] = NULL;
    1397             : 
    1398           0 :   return;
    1399             : }
    1400             : 
    1401             : /* Look up the value of an attribute in the specified modlist.  If the
    1402             :    attribute is not on the mod list, returns NULL.  The result is a
    1403             :    NULL-terminated array of strings.  Don't change it.  */
    1404             : static char **
    1405           0 : modlist_lookup (LDAPMod **modlist, const char *attr)
    1406             : {
    1407             :   LDAPMod **m;
    1408           0 :   for (m = modlist; m && *m; m++)
    1409             :     {
    1410           0 :       if (strcasecmp ((*m)->mod_type, attr) != 0)
    1411           0 :         continue;
    1412             : 
    1413           0 :       return (*m)->mod_values;
    1414             :     }
    1415             : 
    1416           0 :   return NULL;
    1417             : }
    1418             : 
    1419             : /* Dump a modlist to a file.  This is useful for debugging.  */
    1420             : static estream_t modlist_dump (LDAPMod **modlist, estream_t output)
    1421             :   GPGRT_ATTR_USED;
    1422             : 
    1423             : static estream_t
    1424           0 : modlist_dump (LDAPMod **modlist, estream_t output)
    1425             : {
    1426             :   LDAPMod **m;
    1427             : 
    1428           0 :   int opened = 0;
    1429             : 
    1430           0 :   if (! output)
    1431             :     {
    1432           0 :       output = es_fopenmem (0, "rw");
    1433           0 :       if (!output)
    1434           0 :         return NULL;
    1435           0 :       opened = 1;
    1436             :     }
    1437             : 
    1438           0 :   for (m = modlist; m && *m; m++)
    1439             :     {
    1440           0 :       es_fprintf (output, "  %s:", (*m)->mod_type);
    1441             : 
    1442           0 :       if (! (*m)->mod_values)
    1443           0 :         es_fprintf(output, " delete.\n");
    1444             :       else
    1445             :         {
    1446             :           char **ptr;
    1447             :           int i;
    1448             : 
    1449           0 :           int multi = 0;
    1450           0 :           if ((*m)->mod_values[0] && (*m)->mod_values[1])
    1451             :             /* Have at least 2.  */
    1452           0 :             multi = 1;
    1453             : 
    1454           0 :           if (multi)
    1455           0 :             es_fprintf (output, "\n");
    1456             : 
    1457           0 :           for ((ptr = (*m)->mod_values), (i = 1); ptr && *ptr; ptr++, i ++)
    1458             :             {
    1459             :               /* Assuming terminals are about 80 characters wide,
    1460             :                  display at most most about 10 lines of debugging
    1461             :                  output.  If we do trim the buffer, append '...' to
    1462             :                  the end.  */
    1463           0 :               const int max_len = 10 * 70;
    1464           0 :               size_t value_len = strlen (*ptr);
    1465           0 :               int elide = value_len > max_len;
    1466             : 
    1467           0 :               if (multi)
    1468           0 :                 es_fprintf (output, "    %d. ", i);
    1469           0 :               es_fprintf (output, "`%.*s", max_len, *ptr);
    1470           0 :               if (elide)
    1471           0 :                 es_fprintf (output, "...' (%zd bytes elided)",
    1472             :                             value_len - max_len);
    1473             :               else
    1474           0 :                 es_fprintf (output, "'");
    1475           0 :               es_fprintf (output, "\n");
    1476             :             }
    1477             :         }
    1478             :     }
    1479             : 
    1480           0 :   if (opened)
    1481           0 :     es_fseek (output, 0, SEEK_SET);
    1482             : 
    1483           0 :   return output;
    1484             : }
    1485             : 
    1486             : /* Free all of the memory allocated by the mod list.  This assumes
    1487             :    that the attribute names don't have to be freed, but the attributes
    1488             :    values do.  (Which is what modlist_add does.)  */
    1489             : static void
    1490           0 : modlist_free (LDAPMod **modlist)
    1491             : {
    1492             :   LDAPMod **ml;
    1493             : 
    1494           0 :   if (! modlist)
    1495           0 :     return;
    1496             : 
    1497             :   /* Unwind and free the whole modlist structure */
    1498             : 
    1499             :   /* The modlist is a NULL terminated array of pointers.  */
    1500           0 :   for (ml = modlist; *ml; ml++)
    1501             :     {
    1502           0 :       LDAPMod *mod = *ml;
    1503             :       char **ptr;
    1504             : 
    1505             :       /* The list of values is a NULL termianted array of pointers.
    1506             :          If the list is NULL, there are no values.  */
    1507             : 
    1508           0 :       if (mod->mod_values)
    1509             :         {
    1510           0 :           for (ptr = mod->mod_values; *ptr; ptr++)
    1511           0 :             xfree (*ptr);
    1512             : 
    1513           0 :           xfree (mod->mod_values);
    1514             :         }
    1515             : 
    1516           0 :       xfree (mod);
    1517             :     }
    1518           0 :   xfree (modlist);
    1519             : }
    1520             : 
    1521             : /* Append two onto the end of one.  Two is not freed, but its pointers
    1522             :    are now part of one.  Make sure you don't free them both!
    1523             : 
    1524             :    As long as you don't add anything to ONE, TWO is still valid.
    1525             :    After that all bets are off.  */
    1526             : static void
    1527           0 : modlists_join (LDAPMod ***one, LDAPMod **two)
    1528             : {
    1529           0 :   int i, one_count = 0, two_count = 0;
    1530             :   LDAPMod **grow;
    1531             : 
    1532           0 :   if (!*two)
    1533             :     /* two is empty.  Nothing to do.  */
    1534           0 :     return;
    1535             : 
    1536           0 :   if (!*one)
    1537             :     /* one is empty.  Just set it equal to *two.  */
    1538             :     {
    1539           0 :       *one = two;
    1540           0 :       return;
    1541             :     }
    1542             : 
    1543           0 :   for (grow = *one; *grow; grow++)
    1544           0 :     one_count ++;
    1545             : 
    1546           0 :   for (grow = two; *grow; grow++)
    1547           0 :     two_count ++;
    1548             : 
    1549           0 :   grow = xrealloc (*one, sizeof(LDAPMod *) * (one_count + two_count + 1));
    1550             : 
    1551           0 :   for (i = 0; i < two_count; i++)
    1552           0 :     grow[one_count + i] = two[i];
    1553             : 
    1554           0 :   grow[one_count + i] = NULL;
    1555             : 
    1556           0 :   *one = grow;
    1557             : }
    1558             : 
    1559             : /* Given a string, unescape C escapes.  In particular, \xXX.  This
    1560             :    modifies the string in place.  */
    1561             : static void
    1562           0 : uncescape (char *str)
    1563             : {
    1564           0 :   size_t r = 0;
    1565           0 :   size_t w = 0;
    1566             : 
    1567           0 :   char *first = strchr (str, '\\');
    1568           0 :   if (! first)
    1569             :     /* No backslashes => no escaping.  We're done.  */
    1570           0 :     return;
    1571             : 
    1572             :   /* Start at the first '\\'.  */
    1573           0 :   r = w = (uintptr_t) first - (uintptr_t) str;
    1574             : 
    1575           0 :   while (str[r])
    1576             :     {
    1577             :       /* XXX: What to do about bad escapes?
    1578             :          XXX: hextobyte already checks the string thus the hexdigitp
    1579             :          could be removed. */
    1580           0 :       if (str[r] == '\\' && str[r + 1] == 'x'
    1581           0 :           && str[r+2] && str[r+3]
    1582           0 :           && hexdigitp (str + r + 2)
    1583           0 :           && hexdigitp (str + r + 3))
    1584           0 :         {
    1585           0 :           int x = hextobyte (&str[r + 2]);
    1586           0 :           assert (0 <= x && x <= 0xff);
    1587             : 
    1588           0 :           str[w] = x;
    1589             : 
    1590             :           /* We consumed 4 characters and wrote 1.  */
    1591           0 :           r += 4;
    1592           0 :           w ++;
    1593             :         }
    1594             :       else
    1595           0 :         str[w ++] = str[r ++];
    1596             :     }
    1597             : 
    1598           0 :   str[w] = '\0';
    1599             : }
    1600             : 
    1601             : /* Given one line from an info block (`gpg --list-{keys,sigs}
    1602             :    --with-colons KEYID'), pull it apart and fill in the modlist with
    1603             :    the relevant (for the LDAP schema) attributes.  */
    1604             : static void
    1605           0 : extract_attributes (LDAPMod ***modlist, char *line)
    1606             : {
    1607             :   int field_count;
    1608             :   char **fields;
    1609             : 
    1610             :   char *keyid;
    1611             : 
    1612             :   int is_pub, is_sub, is_uid, is_sig;
    1613             : 
    1614             :   /* Remove trailing whitespace */
    1615           0 :   trim_trailing_spaces (line);
    1616             : 
    1617           0 :   fields = strsplit (line, ':', '\0', &field_count);
    1618           0 :   if (field_count == 1)
    1619             :     /* We only have a single field.  There is definitely nothing to
    1620             :        do.  */
    1621           0 :     goto out;
    1622             : 
    1623           0 :   if (field_count < 7)
    1624           0 :     goto out;
    1625             : 
    1626           0 :   is_pub = strcasecmp ("pub", fields[0]) == 0;
    1627           0 :   is_sub = strcasecmp ("sub", fields[0]) == 0;
    1628           0 :   is_uid = strcasecmp ("uid", fields[0]) == 0;
    1629           0 :   is_sig = strcasecmp ("sig", fields[0]) == 0;
    1630             : 
    1631           0 :   if (!is_pub && !is_sub && !is_uid && !is_sig)
    1632             :     /* Not a relevant line.  */
    1633           0 :     goto out;
    1634             : 
    1635           0 :   keyid = fields[4];
    1636             : 
    1637           0 :   if (is_uid && strlen (keyid) == 0)
    1638             :     /* The uid record type can have an empty keyid.  */
    1639             :     ;
    1640           0 :   else if (strlen (keyid) == 16
    1641           0 :            && strspn (keyid, "0123456789aAbBcCdDeEfF") == 16)
    1642             :     /* Otherwise, we expect exactly 16 hex characters.  */
    1643             :     ;
    1644             :   else
    1645             :     {
    1646           0 :       log_error ("malformed record!\n");
    1647           0 :       goto out;
    1648             :     }
    1649             : 
    1650           0 :   if (is_pub)
    1651             :     {
    1652           0 :       int disabled = 0;
    1653           0 :       int revoked = 0;
    1654             :       char *flags;
    1655           0 :       for (flags = fields[1]; *flags; flags ++)
    1656           0 :         switch (*flags)
    1657             :           {
    1658             :           case 'r':
    1659             :           case 'R':
    1660           0 :             revoked = 1;
    1661           0 :             break;
    1662             : 
    1663             :           case 'd':
    1664             :           case 'D':
    1665           0 :             disabled = 1;
    1666           0 :             break;
    1667             :           }
    1668             : 
    1669             :       /* Note: we always create the pgpDisabled and pgpRevoked
    1670             :         attributes, regardless of whether the key is disabled/revoked
    1671             :         or not.  This is because a very common search is like
    1672             :         "(&(pgpUserID=*isabella*)(pgpDisabled=0))"  */
    1673             : 
    1674           0 :       if (is_pub)
    1675             :         {
    1676           0 :           modlist_add (modlist,"pgpDisabled", disabled ? "1" : "0");
    1677           0 :           modlist_add (modlist,"pgpRevoked", revoked ? "1" : "0");
    1678             :         }
    1679             :     }
    1680             : 
    1681           0 :   if (is_pub || is_sub)
    1682             :     {
    1683           0 :       char *size = fields[2];
    1684           0 :       int val = atoi (size);
    1685           0 :       size = NULL;
    1686             : 
    1687           0 :       if (val > 0)
    1688             :         {
    1689             :           /* We zero pad this on the left to make PGP happy. */
    1690             :           char padded[6];
    1691           0 :           if (val < 99999 && val > 0)
    1692             :             {
    1693           0 :               snprintf (padded, sizeof padded, "%05u", val);
    1694           0 :               size = padded;
    1695             :             }
    1696             :         }
    1697             : 
    1698           0 :       if (size)
    1699             :         {
    1700           0 :           if (is_pub || is_sub)
    1701           0 :             modlist_add (modlist, "pgpKeySize", size);
    1702             :         }
    1703             :     }
    1704             : 
    1705           0 :   if (is_pub)
    1706             :     {
    1707           0 :       char *algo = fields[3];
    1708           0 :       int val = atoi (algo);
    1709           0 :       switch (val)
    1710             :         {
    1711             :         case 1:
    1712           0 :           algo = "RSA";
    1713           0 :           break;
    1714             : 
    1715             :         case 17:
    1716           0 :           algo = "DSS/DH";
    1717           0 :           break;
    1718             : 
    1719             :         default:
    1720           0 :           algo = NULL;
    1721           0 :           break;
    1722             :         }
    1723             : 
    1724           0 :       if (algo)
    1725             :         {
    1726           0 :           if (is_pub)
    1727           0 :             modlist_add (modlist, "pgpKeyType", algo);
    1728             :         }
    1729             :     }
    1730             : 
    1731           0 :   if (is_pub || is_sub || is_sig)
    1732             :     {
    1733           0 :       if (is_pub)
    1734             :         {
    1735           0 :           modlist_add (modlist, "pgpCertID", keyid);
    1736           0 :           modlist_add (modlist, "pgpKeyID", &keyid[8]);
    1737             :         }
    1738             : 
    1739           0 :       if (is_sub)
    1740           0 :         modlist_add (modlist, "pgpSubKeyID", keyid);
    1741             : 
    1742           0 :       if (is_sig)
    1743           0 :         modlist_add (modlist, "pgpSignerID", keyid);
    1744             :     }
    1745             : 
    1746           0 :   if (is_pub)
    1747             :     {
    1748           0 :       char *create_time = fields[5];
    1749             : 
    1750           0 :       if (strlen (create_time) == 0)
    1751           0 :         create_time = NULL;
    1752             :       else
    1753             :         {
    1754           0 :           char *create_time_orig = create_time;
    1755             :           struct tm tm;
    1756             :           time_t t;
    1757             :           char *end;
    1758             : 
    1759           0 :           memset (&tm, 0, sizeof (tm));
    1760             : 
    1761             :           /* parse_timestamp handles both seconds fromt he epoch and
    1762             :              ISO 8601 format.  We also need to handle YYYY-MM-DD
    1763             :              format (as generated by gpg1 --with-colons --list-key).
    1764             :              Check that first and then if it fails, then try
    1765             :              parse_timestamp.  */
    1766             : 
    1767           0 :           if (!isodate_human_to_tm (create_time, &tm))
    1768           0 :             create_time = tm2ldaptime (&tm);
    1769           0 :           else if ((t = parse_timestamp (create_time, &end)) != (time_t) -1
    1770           0 :                    && *end == '\0')
    1771             :             {
    1772             : 
    1773           0 :               if (!gnupg_gmtime (&t, &tm))
    1774           0 :                 create_time = NULL;
    1775             :               else
    1776           0 :                 create_time = tm2ldaptime (&tm);
    1777             :             }
    1778             :           else
    1779           0 :             create_time = NULL;
    1780             : 
    1781           0 :           if (! create_time)
    1782             :             /* Failed to parse string.  */
    1783           0 :             log_error ("Failed to parse creation time ('%s')",
    1784             :                        create_time_orig);
    1785             :         }
    1786             : 
    1787           0 :       if (create_time)
    1788             :         {
    1789           0 :           modlist_add (modlist, "pgpKeyCreateTime", create_time);
    1790           0 :           xfree (create_time);
    1791             :         }
    1792             :     }
    1793             : 
    1794           0 :   if (is_pub)
    1795             :     {
    1796           0 :       char *expire_time = fields[6];
    1797             : 
    1798           0 :       if (strlen (expire_time) == 0)
    1799           0 :         expire_time = NULL;
    1800             :       else
    1801             :         {
    1802           0 :           char *expire_time_orig = expire_time;
    1803             :           struct tm tm;
    1804             :           time_t t;
    1805             :           char *end;
    1806             : 
    1807           0 :           memset (&tm, 0, sizeof (tm));
    1808             : 
    1809             :           /* parse_timestamp handles both seconds fromt he epoch and
    1810             :              ISO 8601 format.  We also need to handle YYYY-MM-DD
    1811             :              format (as generated by gpg1 --with-colons --list-key).
    1812             :              Check that first and then if it fails, then try
    1813             :              parse_timestamp.  */
    1814             : 
    1815           0 :           if (!isodate_human_to_tm (expire_time, &tm))
    1816           0 :             expire_time = tm2ldaptime (&tm);
    1817           0 :           else if ((t = parse_timestamp (expire_time, &end)) != (time_t) -1
    1818           0 :                    && *end == '\0')
    1819             :             {
    1820           0 :               if (!gnupg_gmtime (&t, &tm))
    1821           0 :                 expire_time = NULL;
    1822             :               else
    1823           0 :                 expire_time = tm2ldaptime (&tm);
    1824             :             }
    1825             :           else
    1826           0 :             expire_time = NULL;
    1827             : 
    1828           0 :           if (! expire_time)
    1829             :             /* Failed to parse string.  */
    1830           0 :             log_error ("Failed to parse creation time ('%s')",
    1831             :                        expire_time_orig);
    1832             :         }
    1833             : 
    1834           0 :       if (expire_time)
    1835             :         {
    1836           0 :           modlist_add (modlist, "pgpKeyExpireTime", expire_time);
    1837           0 :           xfree (expire_time);
    1838             :         }
    1839             :     }
    1840             : 
    1841           0 :   if ((is_uid || is_pub) && field_count >= 10)
    1842             :     {
    1843           0 :       char *uid = fields[9];
    1844             : 
    1845           0 :       if (is_pub && strlen (uid) == 0)
    1846             :         /* When using gpg --list-keys, the uid is included.  When
    1847             :            passed via gpg, it is not.  It is important to process it
    1848             :            when it is present, because gpg 1 won't print a UID record
    1849             :            if there is only one key.  */
    1850             :         ;
    1851             :       else
    1852             :         {
    1853           0 :           uncescape (uid);
    1854           0 :           modlist_add (modlist, "pgpUserID", uid);
    1855             :         }
    1856             :     }
    1857             : 
    1858             :  out:
    1859           0 :   free (fields);
    1860           0 : }
    1861             : 
    1862             : /* Send the key in {KEY,KEYLEN} with the metadata {INFO,INFOLEN} to
    1863             :    the keyserver identified by URI.  See server.c:cmd_ks_put for the
    1864             :    format of the data and metadata.  */
    1865             : gpg_error_t
    1866           0 : ks_ldap_put (ctrl_t ctrl, parsed_uri_t uri,
    1867             :              void *data, size_t datalen,
    1868             :              void *info, size_t infolen)
    1869             : {
    1870           0 :   gpg_error_t err = 0;
    1871             :   int ldap_err;
    1872             : 
    1873           0 :   LDAP *ldap_conn = NULL;
    1874           0 :   char *basedn = NULL;
    1875           0 :   char *pgpkeyattr = NULL;
    1876             :   int real_ldap;
    1877             : 
    1878           0 :   LDAPMod **modlist = NULL;
    1879           0 :   LDAPMod **addlist = NULL;
    1880             : 
    1881           0 :   char *data_armored = NULL;
    1882             : 
    1883             :   /* The last byte of the info block.  */
    1884           0 :   const char *infoend = (const char *) info + infolen - 1;
    1885             : 
    1886             :   /* Enable this code to dump the modlist to /tmp/modlist.txt.  */
    1887             : #if 0
    1888             : # warning Disable debug code before checking in.
    1889             :   const int dump_modlist = 1;
    1890             : #else
    1891           0 :   const int dump_modlist = 0;
    1892             : #endif
    1893           0 :   estream_t dump = NULL;
    1894             : 
    1895             :   /* Elide a warning.  */
    1896             :   (void) ctrl;
    1897             : 
    1898           0 :   if (opt.use_tor)
    1899             :     {
    1900             :       /* For now we do not support LDAP over Tor.  */
    1901           0 :       log_error (_("LDAP access not possible due to Tor mode\n"));
    1902           0 :       return gpg_error (GPG_ERR_NOT_SUPPORTED);
    1903             :     }
    1904             : 
    1905           0 :   ldap_err = my_ldap_connect (uri,
    1906             :                               &ldap_conn, &basedn, &pgpkeyattr, &real_ldap);
    1907           0 :   if (ldap_err || !basedn)
    1908             :     {
    1909           0 :       if (ldap_err)
    1910           0 :         err = ldap_err_to_gpg_err (ldap_err);
    1911             :       else
    1912           0 :         err = GPG_ERR_GENERAL;
    1913           0 :       goto out;
    1914             :     }
    1915             : 
    1916           0 :   if (! real_ldap)
    1917             :     /* We appear to have an OpenPGP Keyserver, which can unpack the key
    1918             :        on its own (not just a dumb LDAP server).  */
    1919             :     {
    1920             :       LDAPMod mod, *attrs[2];
    1921           0 :       char *key[] = { data, NULL };
    1922             :       char *dn;
    1923             : 
    1924           0 :       memset (&mod, 0, sizeof (mod));
    1925           0 :       mod.mod_op = LDAP_MOD_ADD;
    1926           0 :       mod.mod_type = pgpkeyattr;
    1927           0 :       mod.mod_values = key;
    1928           0 :       attrs[0] = &mod;
    1929           0 :       attrs[1] = NULL;
    1930             : 
    1931           0 :       dn = xasprintf ("pgpCertid=virtual,%s", basedn);
    1932           0 :       ldap_err = ldap_add_s (ldap_conn, dn, attrs);
    1933           0 :       xfree (dn);
    1934             : 
    1935           0 :       if (ldap_err != LDAP_SUCCESS)
    1936             :         {
    1937           0 :           err = ldap_err_to_gpg_err (err);
    1938           0 :           goto out;
    1939             :         }
    1940             : 
    1941           0 :       goto out;
    1942             :     }
    1943             : 
    1944           0 :   modlist = xmalloc (sizeof (LDAPMod *));
    1945           0 :   *modlist = NULL;
    1946             : 
    1947           0 :   if (dump_modlist)
    1948             :     {
    1949           0 :       dump = es_fopen("/tmp/modlist.txt", "w");
    1950           0 :       if (! dump)
    1951           0 :         log_error ("Failed to open /tmp/modlist.txt: %s\n",
    1952           0 :                    strerror (errno));
    1953             : 
    1954           0 :       if (dump)
    1955             :         {
    1956           0 :           es_fprintf(dump, "data (%zd bytes)\n", datalen);
    1957           0 :           es_fprintf(dump, "info (%zd bytes): '\n", infolen);
    1958           0 :           es_fwrite(info, infolen, 1, dump);
    1959           0 :           es_fprintf(dump, "'\n");
    1960             :         }
    1961             :     }
    1962             : 
    1963             :   /* Start by nulling out all attributes.  We try and do a modify
    1964             :      operation first, so this ensures that we don't leave old
    1965             :      attributes lying around. */
    1966           0 :   modlist_add (&modlist, "pgpDisabled", NULL);
    1967           0 :   modlist_add (&modlist, "pgpKeyID", NULL);
    1968           0 :   modlist_add (&modlist, "pgpKeyType", NULL);
    1969           0 :   modlist_add (&modlist, "pgpUserID", NULL);
    1970           0 :   modlist_add (&modlist, "pgpKeyCreateTime", NULL);
    1971           0 :   modlist_add (&modlist, "pgpSignerID", NULL);
    1972           0 :   modlist_add (&modlist, "pgpRevoked", NULL);
    1973           0 :   modlist_add (&modlist, "pgpSubKeyID", NULL);
    1974           0 :   modlist_add (&modlist, "pgpKeySize", NULL);
    1975           0 :   modlist_add (&modlist, "pgpKeyExpireTime", NULL);
    1976           0 :   modlist_add (&modlist, "pgpCertID", NULL);
    1977             : 
    1978             :   /* Assemble the INFO stuff into LDAP attributes */
    1979             : 
    1980           0 :   while (infolen > 0)
    1981             :     {
    1982           0 :       char *temp = NULL;
    1983             : 
    1984           0 :       char *newline = memchr (info, '\n', infolen);
    1985           0 :       if (! newline)
    1986             :         /* The last line is not \n terminated!  Make a copy so we can
    1987             :            add a NUL terminator.  */
    1988             :         {
    1989           0 :           temp = xmalloc (infolen + 1);
    1990           0 :           memcpy (temp, info, infolen);
    1991           0 :           info = temp;
    1992           0 :           newline = (char *) info + infolen;
    1993             :         }
    1994             : 
    1995           0 :       *newline = '\0';
    1996             : 
    1997           0 :       extract_attributes (&modlist, info);
    1998             : 
    1999           0 :       infolen = infolen - ((uintptr_t) newline - (uintptr_t) info + 1);
    2000           0 :       info = newline + 1;
    2001             : 
    2002             :       /* Sanity check.  */
    2003           0 :       if (! temp)
    2004           0 :         assert ((char *) info + infolen - 1 == infoend);
    2005             :       else
    2006             :         {
    2007           0 :           assert (infolen == -1);
    2008           0 :           xfree (temp);
    2009             :         }
    2010             :     }
    2011             : 
    2012           0 :   modlist_add (&addlist, "objectClass", "pgpKeyInfo");
    2013             : 
    2014           0 :   err = armor_data (&data_armored, data, datalen);
    2015           0 :   if (err)
    2016           0 :     goto out;
    2017             : 
    2018           0 :   modlist_add (&addlist, pgpkeyattr, data_armored);
    2019             : 
    2020             :   /* Now append addlist onto modlist.  */
    2021           0 :   modlists_join (&modlist, addlist);
    2022             : 
    2023           0 :   if (dump)
    2024             :     {
    2025           0 :       estream_t input = modlist_dump (modlist, NULL);
    2026           0 :       if (input)
    2027             :         {
    2028           0 :           copy_stream (input, dump);
    2029           0 :           es_fclose (input);
    2030             :         }
    2031             :     }
    2032             : 
    2033             :   /* Going on the assumption that modify operations are more frequent
    2034             :      than adds, we try a modify first.  If it's not there, we just
    2035             :      turn around and send an add command for the same key.  Otherwise,
    2036             :      the modify brings the server copy into compliance with our copy.
    2037             :      Note that unlike the LDAP keyserver (and really, any other
    2038             :      keyserver) this does NOT merge signatures, but replaces the whole
    2039             :      key.  This should make some people very happy. */
    2040             :   {
    2041             :     char **certid;
    2042             :     char *dn;
    2043             : 
    2044           0 :     certid = modlist_lookup (modlist, "pgpCertID");
    2045           0 :     if (/* We should have a value.  */
    2046             :         ! certid
    2047             :         /* Exactly one.  */
    2048           0 :         || !(certid[0] && !certid[1]))
    2049             :       {
    2050           0 :         log_error ("Bad certid.\n");
    2051           0 :         err = GPG_ERR_GENERAL;
    2052           0 :         goto out;
    2053             :       }
    2054             : 
    2055           0 :     dn = xasprintf ("pgpCertID=%s,%s", certid[0], basedn);
    2056             : 
    2057           0 :     err = ldap_modify_s (ldap_conn, dn, modlist);
    2058           0 :     if (err == LDAP_NO_SUCH_OBJECT)
    2059           0 :       err = ldap_add_s (ldap_conn, dn, addlist);
    2060             : 
    2061           0 :     xfree (dn);
    2062             : 
    2063           0 :     if (err != LDAP_SUCCESS)
    2064             :       {
    2065           0 :         log_error ("gpgkeys: error adding key to keyserver: %s\n",
    2066             :                    ldap_err2string (err));
    2067           0 :         err = ldap_err_to_gpg_err (err);
    2068             :       }
    2069             :   }
    2070             : 
    2071             :  out:
    2072           0 :   if (dump)
    2073           0 :     es_fclose (dump);
    2074             : 
    2075           0 :   if (ldap_conn)
    2076           0 :     ldap_unbind (ldap_conn);
    2077             : 
    2078           0 :   xfree (basedn);
    2079           0 :   xfree (pgpkeyattr);
    2080             : 
    2081           0 :   modlist_free (modlist);
    2082           0 :   xfree (addlist);
    2083             : 
    2084           0 :   xfree (data_armored);
    2085             : 
    2086           0 :   return err;
    2087             : }

Generated by: LCOV version 1.11