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