LCOV - code coverage report
Current view: top level - g10 - call-dirmngr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 552 0.5 %
Date: 2016-09-12 12:29:17 Functions: 1 21 4.8 %

          Line data    Source code
       1             : /* call-dirmngr.c - GPG operations to the Dirmngr.
       2             :  * Copyright (C) 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2015  g10 Code GmbH
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #include <unistd.h>
      27             : #include <time.h>
      28             : #ifdef HAVE_LOCALE_H
      29             : # include <locale.h>
      30             : #endif
      31             : 
      32             : #include "gpg.h"
      33             : #include <assuan.h>
      34             : #include "util.h"
      35             : #include "membuf.h"
      36             : #include "options.h"
      37             : #include "i18n.h"
      38             : #include "asshelp.h"
      39             : #include "keyserver.h"
      40             : #include "status.h"
      41             : #include "call-dirmngr.h"
      42             : 
      43             : 
      44             : /* Parameter structure used to gather status info.  */
      45             : struct ks_status_parm_s
      46             : {
      47             :   const char *keyword; /* Look for this keyword or NULL for "SOURCE". */
      48             :   char *source;
      49             : };
      50             : 
      51             : 
      52             : /* Parameter structure used with the KS_SEARCH command.  */
      53             : struct ks_search_parm_s
      54             : {
      55             :   gpg_error_t lasterr;  /* Last error code.  */
      56             :   membuf_t saveddata;   /* Buffer to build complete lines.  */
      57             :   char *helpbuf;        /* NULL or malloced buffer.  */
      58             :   size_t helpbufsize;   /* Allocated size of HELPBUF.  */
      59             :   gpg_error_t (*data_cb)(void*, int, char*);  /* Callback.  */
      60             :   void *data_cb_value;  /* First argument for DATA_CB.  */
      61             :   struct ks_status_parm_s *stparm; /* Link to the status parameter.  */
      62             : };
      63             : 
      64             : 
      65             : /* Parameter structure used with the KS_GET command.  */
      66             : struct ks_get_parm_s
      67             : {
      68             :   estream_t memfp;
      69             : };
      70             : 
      71             : 
      72             : /* Parameter structure used with the KS_PUT command.  */
      73             : struct ks_put_parm_s
      74             : {
      75             :   assuan_context_t ctx;
      76             :   kbnode_t keyblock;  /* The optional keyblock.  */
      77             :   const void *data;   /* The key in OpenPGP binary format.  */
      78             :   size_t datalen;     /* The length of DATA.  */
      79             : };
      80             : 
      81             : 
      82             : /* Parameter structure used with the DNS_CERT command.  */
      83             : struct dns_cert_parm_s
      84             : {
      85             :   estream_t memfp;
      86             :   unsigned char *fpr;
      87             :   size_t fprlen;
      88             :   char *url;
      89             : };
      90             : 
      91             : 
      92             : /* Data used to associate an session with dirmngr contexts.  We can't
      93             :    use a simple one to one mapping because we sometimes need two
      94             :    connections to the dirmngr; for example while doing a listing and
      95             :    being in a data callback we may want to retrieve a key.  The local
      96             :    dirmngr data takes care of this.  At the end of the session the
      97             :    function dirmngr_deinit_session_data is called by gpg.c to cleanup
      98             :    these resources.  Note that gpg.h defines a typedef dirmngr_local_t
      99             :    for this structure. */
     100             : struct dirmngr_local_s
     101             : {
     102             :   /* Link to other contexts which are used simultaneously.  */
     103             :   struct dirmngr_local_s *next;
     104             : 
     105             :   /* The active Assuan context. */
     106             :   assuan_context_t ctx;
     107             : 
     108             :   /* Flag set when the keyserver names have been send.  */
     109             :   int set_keyservers_done;
     110             : 
     111             :   /* Flag set to true while an operation is running on CTX.  */
     112             :   int is_active;
     113             : };
     114             : 
     115             : 
     116             : 
     117             : /* Deinitialize all session data of dirmngr pertaining to CTRL.  */
     118             : void
     119        1699 : gpg_dirmngr_deinit_session_data (ctrl_t ctrl)
     120             : {
     121             :   dirmngr_local_t dml;
     122             : 
     123        3398 :   while ((dml = ctrl->dirmngr_local))
     124             :     {
     125           0 :       ctrl->dirmngr_local = dml->next;
     126           0 :       if (dml->is_active)
     127           0 :         log_error ("oops: trying to cleanup an active dirmngr context\n");
     128             :       else
     129           0 :         assuan_release (dml->ctx);
     130           0 :       xfree (dml);
     131             :     }
     132        1699 : }
     133             : 
     134             : 
     135             : /* Print a warning if the server's version number is less than our
     136             :    version number.  Returns an error code on a connection problem.  */
     137             : static gpg_error_t
     138           0 : warn_version_mismatch (assuan_context_t ctx, const char *servername)
     139             : {
     140             :   gpg_error_t err;
     141             :   char *serverversion;
     142           0 :   const char *myversion = strusage (13);
     143             : 
     144           0 :   err = get_assuan_server_version (ctx, 0, &serverversion);
     145           0 :   if (err)
     146           0 :     log_error (_("error getting version from '%s': %s\n"),
     147             :                servername, gpg_strerror (err));
     148           0 :   else if (!compare_version_strings (serverversion, myversion))
     149             :     {
     150             :       char *warn;
     151             : 
     152           0 :       warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
     153             :                            servername, serverversion, myversion);
     154           0 :       if (!warn)
     155           0 :         err = gpg_error_from_syserror ();
     156             :       else
     157             :         {
     158           0 :           log_info (_("WARNING: %s\n"), warn);
     159           0 :           write_status_strings (STATUS_WARNING, "server_version_mismatch 0",
     160             :                                 " ", warn, NULL);
     161           0 :           xfree (warn);
     162             :         }
     163             :     }
     164           0 :   xfree (serverversion);
     165           0 :   return err;
     166             : }
     167             : 
     168             : 
     169             : /* Try to connect to the Dirmngr via a socket or spawn it if possible.
     170             :    Handle the server's initial greeting and set global options.  */
     171             : static gpg_error_t
     172           0 : create_context (ctrl_t ctrl, assuan_context_t *r_ctx)
     173             : {
     174             :   gpg_error_t err;
     175             :   assuan_context_t ctx;
     176             : 
     177           0 :   *r_ctx = NULL;
     178           0 :   err = start_new_dirmngr (&ctx,
     179             :                            GPG_ERR_SOURCE_DEFAULT,
     180             :                            opt.dirmngr_program,
     181           0 :                            opt.autostart, opt.verbose, DBG_IPC,
     182             :                            NULL /*gpg_status2*/, ctrl);
     183           0 :   if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
     184           0 :     {
     185             :       static int shown;
     186             : 
     187           0 :       if (!shown)
     188             :         {
     189           0 :           shown = 1;
     190           0 :           log_info (_("no dirmngr running in this session\n"));
     191             :         }
     192             :     }
     193           0 :   else if (!err && !(err = warn_version_mismatch (ctx, DIRMNGR_NAME)))
     194             :     {
     195             :       char *line;
     196             : 
     197             :       /* Tell the dirmngr that we want to collect audit event. */
     198             :       /* err = assuan_transact (agent_ctx, "OPTION audit-events=1", */
     199             :       /*                        NULL, NULL, NULL, NULL, NULL, NULL); */
     200           0 :       if (opt.keyserver_options.http_proxy)
     201             :         {
     202           0 :           line = xtryasprintf ("OPTION http-proxy=%s",
     203             :                                opt.keyserver_options.http_proxy);
     204           0 :           if (!line)
     205           0 :             err = gpg_error_from_syserror ();
     206             :           else
     207             :             {
     208           0 :               err = assuan_transact (ctx, line, NULL, NULL, NULL,
     209             :                                      NULL, NULL, NULL);
     210           0 :               xfree (line);
     211             :             }
     212             :         }
     213             : 
     214           0 :       if (err)
     215             :         ;
     216           0 :       else if ((opt.keyserver_options.options & KEYSERVER_HONOR_KEYSERVER_URL))
     217             :         {
     218             :           /* Tell the dirmngr that this possibly privacy invading
     219             :              option is in use.  If Dirmngr is running in Tor mode, it
     220             :              will return an error.  */
     221           0 :           err = assuan_transact (ctx, "OPTION honor-keyserver-url-used",
     222             :                                  NULL, NULL, NULL, NULL, NULL, NULL);
     223           0 :           if (gpg_err_code (err) == GPG_ERR_FORBIDDEN)
     224           0 :             log_error (_("keyserver option \"honor-keyserver-url\""
     225             :                          " may not be used in Tor mode\n"));
     226           0 :           else if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
     227           0 :             err = 0; /* Old dirmngr versions do not support this option.  */
     228             :         }
     229             :     }
     230             : 
     231           0 :   if (err)
     232           0 :     assuan_release (ctx);
     233             :   else
     234             :     {
     235             :       /* audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err); */
     236           0 :       *r_ctx = ctx;
     237             :     }
     238             : 
     239           0 :   return err;
     240             : }
     241             : 
     242             : 
     243             : /* Get a context for accessing dirmngr.  If no context is available a
     244             :    new one is created and - if required - dirmngr started.  On success
     245             :    an assuan context is stored at R_CTX.  This context may only be
     246             :    released by means of close_context.  Note that NULL is stored at
     247             :    R_CTX on error.  */
     248             : static gpg_error_t
     249           0 : open_context (ctrl_t ctrl, assuan_context_t *r_ctx)
     250             : {
     251             :   gpg_error_t err;
     252             :   dirmngr_local_t dml;
     253             : 
     254           0 :   *r_ctx = NULL;
     255             :   for (;;)
     256             :     {
     257           0 :       for (dml = ctrl->dirmngr_local; dml && dml->is_active; dml = dml->next)
     258             :         ;
     259           0 :       if (dml)
     260             :         {
     261             :           /* Found an inactive local session - return that.  */
     262           0 :           log_assert (!dml->is_active);
     263             : 
     264             :           /* But first do the per session init if not yet done.  */
     265           0 :           if (!dml->set_keyservers_done)
     266             :             {
     267             :               keyserver_spec_t ksi;
     268             : 
     269             :               /* Set all configured keyservers.  We clear existing
     270             :                  keyservers so that any keyserver configured in GPG
     271             :                  overrides keyservers possibly still configured in Dirmngr
     272             :                  for the session (Note that the keyserver list of a
     273             :                  session in Dirmngr survives a RESET. */
     274           0 :               for (ksi = opt.keyserver; ksi; ksi = ksi->next)
     275             :                 {
     276             :                   char *line;
     277             : 
     278           0 :                   line = xtryasprintf
     279             :                     ("KEYSERVER%s %s",
     280           0 :                      ksi == opt.keyserver? " --clear":"", ksi->uri);
     281           0 :                   if (!line)
     282           0 :                     err = gpg_error_from_syserror ();
     283             :                   else
     284             :                     {
     285           0 :                       err = assuan_transact (dml->ctx, line, NULL, NULL, NULL,
     286             :                                              NULL, NULL, NULL);
     287           0 :                       xfree (line);
     288             :                     }
     289             : 
     290           0 :                   if (err)
     291           0 :                     return err;
     292             :                 }
     293             : 
     294           0 :               dml->set_keyservers_done = 1;
     295             :             }
     296             : 
     297           0 :           dml->is_active = 1;
     298             : 
     299           0 :           *r_ctx = dml->ctx;
     300           0 :           return 0;
     301             :         }
     302             : 
     303           0 :       dml = xtrycalloc (1, sizeof *dml);
     304           0 :       if (!dml)
     305           0 :         return gpg_error_from_syserror ();
     306           0 :       err = create_context (ctrl, &dml->ctx);
     307           0 :       if (err)
     308             :         {
     309           0 :           xfree (dml);
     310           0 :           return err;
     311             :         }
     312             : 
     313             :       /* To be on the nPth thread safe site we need to add it to a
     314             :          list; this is far easier than to have a lock for this
     315             :          function.  It should not happen anyway but the code is free
     316             :          because we need it for the is_active check above.  */
     317           0 :       dml->next = ctrl->dirmngr_local;
     318           0 :       ctrl->dirmngr_local = dml;
     319           0 :     }
     320             : }
     321             : 
     322             : 
     323             : /* Close the assuan context CTX or return it to a pool of unused
     324             :    contexts.  If CTX is NULL, the function does nothing.  */
     325             : static void
     326           0 : close_context (ctrl_t ctrl, assuan_context_t ctx)
     327             : {
     328             :   dirmngr_local_t dml;
     329             : 
     330           0 :   if (!ctx)
     331           0 :     return;
     332             : 
     333           0 :   for (dml = ctrl->dirmngr_local; dml; dml = dml->next)
     334             :     {
     335           0 :       if (dml->ctx == ctx)
     336             :         {
     337           0 :           if (!dml->is_active)
     338           0 :             log_fatal ("closing inactive dirmngr context %p\n", ctx);
     339           0 :           dml->is_active = 0;
     340           0 :           return;
     341             :         }
     342             :     }
     343           0 :   log_fatal ("closing unknown dirmngr ctx %p\n", ctx);
     344             : }
     345             : 
     346             : 
     347             : /* Clear the set_keyservers_done flag on context CTX.  */
     348             : static void
     349           0 : clear_context_flags (ctrl_t ctrl, assuan_context_t ctx)
     350             : {
     351             :   dirmngr_local_t dml;
     352             : 
     353           0 :   if (!ctx)
     354           0 :     return;
     355             : 
     356           0 :   for (dml = ctrl->dirmngr_local; dml; dml = dml->next)
     357             :     {
     358           0 :       if (dml->ctx == ctx)
     359             :         {
     360           0 :           if (!dml->is_active)
     361           0 :             log_fatal ("clear_context_flags on inactive dirmngr ctx %p\n", ctx);
     362           0 :           dml->set_keyservers_done = 0;
     363           0 :           return;
     364             :         }
     365             :     }
     366           0 :   log_fatal ("clear_context_flags on unknown dirmngr ctx %p\n", ctx);
     367             : }
     368             : 
     369             : 
     370             : 
     371             : /* Status callback for ks_list, ks_get and ks_search.  */
     372             : static gpg_error_t
     373           0 : ks_status_cb (void *opaque, const char *line)
     374             : {
     375           0 :   struct ks_status_parm_s *parm = opaque;
     376           0 :   gpg_error_t err = 0;
     377             :   const char *s;
     378             : 
     379           0 :   if ((s = has_leading_keyword (line, parm->keyword? parm->keyword : "SOURCE")))
     380             :     {
     381           0 :       if (!parm->source)
     382             :         {
     383           0 :           parm->source = xtrystrdup (s);
     384           0 :           if (!parm->source)
     385           0 :             err = gpg_error_from_syserror ();
     386             :         }
     387             :     }
     388             : 
     389           0 :   return err;
     390             : }
     391             : 
     392             : 
     393             : 
     394             : /* Run the "KEYSERVER" command to return the name of the used
     395             :    keyserver at R_KEYSERVER.  */
     396             : gpg_error_t
     397           0 : gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver)
     398             : {
     399             :   gpg_error_t err;
     400             :   assuan_context_t ctx;
     401             :   struct ks_status_parm_s stparm;
     402             : 
     403           0 :   memset (&stparm, 0, sizeof stparm);
     404           0 :   stparm.keyword = "KEYSERVER";
     405           0 :   if (r_keyserver)
     406           0 :     *r_keyserver = NULL;
     407             : 
     408           0 :   err = open_context (ctrl, &ctx);
     409           0 :   if (err)
     410           0 :     return err;
     411             : 
     412           0 :   err = assuan_transact (ctx, "KEYSERVER", NULL, NULL,
     413             :                          NULL, NULL, ks_status_cb, &stparm);
     414           0 :   if (err)
     415           0 :     goto leave;
     416           0 :   if (!stparm.source)
     417             :     {
     418           0 :       err = gpg_error (GPG_ERR_NO_KEYSERVER);
     419           0 :       goto leave;
     420             :     }
     421             : 
     422           0 :   if (r_keyserver)
     423           0 :     *r_keyserver = stparm.source;
     424             :   else
     425           0 :     xfree (stparm.source);
     426           0 :   stparm.source = NULL;
     427             : 
     428             :  leave:
     429           0 :   xfree (stparm.source);
     430           0 :   close_context (ctrl, ctx);
     431           0 :   return err;
     432             : }
     433             : 
     434             : 
     435             : 
     436             : /* Data callback for the KS_SEARCH command. */
     437             : static gpg_error_t
     438           0 : ks_search_data_cb (void *opaque, const void *data, size_t datalen)
     439             : {
     440           0 :   gpg_error_t err = 0;
     441           0 :   struct ks_search_parm_s *parm = opaque;
     442             :   const char *line, *s;
     443             :   size_t rawlen, linelen;
     444             :   char fixedbuf[256];
     445             : 
     446           0 :   if (parm->lasterr)
     447           0 :     return 0;
     448             : 
     449           0 :   if (parm->stparm->source)
     450             :     {
     451           0 :       err = parm->data_cb (parm->data_cb_value, 1, parm->stparm->source);
     452           0 :       if (err)
     453             :         {
     454           0 :           parm->lasterr = err;
     455           0 :           return err;
     456             :         }
     457             :       /* Clear it so that we won't get back here unless the server
     458             :          accidentally sends a second source status line.  Note that
     459             :          will not see all accidentally sent source lines because it
     460             :          depends on whether data lines have been send in between.  */
     461           0 :       xfree (parm->stparm->source);
     462           0 :       parm->stparm->source = NULL;
     463             :     }
     464             : 
     465           0 :   if (!data)
     466           0 :     return 0;  /* Ignore END commands.  */
     467             : 
     468           0 :   put_membuf (&parm->saveddata, data, datalen);
     469             : 
     470             :  again:
     471           0 :   line = peek_membuf (&parm->saveddata, &rawlen);
     472           0 :   if (!line)
     473             :     {
     474           0 :       parm->lasterr = gpg_error_from_syserror ();
     475           0 :       return parm->lasterr; /* Tell the server about our problem.  */
     476             :     }
     477           0 :   if ((s = memchr (line, '\n', rawlen)))
     478             :     {
     479           0 :       linelen = s - line;  /* That is the length excluding the LF.  */
     480           0 :       if (linelen + 1 < sizeof fixedbuf)
     481             :         {
     482             :           /* We can use the static buffer.  */
     483           0 :           memcpy (fixedbuf, line, linelen);
     484           0 :           fixedbuf[linelen] = 0;
     485           0 :           if (linelen && fixedbuf[linelen-1] == '\r')
     486           0 :             fixedbuf[linelen-1] = 0;
     487           0 :           err = parm->data_cb (parm->data_cb_value, 0, fixedbuf);
     488             :         }
     489             :       else
     490             :         {
     491           0 :           if (linelen + 1 >= parm->helpbufsize)
     492             :             {
     493           0 :               xfree (parm->helpbuf);
     494           0 :               parm->helpbufsize = linelen + 1 + 1024;
     495           0 :               parm->helpbuf = xtrymalloc (parm->helpbufsize);
     496           0 :               if (!parm->helpbuf)
     497             :                 {
     498           0 :                   parm->lasterr = gpg_error_from_syserror ();
     499           0 :                   return parm->lasterr;
     500             :                 }
     501             :             }
     502           0 :           memcpy (parm->helpbuf, line, linelen);
     503           0 :           parm->helpbuf[linelen] = 0;
     504           0 :           if (linelen && parm->helpbuf[linelen-1] == '\r')
     505           0 :             parm->helpbuf[linelen-1] = 0;
     506           0 :           err = parm->data_cb (parm->data_cb_value, 0, parm->helpbuf);
     507             :         }
     508           0 :       if (err)
     509           0 :         parm->lasterr = err;
     510             :       else
     511             :         {
     512           0 :           clear_membuf (&parm->saveddata, linelen+1);
     513           0 :           goto again;  /* There might be another complete line.  */
     514             :         }
     515             :     }
     516             : 
     517           0 :   return err;
     518             : }
     519             : 
     520             : 
     521             : /* Run the KS_SEARCH command using the search string SEARCHSTR.  All
     522             :    data lines are passed to the CB function.  That function is called
     523             :    with CB_VALUE as its first argument, a 0 as second argument, and
     524             :    the decoded data line as third argument.  The callback function may
     525             :    modify the data line and it is guaranteed that this data line is a
     526             :    complete line with a terminating 0 character but without the
     527             :    linefeed.  NULL is passed to the callback to indicate EOF.  */
     528             : gpg_error_t
     529           0 : gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
     530             :                        gpg_error_t (*cb)(void*, int, char *), void *cb_value)
     531             : {
     532             :   gpg_error_t err;
     533             :   assuan_context_t ctx;
     534             :   struct ks_status_parm_s stparm;
     535             :   struct ks_search_parm_s parm;
     536             :   char line[ASSUAN_LINELENGTH];
     537             : 
     538           0 :   err = open_context (ctrl, &ctx);
     539           0 :   if (err)
     540           0 :     return err;
     541             : 
     542             :   {
     543           0 :     char *escsearchstr = percent_plus_escape (searchstr);
     544           0 :     if (!escsearchstr)
     545             :       {
     546           0 :         err = gpg_error_from_syserror ();
     547           0 :         close_context (ctrl, ctx);
     548           0 :         return err;
     549             :       }
     550           0 :     snprintf (line, sizeof line, "KS_SEARCH -- %s", escsearchstr);
     551           0 :     xfree (escsearchstr);
     552             :   }
     553             : 
     554           0 :   memset (&stparm, 0, sizeof stparm);
     555           0 :   memset (&parm, 0, sizeof parm);
     556           0 :   init_membuf (&parm.saveddata, 1024);
     557           0 :   parm.data_cb = cb;
     558           0 :   parm.data_cb_value = cb_value;
     559           0 :   parm.stparm = &stparm;
     560             : 
     561           0 :   err = assuan_transact (ctx, line, ks_search_data_cb, &parm,
     562             :                         NULL, NULL, ks_status_cb, &stparm);
     563           0 :   if (!err)
     564           0 :     err = cb (cb_value, 0, NULL);  /* Send EOF.  */
     565             : 
     566           0 :   xfree (get_membuf (&parm.saveddata, NULL));
     567           0 :   xfree (parm.helpbuf);
     568           0 :   xfree (stparm.source);
     569             : 
     570           0 :   close_context (ctrl, ctx);
     571           0 :   return err;
     572             : }
     573             : 
     574             : 
     575             : 
     576             : /* Data callback for the KS_GET and KS_FETCH commands. */
     577             : static gpg_error_t
     578           0 : ks_get_data_cb (void *opaque, const void *data, size_t datalen)
     579             : {
     580           0 :   gpg_error_t err = 0;
     581           0 :   struct ks_get_parm_s *parm = opaque;
     582             :   size_t nwritten;
     583             : 
     584           0 :   if (!data)
     585           0 :     return 0;  /* Ignore END commands.  */
     586             : 
     587           0 :   if (es_write (parm->memfp, data, datalen, &nwritten))
     588           0 :     err = gpg_error_from_syserror ();
     589             : 
     590           0 :   return err;
     591             : }
     592             : 
     593             : 
     594             : /* Run the KS_GET command using the patterns in the array PATTERN.  On
     595             :    success an estream object is returned to retrieve the keys.  On
     596             :    error an error code is returned and NULL stored at R_FP.
     597             : 
     598             :    The pattern may only use search specification which a keyserver can
     599             :    use to retrieve keys.  Because we know the format of the pattern we
     600             :    don't need to escape the patterns before sending them to the
     601             :    server.
     602             : 
     603             :    If R_SOURCE is not NULL the source of the data is stored as a
     604             :    malloced string there.  If a source is not known NULL is stored.
     605             : 
     606             :    If there are too many patterns the function returns an error.  That
     607             :    could be fixed by issuing several search commands or by
     608             :    implementing a different interface.  However with long keyids we
     609             :    are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once.  */
     610             : gpg_error_t
     611           0 : gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
     612             :                     keyserver_spec_t override_keyserver,
     613             :                     estream_t *r_fp, char **r_source)
     614             : {
     615             :   gpg_error_t err;
     616             :   assuan_context_t ctx;
     617             :   struct ks_status_parm_s stparm;
     618             :   struct ks_get_parm_s parm;
     619           0 :   char *line = NULL;
     620             :   size_t linelen;
     621             :   membuf_t mb;
     622             :   int idx;
     623             : 
     624           0 :   memset (&stparm, 0, sizeof stparm);
     625           0 :   memset (&parm, 0, sizeof parm);
     626             : 
     627           0 :   *r_fp = NULL;
     628           0 :   if (r_source)
     629           0 :     *r_source = NULL;
     630             : 
     631           0 :   err = open_context (ctrl, &ctx);
     632           0 :   if (err)
     633           0 :     return err;
     634             : 
     635             :   /* If we have an override keyserver we first indicate that the next
     636             :      user of the context needs to again setup the global keyservers and
     637             :      them we send the override keyserver.  */
     638           0 :   if (override_keyserver)
     639             :     {
     640           0 :       clear_context_flags (ctrl, ctx);
     641           0 :       line = xtryasprintf ("KEYSERVER --clear %s", override_keyserver->uri);
     642           0 :       if (!line)
     643             :         {
     644           0 :           err = gpg_error_from_syserror ();
     645           0 :           goto leave;
     646             :         }
     647           0 :       err = assuan_transact (ctx, line, NULL, NULL, NULL,
     648             :                              NULL, NULL, NULL);
     649           0 :       if (err)
     650           0 :         goto leave;
     651             : 
     652           0 :       xfree (line);
     653           0 :       line = NULL;
     654             :     }
     655             : 
     656             :   /* Lump all patterns into one string.  */
     657           0 :   init_membuf (&mb, 1024);
     658           0 :   put_membuf_str (&mb, "KS_GET --");
     659           0 :   for (idx=0; pattern[idx]; idx++)
     660             :     {
     661           0 :       put_membuf (&mb, " ", 1); /* Append Delimiter.  */
     662           0 :       put_membuf_str (&mb, pattern[idx]);
     663             :     }
     664           0 :   put_membuf (&mb, "", 1); /* Append Nul.  */
     665           0 :   line = get_membuf (&mb, &linelen);
     666           0 :   if (!line)
     667             :     {
     668           0 :       err = gpg_error_from_syserror ();
     669           0 :       goto leave;
     670             :     }
     671           0 :   if (linelen + 2 >= ASSUAN_LINELENGTH)
     672             :     {
     673           0 :       err = gpg_error (GPG_ERR_TOO_MANY);
     674           0 :       goto leave;
     675             :     }
     676             : 
     677           0 :   parm.memfp = es_fopenmem (0, "rwb");
     678           0 :   if (!parm.memfp)
     679             :     {
     680           0 :       err = gpg_error_from_syserror ();
     681           0 :       goto leave;
     682             :     }
     683           0 :   err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
     684             :                          NULL, NULL, ks_status_cb, &stparm);
     685           0 :   if (err)
     686           0 :     goto leave;
     687             : 
     688           0 :   es_rewind (parm.memfp);
     689           0 :   *r_fp = parm.memfp;
     690           0 :   parm.memfp = NULL;
     691             : 
     692           0 :   if (r_source)
     693             :     {
     694           0 :       *r_source = stparm.source;
     695           0 :       stparm.source = NULL;
     696             :     }
     697             : 
     698             :  leave:
     699           0 :   es_fclose (parm.memfp);
     700           0 :   xfree (stparm.source);
     701           0 :   xfree (line);
     702           0 :   close_context (ctrl, ctx);
     703           0 :   return err;
     704             : }
     705             : 
     706             : 
     707             : /* Run the KS_FETCH and pass URL as argument.  On success an estream
     708             :    object is returned to retrieve the keys.  On error an error code is
     709             :    returned and NULL stored at R_FP.
     710             : 
     711             :    The url is expected to point to a small set of keys; in many cases
     712             :    only to one key.  However, schemes like finger may return several
     713             :    keys.  Note that the configured keyservers are ignored by the
     714             :    KS_FETCH command.  */
     715             : gpg_error_t
     716           0 : gpg_dirmngr_ks_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
     717             : {
     718             :   gpg_error_t err;
     719             :   assuan_context_t ctx;
     720             :   struct ks_get_parm_s parm;
     721           0 :   char *line = NULL;
     722             : 
     723           0 :   memset (&parm, 0, sizeof parm);
     724             : 
     725           0 :   *r_fp = NULL;
     726             : 
     727           0 :   err = open_context (ctrl, &ctx);
     728           0 :   if (err)
     729           0 :     return err;
     730             : 
     731           0 :   line = strconcat ("KS_FETCH -- ", url, NULL);
     732           0 :   if (!line)
     733             :     {
     734           0 :       err = gpg_error_from_syserror ();
     735           0 :       goto leave;
     736             :     }
     737           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
     738             :     {
     739           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
     740           0 :       goto leave;
     741             :     }
     742             : 
     743           0 :   parm.memfp = es_fopenmem (0, "rwb");
     744           0 :   if (!parm.memfp)
     745             :     {
     746           0 :       err = gpg_error_from_syserror ();
     747           0 :       goto leave;
     748             :     }
     749           0 :   err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
     750             :                          NULL, NULL, NULL, NULL);
     751           0 :   if (err)
     752           0 :     goto leave;
     753             : 
     754           0 :   es_rewind (parm.memfp);
     755           0 :   *r_fp = parm.memfp;
     756           0 :   parm.memfp = NULL;
     757             : 
     758             :  leave:
     759           0 :   es_fclose (parm.memfp);
     760           0 :   xfree (line);
     761           0 :   close_context (ctrl, ctx);
     762           0 :   return err;
     763             : }
     764             : 
     765             : 
     766             : 
     767             : static void
     768           0 : record_output (estream_t output,
     769             :                pkttype_t type,
     770             :                const char *validity,
     771             :                /* The public key length or -1.  */
     772             :                int pub_key_length,
     773             :                /* The public key algo or -1.  */
     774             :                int pub_key_algo,
     775             :                /* 2 ulongs or NULL.  */
     776             :                const u32 *keyid,
     777             :                /* The creation / expiration date or 0.  */
     778             :                u32 creation_date,
     779             :                u32 expiration_date,
     780             :                const char *userid)
     781             : {
     782           0 :   const char *type_str = NULL;
     783           0 :   char *pub_key_length_str = NULL;
     784           0 :   char *pub_key_algo_str = NULL;
     785           0 :   char *keyid_str = NULL;
     786           0 :   char *creation_date_str = NULL;
     787           0 :   char *expiration_date_str = NULL;
     788           0 :   char *userid_escaped = NULL;
     789             : 
     790           0 :   switch (type)
     791             :     {
     792             :     case PKT_PUBLIC_KEY:
     793           0 :       type_str = "pub";
     794           0 :       break;
     795             :     case PKT_PUBLIC_SUBKEY:
     796           0 :       type_str = "sub";
     797           0 :       break;
     798             :     case PKT_USER_ID:
     799           0 :       type_str = "uid";
     800           0 :       break;
     801             :     case PKT_SIGNATURE:
     802           0 :       type_str = "sig";
     803           0 :       break;
     804             :     default:
     805           0 :       log_assert (! "Unhandled type.");
     806             :     }
     807             : 
     808           0 :   if (pub_key_length > 0)
     809           0 :     pub_key_length_str = xasprintf ("%d", pub_key_length);
     810             : 
     811           0 :   if (pub_key_algo != -1)
     812           0 :     pub_key_algo_str = xasprintf ("%d", pub_key_algo);
     813             : 
     814           0 :   if (keyid)
     815           0 :     keyid_str = xasprintf ("%08lX%08lX", (ulong) keyid[0], (ulong) keyid[1]);
     816             : 
     817           0 :   if (creation_date)
     818           0 :     creation_date_str = xstrdup (colon_strtime (creation_date));
     819             : 
     820           0 :   if (expiration_date)
     821           0 :     expiration_date_str = xstrdup (colon_strtime (expiration_date));
     822             : 
     823             :   /* Quote ':', '%', and any 8-bit characters.  */
     824           0 :   if (userid)
     825             :     {
     826             :       int r;
     827           0 :       int w = 0;
     828             : 
     829           0 :       int len = strlen (userid);
     830             :       /* A 100k character limit on the uid should be way more than
     831             :          enough.  */
     832           0 :       if (len > 100 * 1024)
     833           0 :         len = 100 * 1024;
     834             : 
     835             :       /* The minimum amount of space that we need.  */
     836           0 :       userid_escaped = xmalloc (len * 3 + 1);
     837             : 
     838           0 :       for (r = 0; r < len; r++)
     839             :         {
     840           0 :           if (userid[r] == ':' || userid[r]== '%' || (userid[r] & 0x80))
     841             :             {
     842           0 :               sprintf (&userid_escaped[w], "%%%02X", (byte) userid[r]);
     843           0 :               w += 3;
     844             :             }
     845             :           else
     846           0 :             userid_escaped[w ++] = userid[r];
     847             :         }
     848           0 :       userid_escaped[w] = '\0';
     849             :     }
     850             : 
     851           0 :   es_fprintf (output, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
     852             :               type_str,
     853           0 :               validity ?: "",
     854           0 :               pub_key_length_str ?: "",
     855           0 :               pub_key_algo_str ?: "",
     856           0 :               keyid_str ?: "",
     857           0 :               creation_date_str ?: "",
     858           0 :               expiration_date_str ?: "",
     859             :               "" /* Certificate S/N */,
     860             :               "" /* Ownertrust.  */,
     861           0 :               userid_escaped ?: "",
     862             :               "" /* Signature class.  */,
     863             :               "" /* Key capabilities.  */,
     864             :               "" /* Issuer certificate fingerprint.  */,
     865             :               "" /* Flag field.  */,
     866             :               "" /* S/N of a token.  */,
     867             :               "" /* Hash algo.  */,
     868             :               "" /* Curve name.  */);
     869             : 
     870           0 :   xfree (userid_escaped);
     871           0 :   xfree (expiration_date_str);
     872           0 :   xfree (creation_date_str);
     873           0 :   xfree (keyid_str);
     874           0 :   xfree (pub_key_algo_str);
     875           0 :   xfree (pub_key_length_str);
     876           0 : }
     877             : 
     878             : /* Handle the KS_PUT inquiries. */
     879             : static gpg_error_t
     880           0 : ks_put_inq_cb (void *opaque, const char *line)
     881             : {
     882           0 :   struct ks_put_parm_s *parm = opaque;
     883           0 :   gpg_error_t err = 0;
     884             : 
     885           0 :   if (has_leading_keyword (line, "KEYBLOCK"))
     886             :     {
     887           0 :       if (parm->data)
     888           0 :         err = assuan_send_data (parm->ctx, parm->data, parm->datalen);
     889             :     }
     890           0 :   else if (has_leading_keyword (line, "KEYBLOCK_INFO"))
     891             :     {
     892             :       kbnode_t node;
     893             :       estream_t fp;
     894             : 
     895             :       /* Parse the keyblock and send info lines back to the server.  */
     896           0 :       fp = es_fopenmem (0, "rw,samethread");
     897           0 :       if (!fp)
     898           0 :         err = gpg_error_from_syserror ();
     899             : 
     900             :       /* Note: the output format for the INFO block follows the colon
     901             :          format as described in doc/DETAILS.  We don't actually reuse
     902             :          the functionality from g10/keylist.c to produce the output,
     903             :          because we don't need all of it and some of it is quite
     904             :          expensive to generate.
     905             : 
     906             :          The fields are (the starred fields are the ones we need):
     907             : 
     908             :            * Field 1 - Type of record
     909             :            * Field 2 - Validity
     910             :            * Field 3 - Key length
     911             :            * Field 4 - Public key algorithm
     912             :            * Field 5 - KeyID
     913             :            * Field 6 - Creation date
     914             :            * Field 7 - Expiration date
     915             :              Field 8 - Certificate S/N, UID hash, trust signature info
     916             :              Field 9 -  Ownertrust
     917             :            * Field 10 - User-ID
     918             :              Field 11 - Signature class
     919             :              Field 12 - Key capabilities
     920             :              Field 13 - Issuer certificate fingerprint or other info
     921             :              Field 14 - Flag field
     922             :              Field 15 - S/N of a token
     923             :              Field 16 - Hash algorithm
     924             :              Field 17 - Curve name
     925             :        */
     926           0 :       for (node = parm->keyblock; !err && node; node=node->next)
     927             :         {
     928           0 :           switch (node->pkt->pkttype)
     929             :             {
     930             :             case PKT_PUBLIC_KEY:
     931             :             case PKT_PUBLIC_SUBKEY:
     932             :               {
     933           0 :                 PKT_public_key *pk = node->pkt->pkt.public_key;
     934             : 
     935             :                 char validity[3];
     936             :                 int i;
     937             : 
     938           0 :                 i = 0;
     939           0 :                 if (pk->flags.revoked)
     940           0 :                   validity[i ++] = 'r';
     941           0 :                 if (pk->has_expired)
     942           0 :                   validity[i ++] = 'e';
     943           0 :                 validity[i] = '\0';
     944             : 
     945           0 :                 keyid_from_pk (pk, NULL);
     946             : 
     947           0 :                 record_output (fp, node->pkt->pkttype, validity,
     948           0 :                                nbits_from_pk (pk), pk->pubkey_algo,
     949           0 :                                pk->keyid, pk->timestamp, pk->expiredate,
     950             :                                NULL);
     951             :               }
     952           0 :               break;
     953             : 
     954             :             case PKT_USER_ID:
     955             :               {
     956           0 :                 PKT_user_id *uid = node->pkt->pkt.user_id;
     957             : 
     958           0 :                 if (!uid->attrib_data)
     959             :                   {
     960             :                     char validity[3];
     961             :                     int i;
     962             : 
     963           0 :                     i = 0;
     964           0 :                     if (uid->is_revoked)
     965           0 :                       validity[i ++] = 'r';
     966           0 :                     if (uid->is_expired)
     967           0 :                       validity[i ++] = 'e';
     968           0 :                     validity[i] = '\0';
     969             : 
     970           0 :                     record_output (fp, node->pkt->pkttype, validity,
     971             :                                    -1, -1, NULL,
     972             :                                    uid->created, uid->expiredate,
     973           0 :                                    uid->name);
     974             :                   }
     975             :               }
     976           0 :               break;
     977             : 
     978             :               /* This bit is really for the benefit of people who
     979             :                  store their keys in LDAP servers.  It makes it easy
     980             :                  to do queries for things like "all keys signed by
     981             :                  Isabella".  */
     982             :             case PKT_SIGNATURE:
     983             :               {
     984           0 :                 PKT_signature *sig = node->pkt->pkt.signature;
     985             : 
     986           0 :                 if (IS_UID_SIG (sig))
     987           0 :                   record_output (fp, node->pkt->pkttype, NULL,
     988           0 :                                  -1, -1, sig->keyid,
     989             :                                  sig->timestamp, sig->expiredate, NULL);
     990             :               }
     991           0 :               break;
     992             : 
     993             :             default:
     994           0 :               continue;
     995             :             }
     996             :           /* Given that the last operation was an es_fprintf we should
     997             :              get the correct ERRNO if ferror indicates an error.  */
     998           0 :           if (es_ferror (fp))
     999           0 :             err = gpg_error_from_syserror ();
    1000             :         }
    1001             : 
    1002             :       /* Without an error and if we have an keyblock at all, send the
    1003             :          data back.  */
    1004           0 :       if (!err && parm->keyblock)
    1005             :         {
    1006             :           int rc;
    1007             :           char buffer[512];
    1008             :           size_t nread;
    1009             : 
    1010           0 :           es_rewind (fp);
    1011           0 :           while (!(rc=es_read (fp, buffer, sizeof buffer, &nread)) && nread)
    1012             :             {
    1013           0 :               err = assuan_send_data (parm->ctx, buffer, nread);
    1014           0 :               if (err)
    1015           0 :                 break;
    1016             :             }
    1017           0 :           if (!err && rc)
    1018           0 :             err = gpg_error_from_syserror ();
    1019             :         }
    1020           0 :       es_fclose (fp);
    1021             :     }
    1022             :   else
    1023           0 :     return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
    1024             : 
    1025           0 :   return err;
    1026             : }
    1027             : 
    1028             : 
    1029             : /* Send a key to the configured server.  {DATA,DATLEN} contains the
    1030             :    key in OpenPGP binary transport format.  If KEYBLOCK is not NULL it
    1031             :    has the internal representaion of that key; this is for example
    1032             :    used to convey meta data to LDAP keyservers.  */
    1033             : gpg_error_t
    1034           0 : gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
    1035             : {
    1036             :   gpg_error_t err;
    1037             :   assuan_context_t ctx;
    1038             :   struct ks_put_parm_s parm;
    1039             : 
    1040           0 :   memset (&parm, 0, sizeof parm);
    1041             : 
    1042             :   /* We are going to parse the keyblock, thus we better make sure the
    1043             :      all information is readily available.  */
    1044           0 :   if (keyblock)
    1045           0 :     merge_keys_and_selfsig (keyblock);
    1046             : 
    1047           0 :   err = open_context (ctrl, &ctx);
    1048           0 :   if (err)
    1049           0 :     return err;
    1050             : 
    1051           0 :   parm.ctx = ctx;
    1052           0 :   parm.keyblock = keyblock;
    1053           0 :   parm.data = data;
    1054           0 :   parm.datalen = datalen;
    1055             : 
    1056           0 :   err = assuan_transact (ctx, "KS_PUT", NULL, NULL,
    1057             :                          ks_put_inq_cb, &parm, NULL, NULL);
    1058             : 
    1059           0 :   close_context (ctrl, ctx);
    1060           0 :   return err;
    1061             : }
    1062             : 
    1063             : 
    1064             : 
    1065             : /* Data callback for the DNS_CERT and WKD_GET commands. */
    1066             : static gpg_error_t
    1067           0 : dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
    1068             : {
    1069           0 :   struct dns_cert_parm_s *parm = opaque;
    1070           0 :   gpg_error_t err = 0;
    1071             :   size_t nwritten;
    1072             : 
    1073           0 :   if (!data)
    1074           0 :     return 0;  /* Ignore END commands.  */
    1075           0 :   if (!parm->memfp)
    1076           0 :     return 0;  /* Data is not required.  */
    1077             : 
    1078           0 :   if (es_write (parm->memfp, data, datalen, &nwritten))
    1079           0 :     err = gpg_error_from_syserror ();
    1080             : 
    1081           0 :   return err;
    1082             : }
    1083             : 
    1084             : 
    1085             : /* Status callback for the DNS_CERT command.  */
    1086             : static gpg_error_t
    1087           0 : dns_cert_status_cb (void *opaque, const char *line)
    1088             : {
    1089           0 :   struct dns_cert_parm_s *parm = opaque;
    1090           0 :   gpg_error_t err = 0;
    1091             :   const char *s;
    1092             :   size_t nbytes;
    1093             : 
    1094           0 :   if ((s = has_leading_keyword (line, "FPR")))
    1095             :     {
    1096             :       char *buf;
    1097             : 
    1098           0 :       if (!(buf = xtrystrdup (s)))
    1099           0 :         err = gpg_error_from_syserror ();
    1100           0 :       else if (parm->fpr)
    1101           0 :         err = gpg_error (GPG_ERR_DUP_KEY);
    1102           0 :       else if (!hex2str (buf, buf, strlen (buf)+1, &nbytes))
    1103           0 :         err = gpg_error_from_syserror ();
    1104           0 :       else if (nbytes < 20)
    1105           0 :         err = gpg_error (GPG_ERR_TOO_SHORT);
    1106             :       else
    1107             :         {
    1108           0 :           parm->fpr = xtrymalloc (nbytes);
    1109           0 :           if (!parm->fpr)
    1110           0 :             err = gpg_error_from_syserror ();
    1111             :           else
    1112           0 :             memcpy (parm->fpr, buf, (parm->fprlen = nbytes));
    1113             :         }
    1114           0 :       xfree (buf);
    1115             :     }
    1116           0 :   else if ((s = has_leading_keyword (line, "URL")) && *s)
    1117             :     {
    1118           0 :       if (parm->url)
    1119           0 :         err = gpg_error (GPG_ERR_DUP_KEY);
    1120           0 :       else if (!(parm->url = xtrystrdup (s)))
    1121           0 :         err = gpg_error_from_syserror ();
    1122             :     }
    1123             : 
    1124           0 :   return err;
    1125             : }
    1126             : 
    1127             : /* Ask the dirmngr for a DNS CERT record.  Depending on the found
    1128             :    subtypes different return values are set:
    1129             : 
    1130             :    - For a PGP subtype a new estream with that key will be returned at
    1131             :      R_KEY and the other return parameters are set to NULL/0.
    1132             : 
    1133             :    - For an IPGP subtype the fingerprint is stored as a malloced block
    1134             :      at (R_FPR,R_FPRLEN).  If an URL is available it is stored as a
    1135             :      malloced string at R_URL; NULL is stored if there is no URL.
    1136             : 
    1137             :    If CERTTYPE is DNS_CERTTYPE_ANY this function returns the first
    1138             :    CERT record found with a supported type; it is expected that only
    1139             :    one CERT record is used.  If CERTTYPE is one of the supported
    1140             :    certtypes, only records with this certtype are considered and the
    1141             :    first one found is returned.  All R_* args are optional.
    1142             : 
    1143             :    If CERTTYPE is NULL the DANE method is used to fetch the key.
    1144             :  */
    1145             : gpg_error_t
    1146           0 : gpg_dirmngr_dns_cert (ctrl_t ctrl, const char *name, const char *certtype,
    1147             :                       estream_t *r_key,
    1148             :                       unsigned char **r_fpr, size_t *r_fprlen,
    1149             :                       char **r_url)
    1150             : {
    1151             :   gpg_error_t err;
    1152             :   assuan_context_t ctx;
    1153             :   struct dns_cert_parm_s parm;
    1154           0 :   char *line = NULL;
    1155             : 
    1156           0 :   memset (&parm, 0, sizeof parm);
    1157           0 :   if (r_key)
    1158           0 :     *r_key = NULL;
    1159           0 :   if (r_fpr)
    1160           0 :     *r_fpr = NULL;
    1161           0 :   if (r_fprlen)
    1162           0 :     *r_fprlen = 0;
    1163           0 :   if (r_url)
    1164           0 :     *r_url = NULL;
    1165             : 
    1166           0 :   err = open_context (ctrl, &ctx);
    1167           0 :   if (err)
    1168           0 :     return err;
    1169             : 
    1170           0 :   line = es_bsprintf ("DNS_CERT %s %s", certtype? certtype : "--dane", name);
    1171           0 :   if (!line)
    1172             :     {
    1173           0 :       err = gpg_error_from_syserror ();
    1174           0 :       goto leave;
    1175             :     }
    1176           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1177             :     {
    1178           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1179           0 :       goto leave;
    1180             :     }
    1181             : 
    1182           0 :   parm.memfp = es_fopenmem (0, "rwb");
    1183           0 :   if (!parm.memfp)
    1184             :     {
    1185           0 :       err = gpg_error_from_syserror ();
    1186           0 :       goto leave;
    1187             :     }
    1188           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1189             :                          NULL, NULL, dns_cert_status_cb, &parm);
    1190           0 :   if (err)
    1191           0 :     goto leave;
    1192             : 
    1193           0 :   if (r_key)
    1194             :     {
    1195           0 :       es_rewind (parm.memfp);
    1196           0 :       *r_key = parm.memfp;
    1197           0 :       parm.memfp = NULL;
    1198             :     }
    1199             : 
    1200           0 :   if (r_fpr && parm.fpr)
    1201             :     {
    1202           0 :       *r_fpr = parm.fpr;
    1203           0 :       parm.fpr = NULL;
    1204             :     }
    1205           0 :   if (r_fprlen)
    1206           0 :     *r_fprlen = parm.fprlen;
    1207             : 
    1208           0 :   if (r_url && parm.url)
    1209             :     {
    1210           0 :       *r_url = parm.url;
    1211           0 :       parm.url = NULL;
    1212             :     }
    1213             : 
    1214             :  leave:
    1215           0 :   xfree (parm.fpr);
    1216           0 :   xfree (parm.url);
    1217           0 :   es_fclose (parm.memfp);
    1218           0 :   xfree (line);
    1219           0 :   close_context (ctrl, ctx);
    1220           0 :   return err;
    1221             : }
    1222             : 
    1223             : 
    1224             : /* Ask the dirmngr for PKA info.  On success the retrieved fingerprint
    1225             :    is returned in a malloced buffer at R_FPR and its length is stored
    1226             :    at R_FPRLEN.  If an URL is available it is stored as a malloced
    1227             :    string at R_URL.  On error all return values are set to NULL/0.  */
    1228             : gpg_error_t
    1229           0 : gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
    1230             :                      unsigned char **r_fpr, size_t *r_fprlen,
    1231             :                      char **r_url)
    1232             : {
    1233             :   gpg_error_t err;
    1234             :   assuan_context_t ctx;
    1235             :   struct dns_cert_parm_s parm;
    1236           0 :   char *line = NULL;
    1237             : 
    1238           0 :   memset (&parm, 0, sizeof parm);
    1239           0 :   if (r_fpr)
    1240           0 :     *r_fpr = NULL;
    1241           0 :   if (r_fprlen)
    1242           0 :     *r_fprlen = 0;
    1243           0 :   if (r_url)
    1244           0 :     *r_url = NULL;
    1245             : 
    1246           0 :   err = open_context (ctrl, &ctx);
    1247           0 :   if (err)
    1248           0 :     return err;
    1249             : 
    1250           0 :   line = es_bsprintf ("DNS_CERT --pka -- %s", userid);
    1251           0 :   if (!line)
    1252             :     {
    1253           0 :       err = gpg_error_from_syserror ();
    1254           0 :       goto leave;
    1255             :     }
    1256           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1257             :     {
    1258           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1259           0 :       goto leave;
    1260             :     }
    1261             : 
    1262           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1263             :                          NULL, NULL, dns_cert_status_cb, &parm);
    1264           0 :   if (err)
    1265           0 :     goto leave;
    1266             : 
    1267           0 :   if (r_fpr && parm.fpr)
    1268             :     {
    1269           0 :       *r_fpr = parm.fpr;
    1270           0 :       parm.fpr = NULL;
    1271             :     }
    1272           0 :   if (r_fprlen)
    1273           0 :     *r_fprlen = parm.fprlen;
    1274             : 
    1275           0 :   if (r_url && parm.url)
    1276             :     {
    1277           0 :       *r_url = parm.url;
    1278           0 :       parm.url = NULL;
    1279             :     }
    1280             : 
    1281             :  leave:
    1282           0 :   xfree (parm.fpr);
    1283           0 :   xfree (parm.url);
    1284           0 :   xfree (line);
    1285           0 :   close_context (ctrl, ctx);
    1286           0 :   return err;
    1287             : }
    1288             : 
    1289             : 
    1290             : 
    1291             : /* Ask the dirmngr to retrieve a key via the Web Key Directory
    1292             :  * protocol.  On success a new estream with the key is stored at
    1293             :  * R_KEY.
    1294             :  */
    1295             : gpg_error_t
    1296           0 : gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, estream_t *r_key)
    1297             : {
    1298             :   gpg_error_t err;
    1299             :   assuan_context_t ctx;
    1300             :   struct dns_cert_parm_s parm;
    1301           0 :   char *line = NULL;
    1302             : 
    1303           0 :   memset (&parm, 0, sizeof parm);
    1304             : 
    1305           0 :   err = open_context (ctrl, &ctx);
    1306           0 :   if (err)
    1307           0 :     return err;
    1308             : 
    1309           0 :   line = es_bsprintf ("WKD_GET -- %s", name);
    1310           0 :   if (!line)
    1311             :     {
    1312           0 :       err = gpg_error_from_syserror ();
    1313           0 :       goto leave;
    1314             :     }
    1315           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1316             :     {
    1317           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1318           0 :       goto leave;
    1319             :     }
    1320             : 
    1321           0 :   parm.memfp = es_fopenmem (0, "rwb");
    1322           0 :   if (!parm.memfp)
    1323             :     {
    1324           0 :       err = gpg_error_from_syserror ();
    1325           0 :       goto leave;
    1326             :     }
    1327           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1328             :                          NULL, NULL, NULL, &parm);
    1329           0 :   if (err)
    1330           0 :     goto leave;
    1331             : 
    1332           0 :   if (r_key)
    1333             :     {
    1334           0 :       es_rewind (parm.memfp);
    1335           0 :       *r_key = parm.memfp;
    1336           0 :       parm.memfp = NULL;
    1337             :     }
    1338             : 
    1339             :  leave:
    1340           0 :   xfree (parm.fpr);
    1341           0 :   xfree (parm.url);
    1342           0 :   es_fclose (parm.memfp);
    1343           0 :   xfree (line);
    1344           0 :   close_context (ctrl, ctx);
    1345           0 :   return err;
    1346             : }

Generated by: LCOV version 1.11