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-11-29 15:00:56 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 <https://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        1177 : gpg_dirmngr_deinit_session_data (ctrl_t ctrl)
     120             : {
     121             :   dirmngr_local_t dml;
     122             : 
     123        2354 :   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        1177 : }
     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) < 0)
     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 QUICK is set the dirmngr is advised to use a shorter timeout.
     604             : 
     605             :    If R_SOURCE is not NULL the source of the data is stored as a
     606             :    malloced string there.  If a source is not known NULL is stored.
     607             : 
     608             :    If there are too many patterns the function returns an error.  That
     609             :    could be fixed by issuing several search commands or by
     610             :    implementing a different interface.  However with long keyids we
     611             :    are able to ask for (1000-10-1)/(2+8+1) = 90 keys at once.  */
     612             : gpg_error_t
     613           0 : gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
     614             :                     keyserver_spec_t override_keyserver, int quick,
     615             :                     estream_t *r_fp, char **r_source)
     616             : {
     617             :   gpg_error_t err;
     618             :   assuan_context_t ctx;
     619             :   struct ks_status_parm_s stparm;
     620             :   struct ks_get_parm_s parm;
     621           0 :   char *line = NULL;
     622             :   size_t linelen;
     623             :   membuf_t mb;
     624             :   int idx;
     625             : 
     626           0 :   memset (&stparm, 0, sizeof stparm);
     627           0 :   memset (&parm, 0, sizeof parm);
     628             : 
     629           0 :   *r_fp = NULL;
     630           0 :   if (r_source)
     631           0 :     *r_source = NULL;
     632             : 
     633           0 :   err = open_context (ctrl, &ctx);
     634           0 :   if (err)
     635           0 :     return err;
     636             : 
     637             :   /* If we have an override keyserver we first indicate that the next
     638             :      user of the context needs to again setup the global keyservers and
     639             :      them we send the override keyserver.  */
     640           0 :   if (override_keyserver)
     641             :     {
     642           0 :       clear_context_flags (ctrl, ctx);
     643           0 :       line = xtryasprintf ("KEYSERVER --clear %s", override_keyserver->uri);
     644           0 :       if (!line)
     645             :         {
     646           0 :           err = gpg_error_from_syserror ();
     647           0 :           goto leave;
     648             :         }
     649           0 :       err = assuan_transact (ctx, line, NULL, NULL, NULL,
     650             :                              NULL, NULL, NULL);
     651           0 :       if (err)
     652           0 :         goto leave;
     653             : 
     654           0 :       xfree (line);
     655           0 :       line = NULL;
     656             :     }
     657             : 
     658             :   /* Lump all patterns into one string.  */
     659           0 :   init_membuf (&mb, 1024);
     660           0 :   put_membuf_str (&mb, quick? "KS_GET --quick --" : "KS_GET --");
     661           0 :   for (idx=0; pattern[idx]; idx++)
     662             :     {
     663           0 :       put_membuf (&mb, " ", 1); /* Append Delimiter.  */
     664           0 :       put_membuf_str (&mb, pattern[idx]);
     665             :     }
     666           0 :   put_membuf (&mb, "", 1); /* Append Nul.  */
     667           0 :   line = get_membuf (&mb, &linelen);
     668           0 :   if (!line)
     669             :     {
     670           0 :       err = gpg_error_from_syserror ();
     671           0 :       goto leave;
     672             :     }
     673           0 :   if (linelen + 2 >= ASSUAN_LINELENGTH)
     674             :     {
     675           0 :       err = gpg_error (GPG_ERR_TOO_MANY);
     676           0 :       goto leave;
     677             :     }
     678             : 
     679           0 :   parm.memfp = es_fopenmem (0, "rwb");
     680           0 :   if (!parm.memfp)
     681             :     {
     682           0 :       err = gpg_error_from_syserror ();
     683           0 :       goto leave;
     684             :     }
     685           0 :   err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
     686             :                          NULL, NULL, ks_status_cb, &stparm);
     687           0 :   if (err)
     688           0 :     goto leave;
     689             : 
     690           0 :   es_rewind (parm.memfp);
     691           0 :   *r_fp = parm.memfp;
     692           0 :   parm.memfp = NULL;
     693             : 
     694           0 :   if (r_source)
     695             :     {
     696           0 :       *r_source = stparm.source;
     697           0 :       stparm.source = NULL;
     698             :     }
     699             : 
     700             :  leave:
     701           0 :   es_fclose (parm.memfp);
     702           0 :   xfree (stparm.source);
     703           0 :   xfree (line);
     704           0 :   close_context (ctrl, ctx);
     705           0 :   return err;
     706             : }
     707             : 
     708             : 
     709             : /* Run the KS_FETCH and pass URL as argument.  On success an estream
     710             :    object is returned to retrieve the keys.  On error an error code is
     711             :    returned and NULL stored at R_FP.
     712             : 
     713             :    The url is expected to point to a small set of keys; in many cases
     714             :    only to one key.  However, schemes like finger may return several
     715             :    keys.  Note that the configured keyservers are ignored by the
     716             :    KS_FETCH command.  */
     717             : gpg_error_t
     718           0 : gpg_dirmngr_ks_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp)
     719             : {
     720             :   gpg_error_t err;
     721             :   assuan_context_t ctx;
     722             :   struct ks_get_parm_s parm;
     723           0 :   char *line = NULL;
     724             : 
     725           0 :   memset (&parm, 0, sizeof parm);
     726             : 
     727           0 :   *r_fp = NULL;
     728             : 
     729           0 :   err = open_context (ctrl, &ctx);
     730           0 :   if (err)
     731           0 :     return err;
     732             : 
     733           0 :   line = strconcat ("KS_FETCH -- ", url, NULL);
     734           0 :   if (!line)
     735             :     {
     736           0 :       err = gpg_error_from_syserror ();
     737           0 :       goto leave;
     738             :     }
     739           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
     740             :     {
     741           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
     742           0 :       goto leave;
     743             :     }
     744             : 
     745           0 :   parm.memfp = es_fopenmem (0, "rwb");
     746           0 :   if (!parm.memfp)
     747             :     {
     748           0 :       err = gpg_error_from_syserror ();
     749           0 :       goto leave;
     750             :     }
     751           0 :   err = assuan_transact (ctx, line, ks_get_data_cb, &parm,
     752             :                          NULL, NULL, NULL, NULL);
     753           0 :   if (err)
     754           0 :     goto leave;
     755             : 
     756           0 :   es_rewind (parm.memfp);
     757           0 :   *r_fp = parm.memfp;
     758           0 :   parm.memfp = NULL;
     759             : 
     760             :  leave:
     761           0 :   es_fclose (parm.memfp);
     762           0 :   xfree (line);
     763           0 :   close_context (ctrl, ctx);
     764           0 :   return err;
     765             : }
     766             : 
     767             : 
     768             : 
     769             : static void
     770           0 : record_output (estream_t output,
     771             :                pkttype_t type,
     772             :                const char *validity,
     773             :                /* The public key length or -1.  */
     774             :                int pub_key_length,
     775             :                /* The public key algo or -1.  */
     776             :                int pub_key_algo,
     777             :                /* 2 ulongs or NULL.  */
     778             :                const u32 *keyid,
     779             :                /* The creation / expiration date or 0.  */
     780             :                u32 creation_date,
     781             :                u32 expiration_date,
     782             :                const char *userid)
     783             : {
     784           0 :   const char *type_str = NULL;
     785           0 :   char *pub_key_length_str = NULL;
     786           0 :   char *pub_key_algo_str = NULL;
     787           0 :   char *keyid_str = NULL;
     788           0 :   char *creation_date_str = NULL;
     789           0 :   char *expiration_date_str = NULL;
     790           0 :   char *userid_escaped = NULL;
     791             : 
     792           0 :   switch (type)
     793             :     {
     794             :     case PKT_PUBLIC_KEY:
     795           0 :       type_str = "pub";
     796           0 :       break;
     797             :     case PKT_PUBLIC_SUBKEY:
     798           0 :       type_str = "sub";
     799           0 :       break;
     800             :     case PKT_USER_ID:
     801           0 :       type_str = "uid";
     802           0 :       break;
     803             :     case PKT_SIGNATURE:
     804           0 :       type_str = "sig";
     805           0 :       break;
     806             :     default:
     807           0 :       log_assert (! "Unhandled type.");
     808             :     }
     809             : 
     810           0 :   if (pub_key_length > 0)
     811           0 :     pub_key_length_str = xasprintf ("%d", pub_key_length);
     812             : 
     813           0 :   if (pub_key_algo != -1)
     814           0 :     pub_key_algo_str = xasprintf ("%d", pub_key_algo);
     815             : 
     816           0 :   if (keyid)
     817           0 :     keyid_str = xasprintf ("%08lX%08lX", (ulong) keyid[0], (ulong) keyid[1]);
     818             : 
     819           0 :   if (creation_date)
     820           0 :     creation_date_str = xstrdup (colon_strtime (creation_date));
     821             : 
     822           0 :   if (expiration_date)
     823           0 :     expiration_date_str = xstrdup (colon_strtime (expiration_date));
     824             : 
     825             :   /* Quote ':', '%', and any 8-bit characters.  */
     826           0 :   if (userid)
     827             :     {
     828             :       int r;
     829           0 :       int w = 0;
     830             : 
     831           0 :       int len = strlen (userid);
     832             :       /* A 100k character limit on the uid should be way more than
     833             :          enough.  */
     834           0 :       if (len > 100 * 1024)
     835           0 :         len = 100 * 1024;
     836             : 
     837             :       /* The minimum amount of space that we need.  */
     838           0 :       userid_escaped = xmalloc (len * 3 + 1);
     839             : 
     840           0 :       for (r = 0; r < len; r++)
     841             :         {
     842           0 :           if (userid[r] == ':' || userid[r]== '%' || (userid[r] & 0x80))
     843             :             {
     844           0 :               sprintf (&userid_escaped[w], "%%%02X", (byte) userid[r]);
     845           0 :               w += 3;
     846             :             }
     847             :           else
     848           0 :             userid_escaped[w ++] = userid[r];
     849             :         }
     850           0 :       userid_escaped[w] = '\0';
     851             :     }
     852             : 
     853           0 :   es_fprintf (output, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
     854             :               type_str,
     855           0 :               validity ?: "",
     856           0 :               pub_key_length_str ?: "",
     857           0 :               pub_key_algo_str ?: "",
     858           0 :               keyid_str ?: "",
     859           0 :               creation_date_str ?: "",
     860           0 :               expiration_date_str ?: "",
     861             :               "" /* Certificate S/N */,
     862             :               "" /* Ownertrust.  */,
     863           0 :               userid_escaped ?: "",
     864             :               "" /* Signature class.  */,
     865             :               "" /* Key capabilities.  */,
     866             :               "" /* Issuer certificate fingerprint.  */,
     867             :               "" /* Flag field.  */,
     868             :               "" /* S/N of a token.  */,
     869             :               "" /* Hash algo.  */,
     870             :               "" /* Curve name.  */);
     871             : 
     872           0 :   xfree (userid_escaped);
     873           0 :   xfree (expiration_date_str);
     874           0 :   xfree (creation_date_str);
     875           0 :   xfree (keyid_str);
     876           0 :   xfree (pub_key_algo_str);
     877           0 :   xfree (pub_key_length_str);
     878           0 : }
     879             : 
     880             : /* Handle the KS_PUT inquiries. */
     881             : static gpg_error_t
     882           0 : ks_put_inq_cb (void *opaque, const char *line)
     883             : {
     884           0 :   struct ks_put_parm_s *parm = opaque;
     885           0 :   gpg_error_t err = 0;
     886             : 
     887           0 :   if (has_leading_keyword (line, "KEYBLOCK"))
     888             :     {
     889           0 :       if (parm->data)
     890           0 :         err = assuan_send_data (parm->ctx, parm->data, parm->datalen);
     891             :     }
     892           0 :   else if (has_leading_keyword (line, "KEYBLOCK_INFO"))
     893             :     {
     894             :       kbnode_t node;
     895             :       estream_t fp;
     896             : 
     897             :       /* Parse the keyblock and send info lines back to the server.  */
     898           0 :       fp = es_fopenmem (0, "rw,samethread");
     899           0 :       if (!fp)
     900           0 :         err = gpg_error_from_syserror ();
     901             : 
     902             :       /* Note: the output format for the INFO block follows the colon
     903             :          format as described in doc/DETAILS.  We don't actually reuse
     904             :          the functionality from g10/keylist.c to produce the output,
     905             :          because we don't need all of it and some of it is quite
     906             :          expensive to generate.
     907             : 
     908             :          The fields are (the starred fields are the ones we need):
     909             : 
     910             :            * Field 1 - Type of record
     911             :            * Field 2 - Validity
     912             :            * Field 3 - Key length
     913             :            * Field 4 - Public key algorithm
     914             :            * Field 5 - KeyID
     915             :            * Field 6 - Creation date
     916             :            * Field 7 - Expiration date
     917             :              Field 8 - Certificate S/N, UID hash, trust signature info
     918             :              Field 9 -  Ownertrust
     919             :            * Field 10 - User-ID
     920             :              Field 11 - Signature class
     921             :              Field 12 - Key capabilities
     922             :              Field 13 - Issuer certificate fingerprint or other info
     923             :              Field 14 - Flag field
     924             :              Field 15 - S/N of a token
     925             :              Field 16 - Hash algorithm
     926             :              Field 17 - Curve name
     927             :        */
     928           0 :       for (node = parm->keyblock; !err && node; node=node->next)
     929             :         {
     930           0 :           switch (node->pkt->pkttype)
     931             :             {
     932             :             case PKT_PUBLIC_KEY:
     933             :             case PKT_PUBLIC_SUBKEY:
     934             :               {
     935           0 :                 PKT_public_key *pk = node->pkt->pkt.public_key;
     936             : 
     937             :                 char validity[3];
     938             :                 int i;
     939             : 
     940           0 :                 i = 0;
     941           0 :                 if (pk->flags.revoked)
     942           0 :                   validity[i ++] = 'r';
     943           0 :                 if (pk->has_expired)
     944           0 :                   validity[i ++] = 'e';
     945           0 :                 validity[i] = '\0';
     946             : 
     947           0 :                 keyid_from_pk (pk, NULL);
     948             : 
     949           0 :                 record_output (fp, node->pkt->pkttype, validity,
     950           0 :                                nbits_from_pk (pk), pk->pubkey_algo,
     951           0 :                                pk->keyid, pk->timestamp, pk->expiredate,
     952             :                                NULL);
     953             :               }
     954           0 :               break;
     955             : 
     956             :             case PKT_USER_ID:
     957             :               {
     958           0 :                 PKT_user_id *uid = node->pkt->pkt.user_id;
     959             : 
     960           0 :                 if (!uid->attrib_data)
     961             :                   {
     962             :                     char validity[3];
     963             :                     int i;
     964             : 
     965           0 :                     i = 0;
     966           0 :                     if (uid->is_revoked)
     967           0 :                       validity[i ++] = 'r';
     968           0 :                     if (uid->is_expired)
     969           0 :                       validity[i ++] = 'e';
     970           0 :                     validity[i] = '\0';
     971             : 
     972           0 :                     record_output (fp, node->pkt->pkttype, validity,
     973             :                                    -1, -1, NULL,
     974             :                                    uid->created, uid->expiredate,
     975           0 :                                    uid->name);
     976             :                   }
     977             :               }
     978           0 :               break;
     979             : 
     980             :               /* This bit is really for the benefit of people who
     981             :                  store their keys in LDAP servers.  It makes it easy
     982             :                  to do queries for things like "all keys signed by
     983             :                  Isabella".  */
     984             :             case PKT_SIGNATURE:
     985             :               {
     986           0 :                 PKT_signature *sig = node->pkt->pkt.signature;
     987             : 
     988           0 :                 if (IS_UID_SIG (sig))
     989           0 :                   record_output (fp, node->pkt->pkttype, NULL,
     990           0 :                                  -1, -1, sig->keyid,
     991             :                                  sig->timestamp, sig->expiredate, NULL);
     992             :               }
     993           0 :               break;
     994             : 
     995             :             default:
     996           0 :               continue;
     997             :             }
     998             :           /* Given that the last operation was an es_fprintf we should
     999             :              get the correct ERRNO if ferror indicates an error.  */
    1000           0 :           if (es_ferror (fp))
    1001           0 :             err = gpg_error_from_syserror ();
    1002             :         }
    1003             : 
    1004             :       /* Without an error and if we have an keyblock at all, send the
    1005             :          data back.  */
    1006           0 :       if (!err && parm->keyblock)
    1007             :         {
    1008             :           int rc;
    1009             :           char buffer[512];
    1010             :           size_t nread;
    1011             : 
    1012           0 :           es_rewind (fp);
    1013           0 :           while (!(rc=es_read (fp, buffer, sizeof buffer, &nread)) && nread)
    1014             :             {
    1015           0 :               err = assuan_send_data (parm->ctx, buffer, nread);
    1016           0 :               if (err)
    1017           0 :                 break;
    1018             :             }
    1019           0 :           if (!err && rc)
    1020           0 :             err = gpg_error_from_syserror ();
    1021             :         }
    1022           0 :       es_fclose (fp);
    1023             :     }
    1024             :   else
    1025           0 :     return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
    1026             : 
    1027           0 :   return err;
    1028             : }
    1029             : 
    1030             : 
    1031             : /* Send a key to the configured server.  {DATA,DATLEN} contains the
    1032             :    key in OpenPGP binary transport format.  If KEYBLOCK is not NULL it
    1033             :    has the internal representaion of that key; this is for example
    1034             :    used to convey meta data to LDAP keyservers.  */
    1035             : gpg_error_t
    1036           0 : gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
    1037             : {
    1038             :   gpg_error_t err;
    1039             :   assuan_context_t ctx;
    1040             :   struct ks_put_parm_s parm;
    1041             : 
    1042           0 :   memset (&parm, 0, sizeof parm);
    1043             : 
    1044             :   /* We are going to parse the keyblock, thus we better make sure the
    1045             :      all information is readily available.  */
    1046           0 :   if (keyblock)
    1047           0 :     merge_keys_and_selfsig (keyblock);
    1048             : 
    1049           0 :   err = open_context (ctrl, &ctx);
    1050           0 :   if (err)
    1051           0 :     return err;
    1052             : 
    1053           0 :   parm.ctx = ctx;
    1054           0 :   parm.keyblock = keyblock;
    1055           0 :   parm.data = data;
    1056           0 :   parm.datalen = datalen;
    1057             : 
    1058           0 :   err = assuan_transact (ctx, "KS_PUT", NULL, NULL,
    1059             :                          ks_put_inq_cb, &parm, NULL, NULL);
    1060             : 
    1061           0 :   close_context (ctrl, ctx);
    1062           0 :   return err;
    1063             : }
    1064             : 
    1065             : 
    1066             : 
    1067             : /* Data callback for the DNS_CERT and WKD_GET commands. */
    1068             : static gpg_error_t
    1069           0 : dns_cert_data_cb (void *opaque, const void *data, size_t datalen)
    1070             : {
    1071           0 :   struct dns_cert_parm_s *parm = opaque;
    1072           0 :   gpg_error_t err = 0;
    1073             :   size_t nwritten;
    1074             : 
    1075           0 :   if (!data)
    1076           0 :     return 0;  /* Ignore END commands.  */
    1077           0 :   if (!parm->memfp)
    1078           0 :     return 0;  /* Data is not required.  */
    1079             : 
    1080           0 :   if (es_write (parm->memfp, data, datalen, &nwritten))
    1081           0 :     err = gpg_error_from_syserror ();
    1082             : 
    1083           0 :   return err;
    1084             : }
    1085             : 
    1086             : 
    1087             : /* Status callback for the DNS_CERT command.  */
    1088             : static gpg_error_t
    1089           0 : dns_cert_status_cb (void *opaque, const char *line)
    1090             : {
    1091           0 :   struct dns_cert_parm_s *parm = opaque;
    1092           0 :   gpg_error_t err = 0;
    1093             :   const char *s;
    1094             :   size_t nbytes;
    1095             : 
    1096           0 :   if ((s = has_leading_keyword (line, "FPR")))
    1097             :     {
    1098             :       char *buf;
    1099             : 
    1100           0 :       if (!(buf = xtrystrdup (s)))
    1101           0 :         err = gpg_error_from_syserror ();
    1102           0 :       else if (parm->fpr)
    1103           0 :         err = gpg_error (GPG_ERR_DUP_KEY);
    1104           0 :       else if (!hex2str (buf, buf, strlen (buf)+1, &nbytes))
    1105           0 :         err = gpg_error_from_syserror ();
    1106           0 :       else if (nbytes < 20)
    1107           0 :         err = gpg_error (GPG_ERR_TOO_SHORT);
    1108             :       else
    1109             :         {
    1110           0 :           parm->fpr = xtrymalloc (nbytes);
    1111           0 :           if (!parm->fpr)
    1112           0 :             err = gpg_error_from_syserror ();
    1113             :           else
    1114           0 :             memcpy (parm->fpr, buf, (parm->fprlen = nbytes));
    1115             :         }
    1116           0 :       xfree (buf);
    1117             :     }
    1118           0 :   else if ((s = has_leading_keyword (line, "URL")) && *s)
    1119             :     {
    1120           0 :       if (parm->url)
    1121           0 :         err = gpg_error (GPG_ERR_DUP_KEY);
    1122           0 :       else if (!(parm->url = xtrystrdup (s)))
    1123           0 :         err = gpg_error_from_syserror ();
    1124             :     }
    1125             : 
    1126           0 :   return err;
    1127             : }
    1128             : 
    1129             : /* Ask the dirmngr for a DNS CERT record.  Depending on the found
    1130             :    subtypes different return values are set:
    1131             : 
    1132             :    - For a PGP subtype a new estream with that key will be returned at
    1133             :      R_KEY and the other return parameters are set to NULL/0.
    1134             : 
    1135             :    - For an IPGP subtype the fingerprint is stored as a malloced block
    1136             :      at (R_FPR,R_FPRLEN).  If an URL is available it is stored as a
    1137             :      malloced string at R_URL; NULL is stored if there is no URL.
    1138             : 
    1139             :    If CERTTYPE is DNS_CERTTYPE_ANY this function returns the first
    1140             :    CERT record found with a supported type; it is expected that only
    1141             :    one CERT record is used.  If CERTTYPE is one of the supported
    1142             :    certtypes, only records with this certtype are considered and the
    1143             :    first one found is returned.  All R_* args are optional.
    1144             : 
    1145             :    If CERTTYPE is NULL the DANE method is used to fetch the key.
    1146             :  */
    1147             : gpg_error_t
    1148           0 : gpg_dirmngr_dns_cert (ctrl_t ctrl, const char *name, const char *certtype,
    1149             :                       estream_t *r_key,
    1150             :                       unsigned char **r_fpr, size_t *r_fprlen,
    1151             :                       char **r_url)
    1152             : {
    1153             :   gpg_error_t err;
    1154             :   assuan_context_t ctx;
    1155             :   struct dns_cert_parm_s parm;
    1156           0 :   char *line = NULL;
    1157             : 
    1158           0 :   memset (&parm, 0, sizeof parm);
    1159           0 :   if (r_key)
    1160           0 :     *r_key = NULL;
    1161           0 :   if (r_fpr)
    1162           0 :     *r_fpr = NULL;
    1163           0 :   if (r_fprlen)
    1164           0 :     *r_fprlen = 0;
    1165           0 :   if (r_url)
    1166           0 :     *r_url = NULL;
    1167             : 
    1168           0 :   err = open_context (ctrl, &ctx);
    1169           0 :   if (err)
    1170           0 :     return err;
    1171             : 
    1172           0 :   line = es_bsprintf ("DNS_CERT %s %s", certtype? certtype : "--dane", name);
    1173           0 :   if (!line)
    1174             :     {
    1175           0 :       err = gpg_error_from_syserror ();
    1176           0 :       goto leave;
    1177             :     }
    1178           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1179             :     {
    1180           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1181           0 :       goto leave;
    1182             :     }
    1183             : 
    1184           0 :   parm.memfp = es_fopenmem (0, "rwb");
    1185           0 :   if (!parm.memfp)
    1186             :     {
    1187           0 :       err = gpg_error_from_syserror ();
    1188           0 :       goto leave;
    1189             :     }
    1190           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1191             :                          NULL, NULL, dns_cert_status_cb, &parm);
    1192           0 :   if (err)
    1193           0 :     goto leave;
    1194             : 
    1195           0 :   if (r_key)
    1196             :     {
    1197           0 :       es_rewind (parm.memfp);
    1198           0 :       *r_key = parm.memfp;
    1199           0 :       parm.memfp = NULL;
    1200             :     }
    1201             : 
    1202           0 :   if (r_fpr && parm.fpr)
    1203             :     {
    1204           0 :       *r_fpr = parm.fpr;
    1205           0 :       parm.fpr = NULL;
    1206             :     }
    1207           0 :   if (r_fprlen)
    1208           0 :     *r_fprlen = parm.fprlen;
    1209             : 
    1210           0 :   if (r_url && parm.url)
    1211             :     {
    1212           0 :       *r_url = parm.url;
    1213           0 :       parm.url = NULL;
    1214             :     }
    1215             : 
    1216             :  leave:
    1217           0 :   xfree (parm.fpr);
    1218           0 :   xfree (parm.url);
    1219           0 :   es_fclose (parm.memfp);
    1220           0 :   xfree (line);
    1221           0 :   close_context (ctrl, ctx);
    1222           0 :   return err;
    1223             : }
    1224             : 
    1225             : 
    1226             : /* Ask the dirmngr for PKA info.  On success the retrieved fingerprint
    1227             :    is returned in a malloced buffer at R_FPR and its length is stored
    1228             :    at R_FPRLEN.  If an URL is available it is stored as a malloced
    1229             :    string at R_URL.  On error all return values are set to NULL/0.  */
    1230             : gpg_error_t
    1231           0 : gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
    1232             :                      unsigned char **r_fpr, size_t *r_fprlen,
    1233             :                      char **r_url)
    1234             : {
    1235             :   gpg_error_t err;
    1236             :   assuan_context_t ctx;
    1237             :   struct dns_cert_parm_s parm;
    1238           0 :   char *line = NULL;
    1239             : 
    1240           0 :   memset (&parm, 0, sizeof parm);
    1241           0 :   if (r_fpr)
    1242           0 :     *r_fpr = NULL;
    1243           0 :   if (r_fprlen)
    1244           0 :     *r_fprlen = 0;
    1245           0 :   if (r_url)
    1246           0 :     *r_url = NULL;
    1247             : 
    1248           0 :   err = open_context (ctrl, &ctx);
    1249           0 :   if (err)
    1250           0 :     return err;
    1251             : 
    1252           0 :   line = es_bsprintf ("DNS_CERT --pka -- %s", userid);
    1253           0 :   if (!line)
    1254             :     {
    1255           0 :       err = gpg_error_from_syserror ();
    1256           0 :       goto leave;
    1257             :     }
    1258           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1259             :     {
    1260           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1261           0 :       goto leave;
    1262             :     }
    1263             : 
    1264           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1265             :                          NULL, NULL, dns_cert_status_cb, &parm);
    1266           0 :   if (err)
    1267           0 :     goto leave;
    1268             : 
    1269           0 :   if (r_fpr && parm.fpr)
    1270             :     {
    1271           0 :       *r_fpr = parm.fpr;
    1272           0 :       parm.fpr = NULL;
    1273             :     }
    1274           0 :   if (r_fprlen)
    1275           0 :     *r_fprlen = parm.fprlen;
    1276             : 
    1277           0 :   if (r_url && parm.url)
    1278             :     {
    1279           0 :       *r_url = parm.url;
    1280           0 :       parm.url = NULL;
    1281             :     }
    1282             : 
    1283             :  leave:
    1284           0 :   xfree (parm.fpr);
    1285           0 :   xfree (parm.url);
    1286           0 :   xfree (line);
    1287           0 :   close_context (ctrl, ctx);
    1288           0 :   return err;
    1289             : }
    1290             : 
    1291             : 
    1292             : 
    1293             : /* Ask the dirmngr to retrieve a key via the Web Key Directory
    1294             :  * protocol.  If QUICK is set the dirmngr is advised to use a shorter
    1295             :  * timeout.  On success a new estream with the key is stored at R_KEY.
    1296             :  */
    1297             : gpg_error_t
    1298           0 : gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
    1299             : {
    1300             :   gpg_error_t err;
    1301             :   assuan_context_t ctx;
    1302             :   struct dns_cert_parm_s parm;
    1303           0 :   char *line = NULL;
    1304             : 
    1305           0 :   memset (&parm, 0, sizeof parm);
    1306             : 
    1307           0 :   err = open_context (ctrl, &ctx);
    1308           0 :   if (err)
    1309           0 :     return err;
    1310             : 
    1311           0 :   line = es_bsprintf ("WKD_GET%s -- %s", quick?" --quick":"", name);
    1312           0 :   if (!line)
    1313             :     {
    1314           0 :       err = gpg_error_from_syserror ();
    1315           0 :       goto leave;
    1316             :     }
    1317           0 :   if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    1318             :     {
    1319           0 :       err = gpg_error (GPG_ERR_TOO_LARGE);
    1320           0 :       goto leave;
    1321             :     }
    1322             : 
    1323           0 :   parm.memfp = es_fopenmem (0, "rwb");
    1324           0 :   if (!parm.memfp)
    1325             :     {
    1326           0 :       err = gpg_error_from_syserror ();
    1327           0 :       goto leave;
    1328             :     }
    1329           0 :   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
    1330             :                          NULL, NULL, NULL, &parm);
    1331           0 :   if (err)
    1332           0 :     goto leave;
    1333             : 
    1334           0 :   if (r_key)
    1335             :     {
    1336           0 :       es_rewind (parm.memfp);
    1337           0 :       *r_key = parm.memfp;
    1338           0 :       parm.memfp = NULL;
    1339             :     }
    1340             : 
    1341             :  leave:
    1342           0 :   xfree (parm.fpr);
    1343           0 :   xfree (parm.url);
    1344           0 :   es_fclose (parm.memfp);
    1345           0 :   xfree (line);
    1346           0 :   close_context (ctrl, ctx);
    1347           0 :   return err;
    1348             : }

Generated by: LCOV version 1.11