LCOV - code coverage report
Current view: top level - g10 - call-dirmngr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 506 0.6 %
Date: 2015-11-05 17:10:59 Functions: 1 19 5.3 %

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

Generated by: LCOV version 1.11