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