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