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