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