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