Avoid using the protect-tool to import pkcs#12.
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005,
3  *               2006, 2008, 2009  Free Software Foundation, Inc.
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 /* FIXME: we should not use the default assuan buffering but setup
22    some buffering in secure mempory to protect session keys etc. */
23
24 #include <config.h>
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include <assert.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <dirent.h>
36
37 #include "agent.h"
38 #include <assuan.h>
39 #include "i18n.h"
40
41 /* Maximum allowed size of the inquired ciphertext.  */
42 #define MAXLEN_CIPHERTEXT 4096
43 /* Maximum allowed size of the key parameters.  */
44 #define MAXLEN_KEYPARAM 1024
45 /* Maximum allowed size of key data as used in inquiries (bytes). */
46 #define MAXLEN_KEYDATA 4096
47 /* The size of the import/export KEK key (in bytes).  */
48 #define KEYWRAP_KEYSIZE (128/8)
49
50 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
51
52
53 #if MAX_DIGEST_LEN < 20
54 #error MAX_DIGEST_LEN shorter than keygrip
55 #endif
56
57 /* Data used to associate an Assuan context with local server data */
58 struct server_local_s
59 {
60   assuan_context_t assuan_ctx;
61   int message_fd;
62   int use_cache_for_signing;
63   char *keydesc;  /* Allocated description for the next key
64                      operation. */
65   int pause_io_logging; /* Used to suppress I/O logging during a command */
66   int stopme;    /* If set to true the agent will be terminated after
67                     the end of this session.  */
68   int allow_pinentry_notify; /* Set if pinentry notifications should
69                                 be done. */
70   void *import_key;  /* Malloced KEK for the import_key command.  */
71   void *export_key;  /* Malloced KEK for the export_key command.  */
72 };
73
74
75 /* An entry for the getval/putval commands. */
76 struct putval_item_s
77 {
78   struct putval_item_s *next;
79   size_t off;  /* Offset to the value into DATA.  */
80   size_t len;  /* Length of the value.  */
81   char d[1];   /* Key | Nul | value.  */ 
82 };
83
84
85 /* A list of key value pairs fpr the getval/putval commands.  */
86 static struct putval_item_s *putval_list;
87
88
89 \f
90 /* To help polling clients, we keep track of the number of certain
91    events.  This structure keeps those counters.  The counters are
92    integers and there should be no problem if they are overflowing as
93    callers need to check only whether a counter changed.  The actual
94    values are not meaningful. */
95 struct 
96 {
97   /* Incremented if any of the other counters below changed. */
98   unsigned int any;
99
100   /* Incremented if a key is added or removed from the internal privat
101      key database. */
102   unsigned int key; 
103
104   /* Incremented if a change of the card readers stati has been
105      detected. */
106   unsigned int card;
107
108 } eventcounter;
109
110
111 \f
112 /*  Local prototypes.  */
113 static int command_has_option (const char *cmd, const char *cmdopt);
114
115
116
117 \f
118 /* Release the memory buffer MB but first wipe out the used memory. */
119 static void
120 clear_outbuf (membuf_t *mb)
121 {
122   void *p;
123   size_t n;
124
125   p = get_membuf (mb, &n);
126   if (p)
127     {
128       memset (p, 0, n);
129       xfree (p);
130     }
131 }
132
133
134 /* Write the content of memory buffer MB as assuan data to CTX and
135    wipe the buffer out afterwards. */
136 static gpg_error_t
137 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
138 {
139   gpg_error_t ae;
140   void *p;
141   size_t n;
142
143   p = get_membuf (mb, &n);
144   if (!p)
145     return out_of_core ();
146   ae = assuan_send_data (ctx, p, n);
147   memset (p, 0, n);
148   xfree (p);
149   return ae;
150 }
151
152
153 static gpg_error_t
154 reset_notify (assuan_context_t ctx, char *line)
155 {
156   ctrl_t ctrl = assuan_get_pointer (ctx);
157
158   (void) line;
159
160   memset (ctrl->keygrip, 0, 20);
161   ctrl->have_keygrip = 0;
162   ctrl->digest.valuelen = 0;
163
164   xfree (ctrl->server_local->keydesc);
165   ctrl->server_local->keydesc = NULL;
166   return 0;
167 }
168
169
170 /* Check whether the option NAME appears in LINE */
171 static int
172 has_option (const char *line, const char *name)
173 {
174   const char *s;
175   int n = strlen (name);
176
177   s = strstr (line, name);
178   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
179 }
180
181 /* Same as has_option but does only test for the name of the option
182    and ignores an argument, i.e. with NAME being "--hash" it would
183    return true for "--hash" as well as for "--hash=foo". */
184 static int
185 has_option_name (const char *line, const char *name)
186 {
187   const char *s;
188   int n = strlen (name);
189
190   s = strstr (line, name);
191   return (s && (s == line || spacep (s-1))
192           && (!s[n] || spacep (s+n) || s[n] == '='));
193 }
194
195 /* Return a pointer to the argument of the option with NAME.  If such
196    an option is not given, it returns NULL. */
197 static char *
198 option_value (const char *line, const char *name)
199 {
200   char *s;
201   int n = strlen (name);
202
203   s = strstr (line, name);
204   if (s && (s == line || spacep (s-1))
205       && s[n] && (spacep (s+n) || s[n] == '='))
206     {
207       s += n + 1;
208       s += strspn (s, " ");
209       if (*s && !spacep(s))
210         return s;
211     }
212   return NULL;
213 }
214
215
216 /* Skip over options.  It is assumed that leading spaces have been
217    removed (this is the case for lines passed to a handler from
218    assuan).  Blanks after the options are also removed. */
219 static char *
220 skip_options (char *line)
221 {
222   while ( *line == '-' && line[1] == '-' )
223     {
224       while (*line && !spacep (line))
225         line++;
226       while (spacep (line))
227         line++;
228     }
229   return line;
230 }
231
232
233 /* Replace all '+' by a blank. */
234 static void
235 plus_to_blank (char *s)
236 {
237   for (; *s; s++)
238     {
239       if (*s == '+')
240         *s = ' ';
241     }
242 }
243
244
245 /* Parse a hex string.  Return an Assuan error code or 0 on success and the
246    length of the parsed string in LEN. */
247 static int
248 parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
249 {
250   const char *p;
251   size_t n;
252
253   /* parse the hash value */
254   for (p=string, n=0; hexdigitp (p); p++, n++)
255     ;
256   if (*p != ' ' && *p != '\t' && *p)
257     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
258   if ((n&1))
259     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
260   *len = n;
261   return 0;
262 }
263
264 /* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
265    provide space for 20 bytes. BUF is not changed if the function
266    returns an error. */
267 static int
268 parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
269 {
270   int rc;
271   size_t n = 0;
272
273   rc = parse_hexstring (ctx, string, &n);
274   if (rc)
275     return rc;
276   n /= 2;
277   if (n != 20)
278     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of keygrip");
279
280   if (hex2bin (string, buf, 20) < 0)
281     return set_error (GPG_ERR_BUG, "hex2bin");
282
283   return 0;
284 }
285
286
287 /* Write an assuan status line. */
288 gpg_error_t
289 agent_write_status (ctrl_t ctrl, const char *keyword, ...)
290 {
291   gpg_error_t err = 0;
292   va_list arg_ptr;
293   const char *text;
294   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
295   char buf[950], *p;
296   size_t n;
297
298   va_start (arg_ptr, keyword);
299
300   p = buf; 
301   n = 0;
302   while ( (text = va_arg (arg_ptr, const char *)) )
303     {
304       if (n)
305         {
306           *p++ = ' ';
307           n++;
308         }
309       for ( ; *text && n < DIM (buf)-3; n++, text++)
310         {
311           if (*text == '\n')
312             {
313               *p++ = '\\';
314               *p++ = 'n';
315             }
316           else if (*text == '\r')
317             {
318               *p++ = '\\';
319               *p++ = 'r';
320             }
321           else
322             *p++ = *text;
323         }
324     }
325   *p = 0;
326   err = assuan_write_status (ctx, keyword, buf);
327
328   va_end (arg_ptr);
329   return err;
330 }
331
332
333 /* Helper to notify the client about a launched Pinentry.  Because
334    that might disturb some older clients, this is only done if enabled
335    via an option.  Returns an gpg error code. */
336 gpg_error_t
337 agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid)
338 {
339   char line[100];
340
341   if (!ctrl || !ctrl->server_local 
342       || !ctrl->server_local->allow_pinentry_notify)
343     return 0;
344   snprintf (line, DIM(line)-1, "PINENTRY_LAUNCHED %lu", pid);
345   return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
346 }
347
348
349 /* Helper to print a message while leaving a command.  */
350 static gpg_error_t
351 leave_cmd (assuan_context_t ctx, gpg_error_t err)
352 {
353   if (err)
354     {
355       const char *name = assuan_get_command_name (ctx);
356       if (!name)
357         name = "?";
358       if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
359         log_error ("command '%s' failed: %s\n", name,
360                    gpg_strerror (err));
361       else
362         log_error ("command '%s' failed: %s <%s>\n", name,
363                    gpg_strerror (err), gpg_strsource (err));
364     }
365   return err;
366 }
367
368
369 \f
370 static const char hlp_geteventcounter[] = 
371   "GETEVENTCOUNTER\n"
372   "\n"
373   "Return a a status line named EVENTCOUNTER with the current values\n"
374   "of all event counters.  The values are decimal numbers in the range\n"
375   "0 to UINT_MAX and wrapping around to 0.  The actual values should\n"
376   "not be relied upon, they shall only be used to detect a change.\n"
377   "\n"
378   "The currently defined counters are:\n"
379   "\n"
380   "ANY  - Incremented with any change of any of the other counters.\n"
381   "KEY  - Incremented for added or removed private keys.\n"
382   "CARD - Incremented for changes of the card readers stati.";
383 static gpg_error_t
384 cmd_geteventcounter (assuan_context_t ctx, char *line)
385 {
386   ctrl_t ctrl = assuan_get_pointer (ctx);
387   char any_counter[25];
388   char key_counter[25];
389   char card_counter[25];
390
391   (void)line;
392
393   snprintf (any_counter, sizeof any_counter, "%u", eventcounter.any);
394   snprintf (key_counter, sizeof key_counter, "%u", eventcounter.key);
395   snprintf (card_counter, sizeof card_counter, "%u", eventcounter.card);
396
397   return agent_write_status (ctrl, "EVENTCOUNTER",
398                              any_counter,
399                              key_counter,
400                              card_counter,
401                              NULL);
402 }
403
404
405 /* This function should be called once for all key removals or
406    additions.  This function is assured not to do any context
407    switches. */
408 void
409 bump_key_eventcounter (void)
410 {
411   eventcounter.key++;
412   eventcounter.any++;
413 }
414
415 /* This function should be called for all card reader status
416    changes.  This function is assured not to do any context
417    switches. */
418 void
419 bump_card_eventcounter (void)
420 {
421   eventcounter.card++;
422   eventcounter.any++;
423 }
424
425
426
427 \f
428 static const char hlp_istrusted[] = 
429   "ISTRUSTED <hexstring_with_fingerprint>\n"
430   "\n"
431   "Return OK when we have an entry with this fingerprint in our\n"
432   "trustlist";
433 static gpg_error_t
434 cmd_istrusted (assuan_context_t ctx, char *line)
435 {
436   ctrl_t ctrl = assuan_get_pointer (ctx);
437   int rc, n, i;
438   char *p;
439   char fpr[41];
440
441   /* Parse the fingerprint value. */
442   for (p=line,n=0; hexdigitp (p); p++, n++)
443     ;
444   if (*p || !(n == 40 || n == 32))
445     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
446   i = 0;
447   if (n==32)
448     {
449       strcpy (fpr, "00000000");
450       i += 8;
451     }
452   for (p=line; i < 40; p++, i++)
453     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
454   fpr[i] = 0;
455   rc = agent_istrusted (ctrl, fpr, NULL);
456   if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
457     return rc;
458   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
459     return gpg_error (GPG_ERR_NOT_TRUSTED);
460   else
461     return leave_cmd (ctx, rc);
462 }
463
464
465 static const char hlp_listtrusted[] = 
466   "LISTTRUSTED\n"
467   "\n"
468   "List all entries from the trustlist.";
469 static gpg_error_t
470 cmd_listtrusted (assuan_context_t ctx, char *line)
471 {
472   int rc;
473   
474   (void)line;
475
476   rc = agent_listtrusted (ctx);
477   return leave_cmd (ctx, rc);
478 }
479
480
481 static const char hlp_martrusted[] = 
482   "MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>\n"
483   "\n"
484   "Store a new key in into the trustlist.";
485 static gpg_error_t
486 cmd_marktrusted (assuan_context_t ctx, char *line)
487 {
488   ctrl_t ctrl = assuan_get_pointer (ctx);
489   int rc, n, i;
490   char *p;
491   char fpr[41];
492   int flag;
493
494   /* parse the fingerprint value */
495   for (p=line,n=0; hexdigitp (p); p++, n++)
496     ;
497   if (!spacep (p) || !(n == 40 || n == 32))
498     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
499   i = 0;
500   if (n==32)
501     {
502       strcpy (fpr, "00000000");
503       i += 8;
504     }
505   for (p=line; i < 40; p++, i++)
506     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
507   fpr[i] = 0;
508   
509   while (spacep (p))
510     p++;
511   flag = *p++;
512   if ( (flag != 'S' && flag != 'P') || !spacep (p) )
513     return set_error (GPG_ERR_ASS_PARAMETER, "invalid flag - must be P or S");
514   while (spacep (p))
515     p++;
516
517   rc = agent_marktrusted (ctrl, p, fpr, flag);
518   return leave_cmd (ctx, rc);
519 }
520
521
522
523 \f
524 static const char hlp_havekey[] =
525   "HAVEKEY <hexstring_with_keygrip>\n"
526   "\n"
527   "Return success when the secret key is available.";
528 static gpg_error_t
529 cmd_havekey (assuan_context_t ctx, char *line)
530 {
531   int rc;
532   unsigned char buf[20];
533
534   rc = parse_keygrip (ctx, line, buf);
535   if (rc)
536     return rc;
537
538   if (agent_key_available (buf))
539     return gpg_error (GPG_ERR_NO_SECKEY);
540
541   return 0;
542 }
543
544
545 static const char hlp_sigkey[] =
546   "SIGKEY <hexstring_with_keygrip>\n"
547   "SETKEY <hexstring_with_keygrip>\n"
548   "\n"
549   "Set the  key used for a sign or decrypt operation.";
550 static gpg_error_t
551 cmd_sigkey (assuan_context_t ctx, char *line)
552 {
553   int rc;
554   ctrl_t ctrl = assuan_get_pointer (ctx);
555
556   rc = parse_keygrip (ctx, line, ctrl->keygrip);
557   if (rc)
558     return rc;
559   ctrl->have_keygrip = 1;
560   return 0;
561 }
562
563
564 static const char hlp_setkeydesc[] = 
565   "SETKEYDESC plus_percent_escaped_string\n"
566   "\n"
567   "Set a description to be used for the next PKSIGN or PKDECRYPT\n"
568   "operation if this operation requires the entry of a passphrase.  If\n"
569   "this command is not used a default text will be used.  Note, that\n"
570   "this description implictly selects the label used for the entry\n"
571   "box; if the string contains the string PIN (which in general will\n"
572   "not be translated), \"PIN\" is used, otherwise the translation of\n"
573   "\"passphrase\" is used.  The description string should not contain\n"
574   "blanks unless they are percent or '+' escaped.\n"
575   "\n"
576   "The description is only valid for the next PKSIGN or PKDECRYPT\n"
577   "operation.";
578 static gpg_error_t
579 cmd_setkeydesc (assuan_context_t ctx, char *line)
580 {
581   ctrl_t ctrl = assuan_get_pointer (ctx);
582   char *desc, *p;
583
584   for (p=line; *p == ' '; p++)
585     ;
586   desc = p;
587   p = strchr (desc, ' ');
588   if (p)
589     *p = 0; /* We ignore any garbage; we might late use it for other args. */
590
591   if (!desc || !*desc)
592     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
593
594   /* Note, that we only need to replace the + characters and should
595      leave the other escaping in place because the escaped string is
596      send verbatim to the pinentry which does the unescaping (but not
597      the + replacing) */
598   plus_to_blank (desc);
599
600   xfree (ctrl->server_local->keydesc);
601   ctrl->server_local->keydesc = xtrystrdup (desc);
602   if (!ctrl->server_local->keydesc)
603     return out_of_core ();
604   return 0;
605 }
606
607
608 static const char hlp_sethash[] =
609   "SETHASH (--hash=<name>)|(<algonumber>) <hexstring>\n"
610   "\n"
611   "The client can use this command to tell the server about the data\n"
612   "(which usually is a hash) to be signed.";
613 static gpg_error_t
614 cmd_sethash (assuan_context_t ctx, char *line)
615 {
616   int rc;
617   size_t n;
618   char *p;
619   ctrl_t ctrl = assuan_get_pointer (ctx);
620   unsigned char *buf;
621   char *endp;
622   int algo;
623
624   /* Parse the alternative hash options which may be used instead of
625      the algo number.  */
626   if (has_option_name (line, "--hash"))
627     {
628       if (has_option (line, "--hash=sha1"))
629         algo = GCRY_MD_SHA1;
630       else if (has_option (line, "--hash=sha224"))
631         algo = GCRY_MD_SHA224;
632       else if (has_option (line, "--hash=sha256"))
633         algo = GCRY_MD_SHA256;
634       else if (has_option (line, "--hash=sha384"))
635         algo = GCRY_MD_SHA384;
636       else if (has_option (line, "--hash=sha512"))
637         algo = GCRY_MD_SHA512;
638       else if (has_option (line, "--hash=rmd160"))
639         algo = GCRY_MD_RMD160;
640       else if (has_option (line, "--hash=md5"))
641         algo = GCRY_MD_MD5;
642       else if (has_option (line, "--hash=tls-md5sha1"))
643         algo = MD_USER_TLS_MD5SHA1;
644       else
645         return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
646     }
647   else
648     algo = 0;
649
650   line = skip_options (line);
651   
652   if (!algo)
653     {
654       /* No hash option has been given: require an algo number instead  */
655       algo = (int)strtoul (line, &endp, 10);
656       for (line = endp; *line == ' ' || *line == '\t'; line++)
657         ;
658       if (!algo || gcry_md_test_algo (algo))
659         return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
660     }
661   ctrl->digest.algo = algo;
662   ctrl->digest.raw_value = 0;
663
664   /* Parse the hash value. */
665   n = 0;
666   rc = parse_hexstring (ctx, line, &n);
667   if (rc)
668     return rc;
669   n /= 2;
670   if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
671     ;
672   else if (n != 16 && n != 20 && n != 24 
673            && n != 28 && n != 32 && n != 48 && n != 64)
674     return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
675
676   if (n > MAX_DIGEST_LEN)
677     return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
678
679   buf = ctrl->digest.value;
680   ctrl->digest.valuelen = n;
681   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
682     buf[n] = xtoi_2 (p);
683   for (; n < ctrl->digest.valuelen; n++)
684     buf[n] = 0;
685   return 0;
686 }
687
688
689 static const char hlp_pksign[] = 
690   "PKSIGN [options]\n"
691   "\n"
692   "Perform the actual sign operation.  Neither input nor output are\n"
693   "sensitive to eavesdropping.";
694 static gpg_error_t
695 cmd_pksign (assuan_context_t ctx, char *line)
696 {
697   int rc;
698   cache_mode_t cache_mode = CACHE_MODE_NORMAL;
699   ctrl_t ctrl = assuan_get_pointer (ctx);
700   membuf_t outbuf;
701   
702   (void)line;
703   
704   if (opt.ignore_cache_for_signing)
705     cache_mode = CACHE_MODE_IGNORE;
706   else if (!ctrl->server_local->use_cache_for_signing)
707     cache_mode = CACHE_MODE_IGNORE;
708
709   init_membuf (&outbuf, 512);
710
711   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
712                      &outbuf, cache_mode);
713   if (rc)
714     clear_outbuf (&outbuf);
715   else
716     rc = write_and_clear_outbuf (ctx, &outbuf);
717   xfree (ctrl->server_local->keydesc);
718   ctrl->server_local->keydesc = NULL;
719   return leave_cmd (ctx, rc);
720 }
721
722
723 static const char hlp_pkdecrypt[] = 
724   "PKDECRYPT <options>\n"
725   "\n"
726   "Perform the actual decrypt operation.  Input is not\n"
727   "sensitive to eavesdropping.";
728 static gpg_error_t
729 cmd_pkdecrypt (assuan_context_t ctx, char *line)
730 {
731   int rc;
732   ctrl_t ctrl = assuan_get_pointer (ctx);
733   unsigned char *value;
734   size_t valuelen;
735   membuf_t outbuf;
736
737   (void)line;
738
739   /* First inquire the data to decrypt */
740   rc = assuan_inquire (ctx, "CIPHERTEXT",
741                        &value, &valuelen, MAXLEN_CIPHERTEXT);
742   if (rc)
743     return rc;
744
745   init_membuf (&outbuf, 512);
746
747   rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
748                         value, valuelen, &outbuf);
749   xfree (value);
750   if (rc)
751     clear_outbuf (&outbuf);
752   else
753     rc = write_and_clear_outbuf (ctx, &outbuf);
754   xfree (ctrl->server_local->keydesc);
755   ctrl->server_local->keydesc = NULL;
756   return leave_cmd (ctx, rc);
757 }
758
759
760 static const char hlp_genkey[] = 
761   "GENKEY\n"
762   "\n"
763   "Generate a new key, store the secret part and return the public\n"
764   "part.  Here is an example transaction:\n"
765   "\n"
766   "  C: GENKEY\n"
767   "  S: INQUIRE KEYPARAM\n"
768   "  C: D (genkey (rsa (nbits  1024)))\n"
769   "  C: END\n"
770   "  S: D (public-key\n"
771   "  S: D   (rsa (n 326487324683264) (e 10001)))\n"
772   "  S: OK key created\n"
773   "\n";
774 static gpg_error_t
775 cmd_genkey (assuan_context_t ctx, char *line)
776 {
777   ctrl_t ctrl = assuan_get_pointer (ctx);
778   int rc;
779   unsigned char *value;
780   size_t valuelen;
781   membuf_t outbuf;
782
783   (void)line;
784
785   /* First inquire the parameters */
786   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
787   if (rc)
788     return rc;
789
790   init_membuf (&outbuf, 512);
791
792   rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
793   xfree (value);
794   if (rc)
795     clear_outbuf (&outbuf);
796   else
797     rc = write_and_clear_outbuf (ctx, &outbuf);
798   return leave_cmd (ctx, rc);
799 }
800
801
802
803 \f
804 static const char hlp_readkey[] = 
805   "READKEY <hexstring_with_keygrip>\n"
806   "\n"
807   "Return the public key for the given keygrip.";
808 static gpg_error_t
809 cmd_readkey (assuan_context_t ctx, char *line)
810 {
811   ctrl_t ctrl = assuan_get_pointer (ctx);
812   int rc;
813   unsigned char grip[20];
814   gcry_sexp_t s_pkey = NULL;
815
816   rc = parse_keygrip (ctx, line, grip);
817   if (rc)
818     return rc; /* Return immediately as this is already an Assuan error code.*/
819
820   rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
821   if (!rc)
822     {
823       size_t len;
824       unsigned char *buf;
825
826       len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
827       assert (len);
828       buf = xtrymalloc (len);
829       if (!buf)
830         rc = gpg_error_from_syserror ();
831       else
832         {
833           len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
834           assert (len);
835           rc = assuan_send_data (ctx, buf, len);
836           xfree (buf);
837         }
838       gcry_sexp_release (s_pkey);
839     }
840
841   return leave_cmd (ctx, rc);
842 }
843
844
845 \f
846 static const char hlp_keyinfo[] = 
847   "KEYINFO [--list] <keygrip>\n"
848   "\n"
849   "Return information about the key specified by the KEYGRIP.  If the\n"
850   "key is not available GPG_ERR_NOT_FOUND is returned.  If the option\n"
851   "--list is given the keygrip is ignored and information about all\n"
852   "available keys are returned.  The information is returned as a\n"
853   "status line with this format:\n"
854   "\n"
855   "  KEYINFO <keygrip> <type> <serialno> <idstr>\n"
856   "\n"
857   "KEYGRIP is the keygrip.\n"
858   "\n"
859   "TYPE is describes the type of the key:\n"
860   "    'D' - Regular key stored on disk,\n"
861   "    'T' - Key is stored on a smartcard (token),\n"
862   "    '-' - Unknown type.\n"
863   "\n"
864   "SERIALNO is an ASCII string with the serial number of the\n"
865   "         smartcard.  If the serial number is not known a single\n"
866   "         dash '-' is used instead.\n"
867   "\n"
868   "IDSTR is the IDSTR used to distinguish keys on a smartcard.  If it\n"
869   "      is not known a dash is used instead.\n"
870   "\n"
871   "More information may be added in the future.";
872 static gpg_error_t
873 do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
874 {
875   gpg_error_t err;
876   char hexgrip[40+1];
877   int keytype;
878   unsigned char *shadow_info = NULL;
879   char *serialno = NULL;
880   char *idstr = NULL;
881   const char *keytypestr;
882
883   err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info);
884   if (err)
885     goto leave;
886
887   /* Reformat the grip so that we use uppercase as good style. */
888   bin2hex (grip, 20, hexgrip);
889       
890   if (keytype == PRIVATE_KEY_CLEAR 
891       || keytype == PRIVATE_KEY_PROTECTED)
892     keytypestr = "D";
893   else if (keytype == PRIVATE_KEY_SHADOWED)
894     keytypestr = "T";
895   else 
896     keytypestr = "-";
897       
898   if (shadow_info)
899     {
900       err = parse_shadow_info (shadow_info, &serialno, &idstr);
901       if (err)
902         goto leave;
903     }
904       
905   err = agent_write_status (ctrl, "KEYINFO",
906                             hexgrip,
907                             keytypestr,
908                             serialno? serialno : "-",
909                             idstr? idstr : "-",
910                             NULL);
911  leave:
912   xfree (shadow_info);
913   xfree (serialno);
914   xfree (idstr);
915   return err;
916 }
917
918
919 static gpg_error_t
920 cmd_keyinfo (assuan_context_t ctx, char *line)
921 {
922   ctrl_t ctrl = assuan_get_pointer (ctx);
923   int err;
924   unsigned char grip[20];
925   DIR *dir = NULL;
926   int list_mode;
927
928   list_mode = has_option (line, "--list");
929   line = skip_options (line);
930
931   if (list_mode)
932     {
933       char *dirname;
934       struct dirent *dir_entry;
935       char hexgrip[41];
936       
937       dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
938       if (!dirname)
939         {
940           err = gpg_error_from_syserror ();
941           goto leave;
942         }
943       dir = opendir (dirname);
944       if (!dir)
945         {
946           err = gpg_error_from_syserror ();
947           xfree (dirname);
948           goto leave;
949         }
950       xfree (dirname);
951
952       while ( (dir_entry = readdir (dir)) )
953         {
954           if (strlen (dir_entry->d_name) != 44
955               || strcmp (dir_entry->d_name + 40, ".key"))
956             continue;
957           strncpy (hexgrip, dir_entry->d_name, 40);
958           hexgrip[40] = 0;
959
960           if ( hex2bin (hexgrip, grip, 20) < 0 )
961             continue; /* Bad hex string.  */
962
963           err = do_one_keyinfo (ctrl, grip);
964           if (err)
965             goto leave;
966         }
967       err = 0;
968     }
969   else
970     {
971       err = parse_keygrip (ctx, line, grip);
972       if (err)
973         goto leave;
974       err = do_one_keyinfo (ctrl, grip);
975     }
976       
977  leave:
978   if (dir)
979     closedir (dir);
980   if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
981     leave_cmd (ctx, err);
982   return err;
983 }
984
985
986 \f
987 static int
988 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
989 {
990   size_t n;
991   int rc;
992
993   assuan_begin_confidential (ctx);
994   n = strlen (pw);
995   if (via_data)
996     rc = assuan_send_data (ctx, pw, n);
997   else
998     {
999       char *p = xtrymalloc_secure (n*2+1);
1000       if (!p)
1001         rc = gpg_error_from_syserror ();
1002       else
1003         {
1004           bin2hex (pw, n, p);
1005           rc = assuan_set_okay_line (ctx, p);
1006           xfree (p);
1007         }
1008     }
1009   return rc;
1010 }
1011
1012
1013 static const char hlp_get_passphrase[] = 
1014   "GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
1015   "               [--qualitybar] <cache_id>\n"
1016   "               [<error_message> <prompt> <description>]\n"
1017   "\n"
1018   "This function is usually used to ask for a passphrase to be used\n"
1019   "for conventional encryption, but may also be used by programs which\n"
1020   "need specal handling of passphrases.  This command uses a syntax\n"
1021   "which helps clients to use the agent with minimum effort.  The\n"
1022   "agent either returns with an error or with a OK followed by the hex\n"
1023   "encoded passphrase.  Note that the length of the strings is\n"
1024   "implicitly limited by the maximum length of a command.\n"
1025   "\n"
1026   "If the option \"--data\" is used the passphrase is returned by usual\n"
1027   "data lines and not on the okay line.\n"
1028   "\n"
1029   "If the option \"--check\" is used the passphrase constraints checks as\n"
1030   "implemented by gpg-agent are applied.  A check is not done if the\n"
1031   "passphrase has been found in the cache.\n"
1032   "\n"
1033   "If the option \"--no-ask\" is used and the passphrase is not in the\n"
1034   "cache the user will not be asked to enter a passphrase but the error\n"
1035   "code GPG_ERR_NO_DATA is returned.  \n"
1036   "\n"
1037   "If the option \"--qualitybar\" is used a visual indication of the\n"
1038   "entered passphrase quality is shown.  (Unless no minimum passphrase\n"
1039   "length has been configured.)";
1040 static gpg_error_t
1041 cmd_get_passphrase (assuan_context_t ctx, char *line)
1042 {
1043   ctrl_t ctrl = assuan_get_pointer (ctx);
1044   int rc;
1045   const char *pw;
1046   char *response;
1047   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
1048   const char *desc2 = _("Please re-enter this passphrase");
1049   char *p;
1050   void *cache_marker;
1051   int opt_data, opt_check, opt_no_ask, opt_qualbar;
1052   int opt_repeat = 0;
1053   char *repeat_errtext = NULL;
1054
1055   opt_data = has_option (line, "--data");
1056   opt_check = has_option (line, "--check");
1057   opt_no_ask = has_option (line, "--no-ask");
1058   if (has_option_name (line, "--repeat"))
1059     {
1060       p = option_value (line, "--repeat");
1061       if (p)
1062         opt_repeat = atoi (p);
1063       else
1064         opt_repeat = 1;
1065     }
1066   opt_qualbar = has_option (line, "--qualitybar");
1067   line = skip_options (line);
1068
1069   cacheid = line;
1070   p = strchr (cacheid, ' ');
1071   if (p)
1072     {
1073       *p++ = 0;
1074       while (*p == ' ')
1075         p++;
1076       errtext = p;
1077       p = strchr (errtext, ' ');
1078       if (p)
1079         {
1080           *p++ = 0;
1081           while (*p == ' ')
1082             p++;
1083           prompt = p;
1084           p = strchr (prompt, ' ');
1085           if (p)
1086             {
1087               *p++ = 0;
1088               while (*p == ' ')
1089                 p++;
1090               desc = p;
1091               p = strchr (desc, ' ');
1092               if (p)
1093                 *p = 0; /* Ignore trailing garbage. */
1094             }
1095         }
1096     }
1097   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1098     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1099   if (!desc)
1100     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1101
1102   if (!strcmp (cacheid, "X"))
1103     cacheid = NULL;
1104   if (!strcmp (errtext, "X"))
1105     errtext = NULL;
1106   if (!strcmp (prompt, "X"))
1107     prompt = NULL;
1108   if (!strcmp (desc, "X"))
1109     desc = NULL;
1110
1111   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
1112                : NULL;
1113   if (pw)
1114     {
1115       rc = send_back_passphrase (ctx, opt_data, pw);
1116       agent_unlock_cache_entry (&cache_marker);
1117     }
1118   else if (opt_no_ask)
1119     rc = gpg_error (GPG_ERR_NO_DATA);
1120   else
1121     {
1122       /* Note, that we only need to replace the + characters and
1123          should leave the other escaping in place because the escaped
1124          string is send verbatim to the pinentry which does the
1125          unescaping (but not the + replacing) */
1126       if (errtext)
1127         plus_to_blank (errtext);
1128       if (prompt)
1129         plus_to_blank (prompt);
1130       if (desc)
1131         plus_to_blank (desc);
1132
1133     next_try:
1134       rc = agent_get_passphrase (ctrl, &response, desc, prompt, 
1135                                  repeat_errtext? repeat_errtext:errtext, 
1136                                  opt_qualbar);
1137       xfree (repeat_errtext);
1138       repeat_errtext = NULL;
1139       if (!rc)
1140         {
1141           int i;
1142
1143           if (opt_check && check_passphrase_constraints (ctrl, response, 0))
1144             {
1145               xfree (response);
1146               goto next_try;
1147             }
1148           for (i = 0; i < opt_repeat; i++)
1149             {
1150               char *response2;
1151
1152               rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
1153                                          errtext, 0);
1154               if (rc)
1155                 break;
1156               if (strcmp (response2, response))
1157                 {
1158                   xfree (response2);
1159                   xfree (response);
1160                   repeat_errtext = try_percent_escape 
1161                     (_("does not match - try again"), NULL);
1162                   if (!repeat_errtext)
1163                     {
1164                       rc = gpg_error_from_syserror ();
1165                       break;
1166                     }
1167                   goto next_try;
1168                 }
1169               xfree (response2);
1170             }
1171           if (!rc)
1172             {
1173               if (cacheid)
1174                 agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
1175               rc = send_back_passphrase (ctx, opt_data, response);
1176             }
1177           xfree (response);
1178         }
1179     }
1180
1181   return leave_cmd (ctx, rc);
1182 }
1183
1184
1185 static const char hlp_clear_passphrase[] = 
1186   "CLEAR_PASSPHRASE <cache_id>\n"
1187   "\n"
1188   "may be used to invalidate the cache entry for a passphrase.  The\n"
1189   "function returns with OK even when there is no cached passphrase.";
1190 static gpg_error_t
1191 cmd_clear_passphrase (assuan_context_t ctx, char *line)
1192 {
1193   char *cacheid = NULL;
1194   char *p;
1195
1196   /* parse the stuff */
1197   for (p=line; *p == ' '; p++)
1198     ;
1199   cacheid = p;
1200   p = strchr (cacheid, ' ');
1201   if (p)
1202     *p = 0; /* ignore garbage */
1203   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1204     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1205
1206   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
1207   return 0;
1208 }
1209
1210
1211 static const char hlp_get_confirmation[] = 
1212   "GET_CONFIRMATION <description>\n"
1213   "\n"
1214   "This command may be used to ask for a simple confirmation.\n"
1215   "DESCRIPTION is displayed along with a Okay and Cancel button.  This\n"
1216   "command uses a syntax which helps clients to use the agent with\n"
1217   "minimum effort.  The agent either returns with an error or with a\n"
1218   "OK.  Note, that the length of DESCRIPTION is implicitly limited by\n"
1219   "the maximum length of a command. DESCRIPTION should not contain\n"
1220   "any spaces, those must be encoded either percent escaped or simply\n"
1221   "as '+'.";
1222 static gpg_error_t
1223 cmd_get_confirmation (assuan_context_t ctx, char *line)
1224 {
1225   ctrl_t ctrl = assuan_get_pointer (ctx);
1226   int rc;
1227   char *desc = NULL;
1228   char *p;
1229
1230   /* parse the stuff */
1231   for (p=line; *p == ' '; p++)
1232     ;
1233   desc = p;
1234   p = strchr (desc, ' ');
1235   if (p)
1236     *p = 0; /* We ignore any garbage -may be later used for other args. */
1237
1238   if (!desc || !*desc)
1239     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1240
1241   if (!strcmp (desc, "X"))
1242     desc = NULL;
1243
1244   /* Note, that we only need to replace the + characters and should
1245      leave the other escaping in place because the escaped string is
1246      send verbatim to the pinentry which does the unescaping (but not
1247      the + replacing) */
1248   if (desc)
1249     plus_to_blank (desc);
1250
1251   rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
1252   return leave_cmd (ctx, rc);
1253 }
1254
1255
1256 \f
1257 static const char hlp_learn[] =
1258   "LEARN [--send]\n"
1259   "\n"
1260   "Learn something about the currently inserted smartcard.  With\n"
1261   "--send the new certificates are send back.";
1262 static gpg_error_t
1263 cmd_learn (assuan_context_t ctx, char *line)
1264 {
1265   ctrl_t ctrl = assuan_get_pointer (ctx);
1266   int rc;
1267
1268   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
1269   return leave_cmd (ctx, rc);
1270 }
1271
1272
1273 \f
1274 static const char hlp_passwd[] = 
1275   "PASSWD <hexstring_with_keygrip>\n"
1276   "\n"
1277   "Change the passphrase/PIN for the key identified by keygrip in LINE.";
1278 static gpg_error_t
1279 cmd_passwd (assuan_context_t ctx, char *line)
1280 {
1281   ctrl_t ctrl = assuan_get_pointer (ctx);
1282   int rc;
1283   unsigned char grip[20];
1284   gcry_sexp_t s_skey = NULL;
1285   unsigned char *shadow_info = NULL;
1286
1287   rc = parse_keygrip (ctx, line, grip);
1288   if (rc)
1289     goto leave;
1290
1291   ctrl->in_passwd++;
1292   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
1293                             grip, &shadow_info, CACHE_MODE_IGNORE, NULL, 
1294                             &s_skey);
1295   if (rc)
1296     ;
1297   else if (!s_skey)
1298     {
1299       log_error ("changing a smartcard PIN is not yet supported\n");
1300       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1301     }
1302   else
1303     rc = agent_protect_and_store (ctrl, s_skey);
1304   ctrl->in_passwd--;
1305
1306   xfree (ctrl->server_local->keydesc);
1307   ctrl->server_local->keydesc = NULL;
1308
1309  leave:
1310   gcry_sexp_release (s_skey);
1311   xfree (shadow_info);
1312   return leave_cmd (ctx, rc);
1313 }
1314
1315
1316 static const char hlp_preset_passphrase[] = 
1317   "PRESET_PASSPHRASE <string_or_keygrip> <timeout> <hexstring>\n"
1318   "\n"
1319   "Set the cached passphrase/PIN for the key identified by the keygrip\n"
1320   "to passwd for the given time, where -1 means infinite and 0 means\n"
1321   "the default (currently only a timeout of -1 is allowed, which means\n"
1322   "to never expire it).  If passwd is not provided, ask for it via the\n"
1323   "pinentry module.";
1324 static gpg_error_t
1325 cmd_preset_passphrase (assuan_context_t ctx, char *line)
1326 {
1327   int rc;
1328   char *grip_clear = NULL;
1329   char *passphrase = NULL;
1330   int ttl;
1331   size_t len;
1332
1333   if (!opt.allow_preset_passphrase)
1334     return set_error (GPG_ERR_NOT_SUPPORTED, "no --allow-preset-passphrase");
1335
1336   grip_clear = line;
1337   while (*line && (*line != ' ' && *line != '\t'))
1338     line++;
1339   if (!*line)
1340     return gpg_error (GPG_ERR_MISSING_VALUE);
1341   *line = '\0';
1342   line++;
1343   while (*line && (*line == ' ' || *line == '\t'))
1344     line++;
1345   
1346   /* Currently, only infinite timeouts are allowed.  */
1347   ttl = -1;
1348   if (line[0] != '-' || line[1] != '1')
1349     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1350   line++;
1351   line++;
1352   while (!(*line != ' ' && *line != '\t'))
1353     line++;
1354
1355   /* Syntax check the hexstring.  */
1356   len = 0;
1357   rc = parse_hexstring (ctx, line, &len);
1358   if (rc)
1359     return rc;
1360   line[len] = '\0';
1361
1362   /* If there is a passphrase, use it.  Currently, a passphrase is
1363      required.  */
1364   if (*line)
1365     {
1366       /* Do in-place conversion.  */
1367       passphrase = line;
1368       if (!hex2str (passphrase, passphrase, strlen (passphrase)+1, NULL))
1369         rc = set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
1370     }
1371   else
1372     rc = set_error (GPG_ERR_NOT_IMPLEMENTED, "passphrase is required");
1373
1374   if (!rc)
1375     rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
1376
1377   return leave_cmd (ctx, rc);
1378 }
1379
1380
1381 \f
1382 static const char hlp_scd[] = 
1383   "SCD <commands to pass to the scdaemon>\n"
1384   " \n"
1385   "This is a general quote command to redirect everything to the\n"
1386   "SCdaemon.";
1387 static gpg_error_t
1388 cmd_scd (assuan_context_t ctx, char *line)
1389 {
1390   ctrl_t ctrl = assuan_get_pointer (ctx);
1391   int rc;
1392
1393   rc = divert_generic_cmd (ctrl, line, ctx);
1394
1395   return rc;
1396 }
1397
1398
1399 \f
1400 static const char hlp_keywrap_key[] =
1401   "KEYWRAP_KEY [--clear] <mode>\n"
1402   "\n"
1403   "Return a key to wrap another key.  For now the key is returned\n"
1404   "verbatim and and thus makes not much sense because an eavesdropper on\n"
1405   "the gpg-agent connection will see the key as well as the wrapped key.\n"
1406   "However, this function may either be equipped with a public key\n"
1407   "mechanism or not used at all if the key is a pre-shared key.  In any\n"
1408   "case wrapping the import and export of keys is a requirement for\n"
1409   "certain cryptographic validations and thus useful.  The key persists\n"
1410   "a RESET command but may be cleared using the option --clear.\n"
1411   "\n"
1412   "Supported modes are:\n"
1413   "  --import  - Return a key to import a key into gpg-agent\n"
1414   "  --export  - Return a key to export a key from gpg-agent";
1415 static gpg_error_t
1416 cmd_keywrap_key (assuan_context_t ctx, char *line)
1417 {
1418   ctrl_t ctrl = assuan_get_pointer (ctx);
1419   gpg_error_t err = 0;
1420   int clearopt = has_option (line, "--clear");
1421
1422
1423   assuan_begin_confidential (ctx);
1424   if (has_option (line, "--import"))
1425     {
1426       xfree (ctrl->server_local->import_key);
1427       if (clearopt)
1428         ctrl->server_local->import_key = NULL;
1429       else if (!(ctrl->server_local->import_key = 
1430                  gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
1431         err = gpg_error_from_syserror ();
1432       else
1433         err = assuan_send_data (ctx, ctrl->server_local->import_key,
1434                                 KEYWRAP_KEYSIZE);
1435     }
1436   else if (has_option (line, "--export"))
1437     {
1438       xfree (ctrl->server_local->export_key);
1439       if (clearopt)
1440         ctrl->server_local->export_key = NULL;
1441       else if (!(ctrl->server_local->export_key = 
1442             gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
1443         err = gpg_error_from_syserror ();
1444       else
1445         err = assuan_send_data (ctx, ctrl->server_local->export_key,
1446                                 KEYWRAP_KEYSIZE);
1447     }
1448   else
1449     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for MODE");
1450   assuan_end_confidential (ctx);
1451   
1452   return leave_cmd (ctx, err);
1453 }
1454
1455
1456 \f
1457 static const char hlp_import_key[] =
1458   "IMPORT_KEY\n"
1459   "\n"
1460   "Import a secret key into the key store.  The key is expected to be\n"
1461   "encrypted using the current session's key wrapping key (cf. command\n"
1462   "KEYWRAP_KEY) using the AESWRAP-128 algorithm.  This function takes\n"
1463   "no arguments but uses the inquiry \"KEYDATA\" to ask for the actual\n"
1464   "key data.  The unwrapped key must be a canonical S-expression.";
1465 static gpg_error_t
1466 cmd_import_key (assuan_context_t ctx, char *line)
1467 {
1468   ctrl_t ctrl = assuan_get_pointer (ctx);
1469   gpg_error_t err;
1470   unsigned char *wrappedkey = NULL;
1471   size_t wrappedkeylen;
1472   gcry_cipher_hd_t cipherhd = NULL;
1473   unsigned char *key = NULL;
1474   size_t keylen, realkeylen;
1475   char *passphrase = NULL;
1476   unsigned char *finalkey = NULL;
1477   size_t finalkeylen;
1478   unsigned char grip[20];
1479   
1480   (void)line;
1481
1482   if (!ctrl->server_local->import_key)
1483     {
1484       err = gpg_error (GPG_ERR_BAD_KEY);
1485       goto leave;
1486     }
1487
1488   assuan_begin_confidential (ctx);
1489   err = assuan_inquire (ctx, "KEYDATA",
1490                         &wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA);
1491   assuan_end_confidential (ctx);
1492   if (err)
1493     goto leave;
1494   if (wrappedkeylen < 24)
1495     {
1496       err = gpg_error (GPG_ERR_INV_LENGTH);
1497       goto leave;
1498     }
1499   keylen = wrappedkeylen - 8;
1500   key = xtrymalloc_secure (keylen);
1501   if (!key)
1502     {
1503       err = gpg_error_from_syserror ();
1504       goto leave;
1505     }
1506
1507   err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
1508                           GCRY_CIPHER_MODE_AESWRAP, 0);
1509   if (err)
1510     goto leave;
1511   err = gcry_cipher_setkey (cipherhd,
1512                             ctrl->server_local->import_key, KEYWRAP_KEYSIZE);
1513   if (err)
1514     goto leave;
1515   err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
1516   if (err)
1517     goto leave;
1518   gcry_cipher_close (cipherhd);
1519   cipherhd = NULL;
1520   xfree (wrappedkey);
1521   wrappedkey = NULL;
1522
1523   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
1524   if (!realkeylen)
1525     goto leave; /* Invalid canonical encoded S-expression.  */
1526   
1527   err = keygrip_from_canon_sexp (key, realkeylen, grip);
1528   if (err)
1529     goto leave;
1530
1531   if (!agent_key_available (grip))
1532     {
1533       err = gpg_error (GPG_ERR_EEXIST);
1534       goto leave;
1535     }
1536
1537   err = agent_ask_new_passphrase 
1538     (ctrl, _("Please enter the passphrase to protect the "
1539              "imported object within the GnuPG system."),
1540      &passphrase);
1541   if (err)
1542     goto leave;
1543
1544   if (passphrase)
1545     {
1546       err = agent_protect (key, passphrase, &finalkey, &finalkeylen);
1547       if (!err)
1548         err = agent_write_private_key (grip, finalkey, finalkeylen, 0);
1549     }
1550   else
1551     err = agent_write_private_key (grip, key, realkeylen, 0);
1552
1553  leave:
1554   xfree (finalkey);
1555   xfree (passphrase);
1556   xfree (key);
1557   gcry_cipher_close (cipherhd);
1558   xfree (wrappedkey);
1559   return leave_cmd (ctx, err);
1560 }
1561
1562
1563 \f
1564 static const char hlp_export_key[] =
1565   "EXPORT_KEY\n"
1566   "\n";
1567 static gpg_error_t
1568 cmd_export_key (assuan_context_t ctx, char *line)
1569 {
1570   gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1571
1572
1573  /* leave: */
1574   return leave_cmd (ctx, err);
1575 }
1576
1577
1578
1579 \f
1580 static const char hlp_getval[] = 
1581   "GETVAL <key>\n"
1582   "\n"
1583   "Return the value for KEY from the special environment as created by\n"
1584   "PUTVAL.";
1585 static gpg_error_t
1586 cmd_getval (assuan_context_t ctx, char *line)
1587 {
1588   int rc = 0;
1589   char *key = NULL;
1590   char *p;
1591   struct putval_item_s *vl;
1592
1593   for (p=line; *p == ' '; p++)
1594     ;
1595   key = p;
1596   p = strchr (key, ' ');
1597   if (p)
1598     {
1599       *p++ = 0; 
1600       for (; *p == ' '; p++)
1601         ;
1602       if (*p)
1603         return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
1604     }
1605   if (!key || !*key)
1606     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1607
1608
1609   for (vl=putval_list; vl; vl = vl->next)
1610     if ( !strcmp (vl->d, key) )
1611       break;
1612
1613   if (vl) /* Got an entry. */
1614     rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
1615   else
1616     return gpg_error (GPG_ERR_NO_DATA);
1617
1618   return leave_cmd (ctx, rc);
1619 }
1620
1621
1622 static const char hlp_putval[] = 
1623   "PUTVAL <key> [<percent_escaped_value>]\n"
1624   "\n"
1625   "The gpg-agent maintains a kind of environment which may be used to\n"
1626   "store key/value pairs in it, so that they can be retrieved later.\n"
1627   "This may be used by helper daemons to daemonize themself on\n"
1628   "invocation and register them with gpg-agent.  Callers of the\n"
1629   "daemon's service may now first try connect to get the information\n"
1630   "for that service from gpg-agent through the GETVAL command and then\n"
1631   "try to connect to that daemon.  Only if that fails they may start\n"
1632   "an own instance of the service daemon. \n"
1633   "\n"
1634   "KEY is an an arbitrary symbol with the same syntax rules as keys\n"
1635   "for shell environment variables.  PERCENT_ESCAPED_VALUE is the\n"
1636   "corresponsing value; they should be similar to the values of\n"
1637   "envronment variables but gpg-agent does not enforce any\n"
1638   "restrictions.  If that value is not given any value under that KEY\n"
1639   "is removed from this special environment.";
1640 static gpg_error_t
1641 cmd_putval (assuan_context_t ctx, char *line)
1642 {
1643   int rc = 0;
1644   char *key = NULL;
1645   char *value = NULL;
1646   size_t valuelen = 0;
1647   char *p;
1648   struct putval_item_s *vl, *vlprev;
1649
1650   for (p=line; *p == ' '; p++)
1651     ;
1652   key = p;
1653   p = strchr (key, ' ');
1654   if (p)
1655     {
1656       *p++ = 0; 
1657       for (; *p == ' '; p++)
1658         ;
1659       if (*p)
1660         {
1661           value = p;
1662           p = strchr (value, ' ');
1663           if (p)
1664             *p = 0;
1665           valuelen = percent_plus_unescape_inplace (value, 0);
1666         }
1667     }
1668   if (!key || !*key)
1669     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1670
1671
1672   for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1673     if ( !strcmp (vl->d, key) )
1674       break;
1675
1676   if (vl) /* Delete old entry. */
1677     {
1678       if (vlprev)
1679         vlprev->next = vl->next;
1680       else
1681         putval_list = vl->next;
1682       xfree (vl);
1683     }
1684
1685   if (valuelen) /* Add entry. */  
1686     {
1687       vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1688       if (!vl)
1689         rc = gpg_error_from_syserror ();
1690       else
1691         {
1692           vl->len = valuelen;
1693           vl->off = strlen (key) + 1;
1694           strcpy (vl->d, key);
1695           memcpy (vl->d + vl->off, value, valuelen);
1696           vl->next = putval_list;
1697           putval_list = vl;
1698         }
1699     }
1700
1701   return leave_cmd (ctx, rc);
1702 }
1703
1704
1705
1706 \f
1707 static const char hlp_updatestartuptty[] = 
1708   "UPDATESTARTUPTTY\n"
1709   "\n"
1710   "Set startup TTY and X11 DISPLAY variables to the values of this\n"
1711   "session.  This command is useful to pull future pinentries to\n"
1712   "another screen.  It is only required because there is no way in the\n"
1713   "ssh-agent protocol to convey this information.";
1714 static gpg_error_t
1715 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1716 {
1717   static const char *names[] = 
1718     { "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
1719   ctrl_t ctrl = assuan_get_pointer (ctx);
1720   gpg_error_t err = 0;
1721   session_env_t se;
1722   int idx;
1723   char *lc_ctype = NULL;
1724   char *lc_messages = NULL;
1725   
1726   (void)line;
1727
1728   se = session_env_new ();
1729   if (!se)
1730     err = gpg_error_from_syserror ();
1731
1732   for (idx=0; !err && names[idx]; idx++)
1733     {
1734       const char *value = session_env_getenv (ctrl->session_env, names[idx]);
1735       if (value)
1736         err = session_env_setenv (se, names[idx], value);
1737     }
1738
1739   if (!err && ctrl->lc_ctype) 
1740     if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
1741       err = gpg_error_from_syserror ();
1742
1743   if (!err && ctrl->lc_messages)
1744     if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
1745       err = gpg_error_from_syserror ();
1746    
1747   if (err)
1748     {
1749       session_env_release (se);
1750       xfree (lc_ctype);
1751       xfree (lc_messages);
1752     }
1753   else
1754     {
1755       session_env_release (opt.startup_env);
1756       opt.startup_env = se;
1757       xfree (opt.startup_lc_ctype);
1758       opt.startup_lc_ctype = lc_ctype;
1759       xfree (opt.startup_lc_messages);
1760       opt.startup_lc_messages = lc_messages;
1761     }
1762
1763   return err;
1764 }
1765
1766
1767 \f
1768 static const char hlp_killagent[] =
1769   "KILLAGENT\n"
1770   "\n"
1771   "If the agent has been started using a standard socket\n"
1772   "we allow a client to stop the agent.";
1773 static gpg_error_t
1774 cmd_killagent (assuan_context_t ctx, char *line)
1775 {
1776   ctrl_t ctrl = assuan_get_pointer (ctx);
1777
1778   (void)line;
1779   
1780   if (!opt.use_standard_socket)
1781     return set_error (GPG_ERR_NOT_SUPPORTED, "no --use-standard-socket");
1782
1783   ctrl->server_local->stopme = 1;
1784   return gpg_error (GPG_ERR_EOF);
1785 }
1786
1787
1788 static const char hlp_reloadagent[] =
1789   "RELOADAGENT\n"
1790   "\n"
1791   "This command is an alternative to SIGHUP\n"
1792   "to reload the configuration.";
1793 static gpg_error_t
1794 cmd_reloadagent (assuan_context_t ctx, char *line)
1795 {
1796   (void)ctx;
1797   (void)line;
1798
1799   agent_sighup_action ();
1800   return 0;
1801 }
1802
1803
1804 \f
1805 static const char hlp_getinfo[] = 
1806   "GETINFO <what>\n"
1807   "\n"
1808   "Multipurpose function to return a variety of information.\n"
1809   "Supported values for WHAT are:\n"
1810   "\n"
1811   "  version     - Return the version of the program.\n"
1812   "  pid         - Return the process id of the server.\n"
1813   "  socket_name - Return the name of the socket.\n"
1814   "  ssh_socket_name - Return the name of the ssh socket.\n"
1815   "  scd_running - Return OK if the SCdaemon is already running.\n"
1816   "  s2k_count   - Return the calibrated S2K count.\n"
1817   "  std_session_env - List the standard session environment.\n"
1818   "  std_startup_env - List the standard startup environment.\n"
1819   "  cmd_has_option\n"
1820   "              - Returns OK if the command CMD implements the option OPT\n.";
1821 static gpg_error_t
1822 cmd_getinfo (assuan_context_t ctx, char *line)
1823 {
1824   ctrl_t ctrl = assuan_get_pointer (ctx);
1825   int rc = 0;
1826
1827   if (!strcmp (line, "version"))
1828     {
1829       const char *s = VERSION;
1830       rc = assuan_send_data (ctx, s, strlen (s));
1831     }
1832   else if (!strcmp (line, "pid"))
1833     {
1834       char numbuf[50];
1835
1836       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1837       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1838     }
1839   else if (!strcmp (line, "socket_name"))
1840     {
1841       const char *s = get_agent_socket_name ();
1842
1843       if (s)
1844         rc = assuan_send_data (ctx, s, strlen (s));
1845       else
1846         rc = gpg_error (GPG_ERR_NO_DATA);
1847     }
1848   else if (!strcmp (line, "ssh_socket_name"))
1849     {
1850       const char *s = get_agent_ssh_socket_name ();
1851
1852       if (s)
1853         rc = assuan_send_data (ctx, s, strlen (s));
1854       else
1855         rc = gpg_error (GPG_ERR_NO_DATA);
1856     }
1857   else if (!strcmp (line, "scd_running"))
1858     {
1859       rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL);
1860     }
1861   else if (!strcmp (line, "s2k_count"))
1862     {
1863       char numbuf[50];
1864
1865       snprintf (numbuf, sizeof numbuf, "%lu", get_standard_s2k_count ());
1866       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1867     }
1868   else if (!strcmp (line, "std_session_env")
1869            || !strcmp (line, "std_startup_env"))
1870     {
1871       int iterator;
1872       const char *name, *value;
1873       char *string;
1874       
1875       iterator = 0; 
1876       while ((name = session_env_list_stdenvnames (&iterator, NULL)))
1877         {
1878           value = session_env_getenv_or_default
1879             (line[5] == 't'? opt.startup_env:ctrl->session_env, name, NULL);
1880           if (value)
1881             {
1882               string = xtryasprintf ("%s=%s", name, value); 
1883               if (!string)
1884                 rc = gpg_error_from_syserror ();
1885               else
1886                 {
1887                   rc = assuan_send_data (ctx, string, strlen (string)+1);
1888                   if (!rc)
1889                     rc = assuan_send_data (ctx, NULL, 0);
1890                 }
1891               if (rc)
1892                 break;
1893             }
1894         }
1895     }
1896   else if (!strncmp (line, "cmd_has_option", 14)
1897            && (line[14] == ' ' || line[14] == '\t' || !line[14]))
1898     {
1899       char *cmd, *cmdopt;
1900       line += 14;
1901       while (*line == ' ' || *line == '\t')
1902         line++;
1903       if (!*line)
1904         rc = gpg_error (GPG_ERR_MISSING_VALUE);
1905       else
1906         {
1907           cmd = line;
1908           while (*line && (*line != ' ' && *line != '\t'))
1909             line++;
1910           if (!*line)
1911             rc = gpg_error (GPG_ERR_MISSING_VALUE);
1912           else
1913             {
1914               *line++ = 0;
1915               while (*line == ' ' || *line == '\t')
1916                 line++;
1917               if (!*line)
1918                 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1919               else
1920                 {
1921                   cmdopt = line;
1922                   if (!command_has_option (cmd, cmdopt))
1923                     rc = gpg_error (GPG_ERR_GENERAL);
1924                 }
1925             }
1926         }
1927     }
1928   else
1929     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1930   return rc;
1931 }
1932
1933
1934 \f
1935 static gpg_error_t
1936 option_handler (assuan_context_t ctx, const char *key, const char *value)
1937 {
1938   ctrl_t ctrl = assuan_get_pointer (ctx);
1939   gpg_error_t err = 0;
1940
1941   if (!strcmp (key, "putenv"))
1942     {
1943       /* Change the session's environment to be used for the
1944          Pinentry.  Valid values are:
1945           <NAME>            Delete envvar NAME
1946           <KEY>=            Set envvar NAME to the empty string
1947           <KEY>=<VALUE>     Set envvar NAME to VALUE
1948       */
1949       err = session_env_putenv (ctrl->session_env, value);
1950     }
1951   else if (!strcmp (key, "display"))
1952     {
1953       err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
1954     }
1955   else if (!strcmp (key, "ttyname"))
1956     {
1957       if (!opt.keep_tty)
1958         err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
1959     }
1960   else if (!strcmp (key, "ttytype"))
1961     {
1962       if (!opt.keep_tty)
1963         err = session_env_setenv (ctrl->session_env, "TERM", value);
1964     }
1965   else if (!strcmp (key, "lc-ctype"))
1966     {
1967       if (ctrl->lc_ctype)
1968         xfree (ctrl->lc_ctype);
1969       ctrl->lc_ctype = xtrystrdup (value);
1970       if (!ctrl->lc_ctype)
1971         return out_of_core ();
1972     }
1973   else if (!strcmp (key, "lc-messages"))
1974     {
1975       if (ctrl->lc_messages)
1976         xfree (ctrl->lc_messages);
1977       ctrl->lc_messages = xtrystrdup (value);
1978       if (!ctrl->lc_messages)
1979         return out_of_core ();
1980     }
1981   else if (!strcmp (key, "xauthority"))
1982     {
1983       err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
1984     }
1985   else if (!strcmp (key, "pinentry-user-data"))
1986     {
1987       err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
1988     }
1989   else if (!strcmp (key, "use-cache-for-signing"))
1990     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1991   else if (!strcmp (key, "allow-pinentry-notify"))
1992     ctrl->server_local->allow_pinentry_notify = 1;
1993   else
1994     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
1995
1996   return err;
1997 }
1998
1999
2000
2001 \f
2002 /* Called by libassuan after all commands. ERR is the error from the
2003    last assuan operation and not the one returned from the command. */
2004 static void
2005 post_cmd_notify (assuan_context_t ctx, gpg_error_t err)
2006 {
2007   ctrl_t ctrl = assuan_get_pointer (ctx);
2008   
2009   (void)err;
2010
2011   /* Switch off any I/O monitor controlled logging pausing. */
2012   ctrl->server_local->pause_io_logging = 0;
2013 }
2014
2015
2016 /* This function is called by libassuan for all I/O.  We use it here
2017    to disable logging for the GETEVENTCOUNTER commands.  This is so
2018    that the debug output won't get cluttered by this primitive
2019    command.  */
2020 static unsigned int
2021 io_monitor (assuan_context_t ctx, void *hook, int direction,
2022             const char *line, size_t linelen)
2023 {
2024   ctrl_t ctrl = assuan_get_pointer (ctx);
2025   
2026   (void) hook;
2027
2028   /* Note that we only check for the uppercase name.  This allows to
2029      see the logging for debugging if using a non-upercase command
2030      name. */
2031   if (ctx && direction == ASSUAN_IO_FROM_PEER
2032       && linelen >= 15
2033       && !strncmp (line, "GETEVENTCOUNTER", 15)
2034       && (linelen == 15 || spacep (line+15)))
2035     {
2036       ctrl->server_local->pause_io_logging = 1;
2037     }
2038
2039   return ctrl->server_local->pause_io_logging? ASSUAN_IO_MONITOR_NOLOG : 0;
2040 }
2041
2042
2043 /* Return true if the command CMD implements the option OPT.  */
2044 static int
2045 command_has_option (const char *cmd, const char *cmdopt)
2046 {
2047   if (!strcmp (cmd, "GET_PASSPHRASE"))
2048     {
2049       if (!strcmp (cmdopt, "repeat"))
2050           return 1;
2051     }
2052       
2053   return 0;
2054 }
2055
2056
2057 /* Tell the assuan library about our commands */
2058 static int
2059 register_commands (assuan_context_t ctx)
2060 {
2061   static struct {
2062     const char *name;
2063     assuan_handler_t handler;
2064     const char * const help;
2065   } table[] = {
2066     { "GETEVENTCOUNTER",cmd_geteventcounter, hlp_geteventcounter },
2067     { "ISTRUSTED",      cmd_istrusted, hlp_istrusted },
2068     { "HAVEKEY",        cmd_havekey,   hlp_havekey },
2069     { "KEYINFO",        cmd_keyinfo,   hlp_keyinfo },
2070     { "SIGKEY",         cmd_sigkey,    hlp_sigkey },
2071     { "SETKEY",         cmd_sigkey,    hlp_sigkey },
2072     { "SETKEYDESC",     cmd_setkeydesc,hlp_setkeydesc },
2073     { "SETHASH",        cmd_sethash,   hlp_sethash },
2074     { "PKSIGN",         cmd_pksign,    hlp_pksign },
2075     { "PKDECRYPT",      cmd_pkdecrypt, hlp_pkdecrypt },
2076     { "GENKEY",         cmd_genkey,    hlp_genkey },
2077     { "READKEY",        cmd_readkey,   hlp_readkey },
2078     { "GET_PASSPHRASE", cmd_get_passphrase, hlp_get_passphrase },
2079     { "PRESET_PASSPHRASE", cmd_preset_passphrase, hlp_preset_passphrase },
2080     { "CLEAR_PASSPHRASE", cmd_clear_passphrase,   hlp_clear_passphrase },
2081     { "GET_CONFIRMATION", cmd_get_confirmation,   hlp_get_confirmation },
2082     { "LISTTRUSTED",    cmd_listtrusted, hlp_listtrusted },
2083     { "MARKTRUSTED",    cmd_marktrusted, hlp_martrusted },
2084     { "LEARN",          cmd_learn,     hlp_learn },
2085     { "PASSWD",         cmd_passwd,    hlp_passwd },
2086     { "INPUT",          NULL }, 
2087     { "OUTPUT",         NULL }, 
2088     { "SCD",            cmd_scd,       hlp_scd },
2089     { "KEYWRAP_KEY",    cmd_keywrap_key, hlp_keywrap_key },
2090     { "IMPORT_KEY",     cmd_import_key, hlp_import_key },
2091     { "EXPORT_KEY",     cmd_export_key, hlp_export_key },
2092     { "GETVAL",         cmd_getval,    hlp_getval },
2093     { "PUTVAL",         cmd_putval,    hlp_putval },
2094     { "UPDATESTARTUPTTY",  cmd_updatestartuptty, hlp_updatestartuptty },
2095     { "KILLAGENT",      cmd_killagent,  hlp_killagent },
2096     { "RELOADAGENT",    cmd_reloadagent,hlp_reloadagent },
2097     { "GETINFO",        cmd_getinfo,   hlp_getinfo },
2098     { NULL }
2099   };
2100   int i, rc;
2101
2102   for (i=0; table[i].name; i++)
2103     {
2104       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2105                                     table[i].help);
2106       if (rc)
2107         return rc;
2108     } 
2109   assuan_register_post_cmd_notify (ctx, post_cmd_notify);
2110   assuan_register_reset_notify (ctx, reset_notify);
2111   assuan_register_option_handler (ctx, option_handler);
2112   return 0;
2113 }
2114
2115
2116 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a
2117    simple piper server, otherwise it is a regular server.  CTRL is the
2118    control structure for this connection; it has only the basic
2119    intialization. */
2120 void
2121 start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
2122 {
2123   int rc;
2124   assuan_context_t ctx = NULL;
2125
2126   rc = assuan_new (&ctx);
2127   if (rc)
2128     {
2129       log_error ("failed to allocate assuan context: %s\n", gpg_strerror (rc));
2130       agent_exit (2);
2131     }
2132
2133   if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD)
2134     {
2135       assuan_fd_t filedes[2];
2136
2137       filedes[0] = assuan_fdopen (0);
2138       filedes[1] = assuan_fdopen (1);
2139       rc = assuan_init_pipe_server (ctx, filedes);
2140     }
2141   else if (listen_fd != GNUPG_INVALID_FD)
2142     {
2143       rc = assuan_init_socket_server (ctx, listen_fd, 0);
2144       /* FIXME: Need to call assuan_sock_set_nonce for Windows.  But
2145          this branch is currently not used.  */
2146     }
2147   else 
2148     {
2149       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
2150     }
2151   if (rc)
2152     {
2153       log_error ("failed to initialize the server: %s\n",
2154                  gpg_strerror(rc));
2155       agent_exit (2);
2156     }
2157   rc = register_commands (ctx);
2158   if (rc)
2159     {
2160       log_error ("failed to register commands with Assuan: %s\n",
2161                  gpg_strerror(rc));
2162       agent_exit (2);
2163     }
2164
2165   assuan_set_pointer (ctx, ctrl);
2166   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
2167   ctrl->server_local->assuan_ctx = ctx;
2168   ctrl->server_local->message_fd = -1;
2169   ctrl->server_local->use_cache_for_signing = 1;
2170   ctrl->digest.raw_value = 0;
2171
2172   assuan_set_io_monitor (ctx, io_monitor, NULL);
2173
2174   for (;;)
2175     {
2176       rc = assuan_accept (ctx);
2177       if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1)
2178         {
2179           break;
2180         }
2181       else if (rc)
2182         {
2183           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
2184           break;
2185         }
2186       
2187       rc = assuan_process (ctx);
2188       if (rc)
2189         {
2190           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
2191           continue;
2192         }
2193     }
2194
2195   /* Reset the SCD if needed. */
2196   agent_reset_scd (ctrl);
2197
2198   /* Reset the pinentry (in case of popup messages). */
2199   agent_reset_query (ctrl);
2200
2201   /* Cleanup.  */
2202   assuan_release (ctx);
2203   xfree (ctrl->server_local->keydesc);
2204   xfree (ctrl->server_local->import_key);
2205   xfree (ctrl->server_local->export_key);
2206   if (ctrl->server_local->stopme)
2207     agent_exit (0);
2208   xfree (ctrl->server_local);
2209   ctrl->server_local = NULL;
2210 }
2211