Implemented the chain model for X.509 validation.
[gnupg.git] / sm / call-dirmngr.c
1 /* call-dirmngr.c - communication with the dromngr 
2  *      Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h> 
26 #include <time.h>
27 #include <assert.h>
28 #include <ctype.h>
29
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <assuan.h>
33
34 #include "i18n.h"
35 #include "keydb.h"
36
37 /* The name of the socket for a system daemon.  */
38 #define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket"
39
40 struct membuf {
41   size_t len;
42   size_t size;
43   char *buf;
44   int out_of_core;
45 };
46
47
48
49 static assuan_context_t dirmngr_ctx = NULL;
50 static int force_pipe_server = 0;
51
52 struct inq_certificate_parm_s {
53   assuan_context_t ctx;
54   ksba_cert_t cert;
55   ksba_cert_t issuer_cert;
56 };
57
58 struct isvalid_status_parm_s {
59   ctrl_t ctrl;
60   int seen;
61   unsigned char fpr[20];
62 };
63
64
65 struct lookup_parm_s {
66   ctrl_t ctrl;
67   assuan_context_t ctx;
68   void (*cb)(void *, ksba_cert_t);
69   void *cb_value;
70   struct membuf data;
71   int error;
72 };
73
74 struct run_command_parm_s {
75   assuan_context_t ctx;
76 };
77
78
79 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
80    create a buffer, put_membuf to append bytes and get_membuf to
81    release and return the buffer.  Allocation errors are detected but
82    only returned at the final get_membuf(), this helps not to clutter
83    the code with out of core checks.  */
84
85 static void
86 init_membuf (struct membuf *mb, int initiallen)
87 {
88   mb->len = 0;
89   mb->size = initiallen;
90   mb->out_of_core = 0;
91   mb->buf = xtrymalloc (initiallen);
92   if (!mb->buf)
93       mb->out_of_core = 1;
94 }
95
96 static void
97 put_membuf (struct membuf *mb, const void *buf, size_t len)
98 {
99   if (mb->out_of_core)
100     return;
101
102   if (mb->len + len >= mb->size)
103     {
104       char *p;
105       
106       mb->size += len + 1024;
107       p = xtryrealloc (mb->buf, mb->size);
108       if (!p)
109         {
110           mb->out_of_core = 1;
111           return;
112         }
113       mb->buf = p;
114     }
115   memcpy (mb->buf + mb->len, buf, len);
116   mb->len += len;
117 }
118
119 static void *
120 get_membuf (struct membuf *mb, size_t *len)
121 {
122   char *p;
123
124   if (mb->out_of_core)
125     {
126       xfree (mb->buf);
127       mb->buf = NULL;
128       return NULL;
129     }
130
131   p = mb->buf;
132   *len = mb->len;
133   mb->buf = NULL;
134   mb->out_of_core = 1; /* don't allow a reuse */
135   return p;
136 }
137
138
139
140
141 \f
142 /* Try to connect to the agent via socket or fork it off and work by
143    pipes.  Handle the server's initial greeting */
144 static int
145 start_dirmngr (void)
146 {
147   int rc;
148   char *infostr, *p;
149   assuan_context_t ctx;
150   int try_default = 0;
151
152   if (dirmngr_ctx)
153     return 0; /* fixme: We need a context for each thread or serialize
154                  the access to the dirmngr */
155   /* Note: if you change this to multiple connections, you also need
156      to take care of the implicit option sending caching. */
157
158   infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
159   if (opt.prefer_system_dirmngr && !force_pipe_server
160       &&(!infostr || !*infostr))
161     {
162       infostr = DEFAULT_SOCKET_NAME;
163       try_default = 1;
164     }
165   if (!infostr || !*infostr)
166     {
167       const char *pgmname;
168       const char *argv[3];
169       int no_close_list[3];
170       int i;
171
172       if (!opt.dirmngr_program || !*opt.dirmngr_program)
173         opt.dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
174       if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
175         pgmname = opt.dirmngr_program;
176       else
177         pgmname++;
178
179       if (opt.verbose)
180         log_info (_("no running dirmngr - starting `%s'\n"),
181                   opt.dirmngr_program);
182       
183       if (fflush (NULL))
184         {
185           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
186           log_error ("error flushing pending output: %s\n", strerror (errno));
187           return tmperr;
188         }
189
190       argv[0] = pgmname;
191       argv[1] = "--server";
192       argv[2] = NULL;
193
194       i=0;
195       if (log_get_fd () != -1)
196         no_close_list[i++] = log_get_fd ();
197       no_close_list[i++] = fileno (stderr);
198       no_close_list[i] = -1;
199
200       /* connect to the agent and perform initial handshaking */
201       rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, argv,
202                                 no_close_list);
203     }
204   else
205     {
206       int prot;
207       int pid;
208
209       infostr = xstrdup (infostr);
210       if (!try_default && *infostr)
211         {
212           if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
213             {
214               log_error (_("malformed DIRMNGR_INFO environment variable\n"));
215               xfree (infostr);
216               force_pipe_server = 1;
217               return start_dirmngr ();
218             }
219           *p++ = 0;
220           pid = atoi (p);
221           while (*p && *p != PATHSEP_C)
222             p++;
223           prot = *p? atoi (p+1) : 0;
224           if (prot != 1)
225             {
226               log_error (_("dirmngr protocol version %d is not supported\n"),
227                          prot);
228               xfree (infostr);
229               force_pipe_server = 1;
230               return start_dirmngr ();
231             }
232         }
233       else
234         pid = -1;
235
236       rc = assuan_socket_connect (&ctx, infostr, pid);
237       xfree (infostr);
238       if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
239         {
240           log_error (_("can't connect to the dirmngr - trying fall back\n"));
241           force_pipe_server = 1;
242           return start_dirmngr ();
243         }
244     }
245
246   if (rc)
247     {
248       log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
249       return gpg_error (GPG_ERR_NO_DIRMNGR);
250     }
251   dirmngr_ctx = ctx;
252
253   if (DBG_ASSUAN)
254     log_debug ("connection to dirmngr established\n");
255   return 0;
256 }
257
258
259 \f
260 /* Handle a SENDCERT inquiry. */
261 static int
262 inq_certificate (void *opaque, const char *line)
263 {
264   struct inq_certificate_parm_s *parm = opaque;
265   int rc;
266   const unsigned char *der;
267   size_t derlen;
268   int issuer_mode = 0;
269   ksba_sexp_t ski = NULL;
270
271   if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
272     {
273       line += 8;
274     }
275   else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12]))
276     {
277       size_t n;
278
279       /* Send a certificate where a sourceKeyIdentifier is included. */
280       line += 12;
281       while (*line == ' ')
282         line++;
283       ski = make_simple_sexp_from_hexstr (line, &n);
284       line += n;
285       while (*line == ' ')
286         line++;
287     }
288   else if (!strncmp (line, "SENDISSUERCERT", 14)
289            && (line[14] == ' ' || !line[14]))
290     {
291       line += 14;
292       issuer_mode = 1;
293     }
294   else
295     {
296       log_error ("unsupported inquiry `%s'\n", line);
297       return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
298     }
299
300   if (!*line)
301     { /* Send the current certificate. */
302       der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
303                                  &derlen);
304       if (!der)
305         rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
306       else
307         rc = assuan_send_data (parm->ctx, der, derlen);
308     }
309   else if (issuer_mode)
310     {
311       log_error ("sending specific issuer certificate back "
312                  "is not yet implemented\n");
313       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
314     }
315   else 
316     { /* Send the given certificate. */
317       int err;
318       ksba_cert_t cert;
319
320
321       err = gpgsm_find_cert (line, ski, &cert);
322       if (err)
323         {
324           log_error ("certificate not found: %s\n", gpg_strerror (err));
325           rc = gpg_error (GPG_ERR_NOT_FOUND);
326         }
327       else
328         {
329           der = ksba_cert_get_image (cert, &derlen);
330           if (!der)
331             rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
332           else
333             rc = assuan_send_data (parm->ctx, der, derlen);
334           ksba_cert_release (cert);
335         }
336     }
337
338   xfree (ski);
339   return rc; 
340 }
341
342
343 /* Take a 20 byte hexencoded string and put it into the the provided
344    20 byte buffer FPR in binary format. */
345 static int
346 unhexify_fpr (const char *hexstr, unsigned char *fpr)
347 {
348   const char *s;
349   int n;
350
351   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
352     ;
353   if (*s || (n != 40))
354     return 0; /* no fingerprint (invalid or wrong length). */
355   n /= 2;
356   for (s=hexstr, n=0; *s; s += 2, n++)
357     fpr[n] = xtoi_2 (s);
358   return 1; /* okay */
359 }
360
361
362 static assuan_error_t
363 isvalid_status_cb (void *opaque, const char *line)
364 {
365   struct isvalid_status_parm_s *parm = opaque;
366
367   if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
368     {
369       if (parm->ctrl)
370         {
371           for (line += 8; *line == ' '; line++)
372             ;
373           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
374             return gpg_error (GPG_ERR_ASS_CANCELED);
375         }
376     }
377   else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
378       && (line[24]==' ' || !line[24]))
379     {
380       parm->seen++;
381       if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
382         parm->seen++; /* Bumb it to indicate an error. */
383     }
384   return 0;
385 }
386
387
388
389 \f
390 /* Call the directory manager to check whether the certificate is valid
391    Returns 0 for valid or usually one of the errors:
392
393   GPG_ERR_CERTIFICATE_REVOKED
394   GPG_ERR_NO_CRL_KNOWN
395   GPG_ERR_CRL_TOO_OLD
396
397   Values for USE_OCSP:
398      0 = Do CRL check.
399      1 = Do an OCSP check.
400      2 = Do an OCSP check using only the default responder.
401  */
402 int
403 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
404                        ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
405 {
406   static int did_options;
407   int rc;
408   char *certid;
409   char line[ASSUAN_LINELENGTH];
410   struct inq_certificate_parm_s parm;
411   struct isvalid_status_parm_s stparm;
412
413
414   rc = start_dirmngr ();
415   if (rc)
416     return rc;
417
418   if (use_ocsp)
419     {
420       certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
421     }
422   else
423     {
424       certid = gpgsm_get_certid (cert);
425       if (!certid)
426         {
427           log_error ("error getting the certificate ID\n");
428           return gpg_error (GPG_ERR_GENERAL);
429         }
430     }
431
432   if (opt.verbose > 1)
433     {
434       char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
435       log_info ("asking dirmngr about %s%s\n", fpr,
436                 use_ocsp? " (using OCSP)":"");
437       xfree (fpr);
438     }
439
440   parm.ctx = dirmngr_ctx;
441   parm.cert = cert;
442   parm.issuer_cert = issuer_cert;
443
444   stparm.ctrl = ctrl;
445   stparm.seen = 0;
446   memset (stparm.fpr, 0, 20);
447
448   /* FIXME: If --disable-crl-checks has been set, we should pass an
449      option to dirmngr, so that no fallback CRL check is done after an
450      ocsp check.  It is not a problem right now as dirmngr does not
451      fallback to CRL checking.  */
452
453   /* It is sufficient to send the options only once because we have
454      one connection per process only. */
455   if (!did_options)
456     {
457       if (opt.force_crl_refresh)
458         assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
459                          NULL, NULL, NULL, NULL, NULL, NULL);
460       did_options = 1;
461     }
462   snprintf (line, DIM(line)-1, "ISVALID%s %s", 
463             use_ocsp == 2? " --only-ocsp --force-default-responder":"",
464             certid);
465   line[DIM(line)-1] = 0;
466   xfree (certid);
467
468   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
469                         inq_certificate, &parm,
470                         isvalid_status_cb, &stparm);
471   if (opt.verbose > 1)
472     log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
473   rc = rc;
474
475   if (!rc && stparm.seen)
476     {
477       /* Need to also check the certificate validity. */
478       if (stparm.seen != 1)
479         {
480           log_error ("communication problem with dirmngr detected\n");
481           rc = gpg_error (GPG_ERR_INV_CRL);
482         }
483       else
484         {
485           KEYDB_HANDLE kh;
486           ksba_cert_t rspcert = NULL;
487
488           /* Fixme: First try to get the certificate from the
489              dirmngr's cache - it should be there. */
490           kh = keydb_new (0);
491           if (!kh)
492             rc = gpg_error (GPG_ERR_ENOMEM);
493           if (!rc)
494             rc = keydb_search_fpr (kh, stparm.fpr);
495           if (!rc)
496             rc = keydb_get_cert (kh, &rspcert);
497           if (rc)
498             {
499               log_error ("unable to find the certificate used "
500                          "by the dirmngr: %s\n", gpg_strerror (rc));
501               rc = gpg_error (GPG_ERR_INV_CRL);
502             }
503           keydb_release (kh);
504
505           if (!rc)
506             {
507               rc = gpgsm_cert_use_ocsp_p (rspcert);
508               if (rc)
509                 rc = gpg_error (GPG_ERR_INV_CRL);
510               else
511                 {
512                   /* Note the no_dirmngr flag: This avoids checking
513                      this certificate over and over again. */
514                   rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL, 
515                                              VALIDATE_FLAG_NO_DIRMNGR, NULL);
516                   if (rc)
517                     {
518                       log_error ("invalid certificate used for CRL/OCSP: %s\n",
519                                  gpg_strerror (rc));
520                       rc = gpg_error (GPG_ERR_INV_CRL);
521                     }
522                 }
523             }
524           ksba_cert_release (rspcert);
525         }
526     }
527   return rc;
528 }
529
530
531 \f
532 /* Lookup helpers*/
533 static int
534 lookup_cb (void *opaque, const void *buffer, size_t length)
535 {
536   struct lookup_parm_s *parm = opaque;
537   size_t len;
538   char *buf;
539   ksba_cert_t cert;
540   int rc;
541
542   if (parm->error)
543     return 0;
544
545   if (buffer)
546     {
547       put_membuf (&parm->data, buffer, length);
548       return 0;
549     }
550   /* END encountered - process what we have */
551   buf = get_membuf (&parm->data, &len);
552   if (!buf)
553     {
554       parm->error = gpg_error (GPG_ERR_ENOMEM);
555       return 0;
556     }
557
558   rc = ksba_cert_new (&cert);
559   if (rc)
560     {
561       parm->error = rc;
562       return 0;
563     }
564   rc = ksba_cert_init_from_mem (cert, buf, len);
565   if (rc)
566     {
567       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
568     }
569   else
570     {
571       parm->cb (parm->cb_value, cert);
572     }
573
574   ksba_cert_release (cert);
575   init_membuf (&parm->data, 4096);
576   return 0;
577 }
578
579 /* Return a properly escaped pattern from NAMES.  The only error
580    return is NULL to indicate a malloc failure. */
581 static char *
582 pattern_from_strlist (strlist_t names)
583 {
584   strlist_t sl;
585   int n;
586   const char *s;
587   char *pattern, *p;
588
589   for (n=0, sl=names; sl; sl = sl->next)
590     {
591       for (s=sl->d; *s; s++, n++)
592         {
593           if (*s == '%' || *s == ' ' || *s == '+')
594             n += 2;
595         }
596       n++;
597     }
598
599   p = pattern = xtrymalloc (n+1);
600   if (!pattern)
601     return NULL;
602
603   for (n=0, sl=names; sl; sl = sl->next)
604     {
605       for (s=sl->d; *s; s++)
606         {
607           switch (*s)
608             {
609             case '%':
610               *p++ = '%';
611               *p++ = '2';
612               *p++ = '5';
613               break;
614             case ' ':
615               *p++ = '%';
616               *p++ = '2';
617               *p++ = '0';
618               break;
619             case '+':
620               *p++ = '%';
621               *p++ = '2';
622               *p++ = 'B';
623               break;
624             default:
625               *p++ = *s;
626               break;
627             }
628         }
629       *p++ = ' ';
630     }
631   if (p == pattern)
632     *pattern = 0; /* is empty */
633   else
634     p[-1] = '\0'; /* remove trailing blank */
635   
636   return pattern;
637 }
638
639 static int
640 lookup_status_cb (void *opaque, const char *line)
641 {
642   struct lookup_parm_s *parm = opaque;
643
644   if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
645     {
646       if (parm->ctrl)
647         {
648           for (line += 8; *line == ' '; line++)
649             ;
650           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
651             return gpg_error (GPG_ERR_ASS_CANCELED);
652         }
653     }
654   else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
655     {
656       if (parm->ctrl)
657         {
658           for (line +=9; *line == ' '; line++)
659             ;
660           gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
661         }
662     }
663   return 0;
664 }
665
666
667 /* Run the Directroy Managers lookup command using the pattern
668    compiled from the strings given in NAMES.  The caller must provide
669    the callback CB which will be passed cert by cert.  Note that CTRL
670    is optional. */
671 int 
672 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
673                       void (*cb)(void*, ksba_cert_t), void *cb_value)
674
675   int rc;
676   char *pattern;
677   char line[ASSUAN_LINELENGTH];
678   struct lookup_parm_s parm;
679   size_t len;
680
681   rc = start_dirmngr ();
682   if (rc)
683     return rc;
684
685   pattern = pattern_from_strlist (names);
686   if (!pattern)
687     return out_of_core ();
688   snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
689   line[DIM(line)-1] = 0;
690   xfree (pattern);
691
692   parm.ctrl = ctrl;
693   parm.ctx = dirmngr_ctx;
694   parm.cb = cb;
695   parm.cb_value = cb_value;
696   parm.error = 0;
697   init_membuf (&parm.data, 4096);
698
699   rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
700                         NULL, NULL, lookup_status_cb, &parm);
701   xfree (get_membuf (&parm.data, &len));
702   if (rc)
703     return rc;
704   return parm.error;
705 }
706
707
708 \f
709 /* Run Command helpers*/
710
711 /* Fairly simple callback to write all output of dirmngr to stdout. */
712 static int
713 run_command_cb (void *opaque, const void *buffer, size_t length)
714 {
715   if (buffer)
716     {
717       if ( fwrite (buffer, length, 1, stdout) != 1 )
718         log_error ("error writing to stdout: %s\n", strerror (errno));
719     }
720   return 0;
721 }
722
723 /* Handle inquiries from the dirmngr COMMAND. */
724 static int
725 run_command_inq_cb (void *opaque, const char *line)
726 {
727   struct run_command_parm_s *parm = opaque;
728   int rc = 0;
729
730   if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
731     { /* send the given certificate */
732       int err;
733       ksba_cert_t cert;
734       const unsigned char *der;
735       size_t derlen;
736
737       line += 8;
738       if (!*line)
739         return gpg_error (GPG_ERR_ASS_PARAMETER);
740
741       err = gpgsm_find_cert (line, NULL, &cert);
742       if (err)
743         {
744           log_error ("certificate not found: %s\n", gpg_strerror (err));
745           rc = gpg_error (GPG_ERR_NOT_FOUND);
746         }
747       else
748         {
749           der = ksba_cert_get_image (cert, &derlen);
750           if (!der)
751             rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
752           else
753             rc = assuan_send_data (parm->ctx, der, derlen);
754           ksba_cert_release (cert);
755         }
756     }
757   else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
758     { /* Simply show the message given in the argument. */
759       line += 9;
760       log_info ("dirmngr: %s\n", line);
761     }
762   else
763     {
764       log_error ("unsupported inquiry `%s'\n", line);
765       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
766     }
767
768   return rc; 
769 }
770
771 static int
772 run_command_status_cb (void *opaque, const char *line)
773 {
774   ctrl_t ctrl = opaque;
775
776   if (opt.verbose)
777     {
778       log_info ("dirmngr status: %s\n", line);
779     }
780   if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
781     {
782       if (ctrl)
783         {
784           for (line += 8; *line == ' '; line++)
785             ;
786           if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
787             return gpg_error (GPG_ERR_ASS_CANCELED);
788         }
789     }
790   return 0;
791 }
792
793
794
795 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
796    to stdout.  A couple of inquiries are defined (see above).  ARGC
797    arguments in ARGV are given to the Dirmngr.  Spaces, plus and
798    percent characters within the argument strings are percent escaped
799    so that blanks can act as delimiters. */
800 int
801 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
802                            int argc, char **argv)
803
804   int rc;
805   int i;
806   const char *s;
807   char *line, *p;
808   size_t len;
809   struct run_command_parm_s parm;
810
811   rc = start_dirmngr ();
812   if (rc)
813     return rc;
814
815   parm.ctx = dirmngr_ctx;
816
817   len = strlen (command) + 1;
818   for (i=0; i < argc; i++)
819     len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
820   line = xtrymalloc (len);
821   if (!line)
822     return out_of_core ();
823
824   p = stpcpy (line, command);
825   for (i=0; i < argc; i++)
826     {
827       *p++ = ' ';
828       for (s=argv[i]; *s; s++)
829         {
830           if (!isascii (*s))
831             *p++ = *s;
832           else if (*s == ' ')
833             *p++ = '+';
834           else if (!isprint (*s) || *s == '+')
835             {
836               sprintf (p, "%%%02X", *(const unsigned char *)s);
837               p += 3;
838             }
839           else
840             *p++ = *s;
841         }
842     }
843   *p = 0;
844
845   rc = assuan_transact (dirmngr_ctx, line,
846                         run_command_cb, NULL,
847                         run_command_inq_cb, &parm,
848                         run_command_status_cb, ctrl);
849   xfree (line);
850   log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
851   return rc;
852 }