b78dc07d9da371a507695333f75e83954f5c6e24
[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   ctrl->digest.raw_value = 0;
646
647   /* Parse the hash value. */
648   n = 0;
649   rc = parse_hexstring (ctx, line, &n);
650   if (rc)
651     return rc;
652   n /= 2;
653   if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
654     ;
655   else if (n != 16 && n != 20 && n != 24 
656            && n != 28 && n != 32 && n != 48 && n != 64)
657     return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
658
659   if (n > MAX_DIGEST_LEN)
660     return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
661
662   buf = ctrl->digest.value;
663   ctrl->digest.valuelen = n;
664   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
665     buf[n] = xtoi_2 (p);
666   for (; n < ctrl->digest.valuelen; n++)
667     buf[n] = 0;
668   return 0;
669 }
670
671
672 static const char hlp_pksign[] = 
673   "PKSIGN [options]\n"
674   "\n"
675   "Perform the actual sign operation.  Neither input nor output are\n"
676   "sensitive to eavesdropping.";
677 static gpg_error_t
678 cmd_pksign (assuan_context_t ctx, char *line)
679 {
680   int rc;
681   cache_mode_t cache_mode = CACHE_MODE_NORMAL;
682   ctrl_t ctrl = assuan_get_pointer (ctx);
683   membuf_t outbuf;
684   
685   (void)line;
686   
687   if (opt.ignore_cache_for_signing)
688     cache_mode = CACHE_MODE_IGNORE;
689   else if (!ctrl->server_local->use_cache_for_signing)
690     cache_mode = CACHE_MODE_IGNORE;
691
692   init_membuf (&outbuf, 512);
693
694   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
695                      &outbuf, cache_mode);
696   if (rc)
697     clear_outbuf (&outbuf);
698   else
699     rc = write_and_clear_outbuf (ctx, &outbuf);
700   if (rc)
701     log_error ("command pksign failed: %s\n", gpg_strerror (rc));
702   xfree (ctrl->server_local->keydesc);
703   ctrl->server_local->keydesc = NULL;
704   return rc;
705 }
706
707
708 static const char hlp_pkdecrypt[] = 
709   "PKDECRYPT <options>\n"
710   "\n"
711   "Perform the actual decrypt operation.  Input is not\n"
712   "sensitive to eavesdropping.";
713 static gpg_error_t
714 cmd_pkdecrypt (assuan_context_t ctx, char *line)
715 {
716   int rc;
717   ctrl_t ctrl = assuan_get_pointer (ctx);
718   unsigned char *value;
719   size_t valuelen;
720   membuf_t outbuf;
721
722   (void)line;
723
724   /* First inquire the data to decrypt */
725   rc = assuan_inquire (ctx, "CIPHERTEXT",
726                        &value, &valuelen, MAXLEN_CIPHERTEXT);
727   if (rc)
728     return rc;
729
730   init_membuf (&outbuf, 512);
731
732   rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
733                         value, valuelen, &outbuf);
734   xfree (value);
735   if (rc)
736     clear_outbuf (&outbuf);
737   else
738     rc = write_and_clear_outbuf (ctx, &outbuf);
739   if (rc)
740     log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
741   xfree (ctrl->server_local->keydesc);
742   ctrl->server_local->keydesc = NULL;
743   return rc;
744 }
745
746
747 static const char hlp_genkey[] = 
748   "GENKEY\n"
749   "\n"
750   "Generate a new key, store the secret part and return the public\n"
751   "part.  Here is an example transaction:\n"
752   "\n"
753   "  C: GENKEY\n"
754   "  S: INQUIRE KEYPARAM\n"
755   "  C: D (genkey (rsa (nbits  1024)))\n"
756   "  C: END\n"
757   "  S: D (public-key\n"
758   "  S: D   (rsa (n 326487324683264) (e 10001)))\n"
759   "  S: OK key created\n"
760   "\n";
761 static gpg_error_t
762 cmd_genkey (assuan_context_t ctx, char *line)
763 {
764   ctrl_t ctrl = assuan_get_pointer (ctx);
765   int rc;
766   unsigned char *value;
767   size_t valuelen;
768   membuf_t outbuf;
769
770   (void)line;
771
772   /* First inquire the parameters */
773   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
774   if (rc)
775     return rc;
776
777   init_membuf (&outbuf, 512);
778
779   rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
780   xfree (value);
781   if (rc)
782     clear_outbuf (&outbuf);
783   else
784     rc = write_and_clear_outbuf (ctx, &outbuf);
785   if (rc)
786     log_error ("command genkey failed: %s\n", gpg_strerror (rc));
787   return rc;
788 }
789
790
791
792 \f
793 static const char hlp_readkey[] = 
794   "READKEY <hexstring_with_keygrip>\n"
795   "\n"
796   "Return the public key for the given keygrip.";
797 static gpg_error_t
798 cmd_readkey (assuan_context_t ctx, char *line)
799 {
800   ctrl_t ctrl = assuan_get_pointer (ctx);
801   int rc;
802   unsigned char grip[20];
803   gcry_sexp_t s_pkey = NULL;
804
805   rc = parse_keygrip (ctx, line, grip);
806   if (rc)
807     return rc; /* Return immediately as this is already an Assuan error code.*/
808
809   rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
810   if (!rc)
811     {
812       size_t len;
813       unsigned char *buf;
814
815       len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
816       assert (len);
817       buf = xtrymalloc (len);
818       if (!buf)
819         rc = gpg_error_from_syserror ();
820       else
821         {
822           len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
823           assert (len);
824           rc = assuan_send_data (ctx, buf, len);
825           xfree (buf);
826         }
827       gcry_sexp_release (s_pkey);
828     }
829
830   if (rc)
831     log_error ("command readkey failed: %s\n", gpg_strerror (rc));
832   return rc;
833 }
834
835
836 \f
837 static const char hlp_keyinfo[] = 
838   "KEYINFO [--list] <keygrip>\n"
839   "\n"
840   "Return information about the key specified by the KEYGRIP.  If the\n"
841   "key is not available GPG_ERR_NOT_FOUND is returned.  If the option\n"
842   "--list is given the keygrip is ignored and information about all\n"
843   "available keys are returned.  The information is returned as a\n"
844   "status line with this format:\n"
845   "\n"
846   "  KEYINFO <keygrip> <type> <serialno> <idstr>\n"
847   "\n"
848   "KEYGRIP is the keygrip.\n"
849   "\n"
850   "TYPE is describes the type of the key:\n"
851   "    'D' - Regular key stored on disk,\n"
852   "    'T' - Key is stored on a smartcard (token),\n"
853   "    '-' - Unknown type.\n"
854   "\n"
855   "SERIALNO is an ASCII string with the serial number of the\n"
856   "         smartcard.  If the serial number is not known a single\n"
857   "         dash '-' is used instead.\n"
858   "\n"
859   "IDSTR is the IDSTR used to distinguish keys on a smartcard.  If it\n"
860   "      is not known a dash is used instead.\n"
861   "\n"
862   "More information may be added in the future.";
863 static gpg_error_t
864 do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
865 {
866   gpg_error_t err;
867   char hexgrip[40+1];
868   int keytype;
869   unsigned char *shadow_info = NULL;
870   char *serialno = NULL;
871   char *idstr = NULL;
872   const char *keytypestr;
873
874   err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info);
875   if (err)
876     goto leave;
877
878   /* Reformat the grip so that we use uppercase as good style. */
879   bin2hex (grip, 20, hexgrip);
880       
881   if (keytype == PRIVATE_KEY_CLEAR 
882       || keytype == PRIVATE_KEY_PROTECTED)
883     keytypestr = "D";
884   else if (keytype == PRIVATE_KEY_SHADOWED)
885     keytypestr = "T";
886   else 
887     keytypestr = "-";
888       
889   if (shadow_info)
890     {
891       err = parse_shadow_info (shadow_info, &serialno, &idstr);
892       if (err)
893         goto leave;
894     }
895       
896   err = agent_write_status (ctrl, "KEYINFO",
897                             hexgrip,
898                             keytypestr,
899                             serialno? serialno : "-",
900                             idstr? idstr : "-",
901                             NULL);
902  leave:
903   xfree (shadow_info);
904   xfree (serialno);
905   xfree (idstr);
906   return err;
907 }
908
909
910 static gpg_error_t
911 cmd_keyinfo (assuan_context_t ctx, char *line)
912 {
913   ctrl_t ctrl = assuan_get_pointer (ctx);
914   int err;
915   unsigned char grip[20];
916   DIR *dir = NULL;
917   int list_mode;
918
919   list_mode = has_option (line, "--list");
920   line = skip_options (line);
921
922   if (list_mode)
923     {
924       char *dirname;
925       struct dirent *dir_entry;
926       char hexgrip[41];
927       
928       dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
929       if (!dirname)
930         {
931           err = gpg_error_from_syserror ();
932           goto leave;
933         }
934       dir = opendir (dirname);
935       if (!dir)
936         {
937           err = gpg_error_from_syserror ();
938           xfree (dirname);
939           goto leave;
940         }
941       xfree (dirname);
942
943       while ( (dir_entry = readdir (dir)) )
944         {
945           if (strlen (dir_entry->d_name) != 44
946               || strcmp (dir_entry->d_name + 40, ".key"))
947             continue;
948           strncpy (hexgrip, dir_entry->d_name, 40);
949           hexgrip[40] = 0;
950
951           if ( hex2bin (hexgrip, grip, 20) < 0 )
952             continue; /* Bad hex string.  */
953
954           err = do_one_keyinfo (ctrl, grip);
955           if (err)
956             goto leave;
957         }
958       err = 0;
959     }
960   else
961     {
962       err = parse_keygrip (ctx, line, grip);
963       if (err)
964         goto leave;
965       err = do_one_keyinfo (ctrl, grip);
966     }
967       
968  leave:
969   if (dir)
970     closedir (dir);
971   if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
972     log_error ("command keyinfo failed: %s\n", gpg_strerror (err));
973   return err;
974 }
975
976
977 \f
978 static int
979 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
980 {
981   size_t n;
982   int rc;
983
984   assuan_begin_confidential (ctx);
985   n = strlen (pw);
986   if (via_data)
987     rc = assuan_send_data (ctx, pw, n);
988   else
989     {
990       char *p = xtrymalloc_secure (n*2+1);
991       if (!p)
992         rc = gpg_error_from_syserror ();
993       else
994         {
995           bin2hex (pw, n, p);
996           rc = assuan_set_okay_line (ctx, p);
997           xfree (p);
998         }
999     }
1000   return rc;
1001 }
1002
1003
1004 static const char hlp_get_passphrase[] = 
1005   "GET_PASSPHRASE [--data] [--check] [--no-ask] [--repeat[=N]]\n"
1006   "               [--qualitybar] <cache_id>\n"
1007   "               [<error_message> <prompt> <description>]\n"
1008   "\n"
1009   "This function is usually used to ask for a passphrase to be used\n"
1010   "for conventional encryption, but may also be used by programs which\n"
1011   "need specal handling of passphrases.  This command uses a syntax\n"
1012   "which helps clients to use the agent with minimum effort.  The\n"
1013   "agent either returns with an error or with a OK followed by the hex\n"
1014   "encoded passphrase.  Note that the length of the strings is\n"
1015   "implicitly limited by the maximum length of a command.\n"
1016   "\n"
1017   "If the option \"--data\" is used the passphrase is returned by usual\n"
1018   "data lines and not on the okay line.\n"
1019   "\n"
1020   "If the option \"--check\" is used the passphrase constraints checks as\n"
1021   "implemented by gpg-agent are applied.  A check is not done if the\n"
1022   "passphrase has been found in the cache.\n"
1023   "\n"
1024   "If the option \"--no-ask\" is used and the passphrase is not in the\n"
1025   "cache the user will not be asked to enter a passphrase but the error\n"
1026   "code GPG_ERR_NO_DATA is returned.  \n"
1027   "\n"
1028   "If the option \"--qualitybar\" is used a visual indication of the\n"
1029   "entered passphrase quality is shown.  (Unless no minimum passphrase\n"
1030   "length has been configured.)";
1031 static gpg_error_t
1032 cmd_get_passphrase (assuan_context_t ctx, char *line)
1033 {
1034   ctrl_t ctrl = assuan_get_pointer (ctx);
1035   int rc;
1036   const char *pw;
1037   char *response;
1038   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
1039   const char *desc2 = _("Please re-enter this passphrase");
1040   char *p;
1041   void *cache_marker;
1042   int opt_data, opt_check, opt_no_ask, opt_qualbar;
1043   int opt_repeat = 0;
1044   char *repeat_errtext = NULL;
1045
1046   opt_data = has_option (line, "--data");
1047   opt_check = has_option (line, "--check");
1048   opt_no_ask = has_option (line, "--no-ask");
1049   if (has_option_name (line, "--repeat"))
1050     {
1051       p = option_value (line, "--repeat");
1052       if (p)
1053         opt_repeat = atoi (p);
1054       else
1055         opt_repeat = 1;
1056     }
1057   opt_qualbar = has_option (line, "--qualitybar");
1058   line = skip_options (line);
1059
1060   cacheid = line;
1061   p = strchr (cacheid, ' ');
1062   if (p)
1063     {
1064       *p++ = 0;
1065       while (*p == ' ')
1066         p++;
1067       errtext = p;
1068       p = strchr (errtext, ' ');
1069       if (p)
1070         {
1071           *p++ = 0;
1072           while (*p == ' ')
1073             p++;
1074           prompt = p;
1075           p = strchr (prompt, ' ');
1076           if (p)
1077             {
1078               *p++ = 0;
1079               while (*p == ' ')
1080                 p++;
1081               desc = p;
1082               p = strchr (desc, ' ');
1083               if (p)
1084                 *p = 0; /* Ignore trailing garbage. */
1085             }
1086         }
1087     }
1088   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1089     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1090   if (!desc)
1091     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1092
1093   if (!strcmp (cacheid, "X"))
1094     cacheid = NULL;
1095   if (!strcmp (errtext, "X"))
1096     errtext = NULL;
1097   if (!strcmp (prompt, "X"))
1098     prompt = NULL;
1099   if (!strcmp (desc, "X"))
1100     desc = NULL;
1101
1102   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
1103                : NULL;
1104   if (pw)
1105     {
1106       rc = send_back_passphrase (ctx, opt_data, pw);
1107       agent_unlock_cache_entry (&cache_marker);
1108     }
1109   else if (opt_no_ask)
1110     rc = gpg_error (GPG_ERR_NO_DATA);
1111   else
1112     {
1113       /* Note, that we only need to replace the + characters and
1114          should leave the other escaping in place because the escaped
1115          string is send verbatim to the pinentry which does the
1116          unescaping (but not the + replacing) */
1117       if (errtext)
1118         plus_to_blank (errtext);
1119       if (prompt)
1120         plus_to_blank (prompt);
1121       if (desc)
1122         plus_to_blank (desc);
1123
1124     next_try:
1125       rc = agent_get_passphrase (ctrl, &response, desc, prompt, 
1126                                  repeat_errtext? repeat_errtext:errtext, 
1127                                  opt_qualbar);
1128       xfree (repeat_errtext);
1129       repeat_errtext = NULL;
1130       if (!rc)
1131         {
1132           int i;
1133
1134           if (opt_check && check_passphrase_constraints (ctrl, response, 0))
1135             {
1136               xfree (response);
1137               goto next_try;
1138             }
1139           for (i = 0; i < opt_repeat; i++)
1140             {
1141               char *response2;
1142
1143               rc = agent_get_passphrase (ctrl, &response2, desc2, prompt,
1144                                          errtext, 0);
1145               if (rc)
1146                 break;
1147               if (strcmp (response2, response))
1148                 {
1149                   xfree (response2);
1150                   xfree (response);
1151                   repeat_errtext = try_percent_escape 
1152                     (_("does not match - try again"), NULL);
1153                   if (!repeat_errtext)
1154                     {
1155                       rc = gpg_error_from_syserror ();
1156                       break;
1157                     }
1158                   goto next_try;
1159                 }
1160               xfree (response2);
1161             }
1162           if (!rc)
1163             {
1164               if (cacheid)
1165                 agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
1166               rc = send_back_passphrase (ctx, opt_data, response);
1167             }
1168           xfree (response);
1169         }
1170     }
1171
1172   if (rc)
1173     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
1174   return rc;
1175 }
1176
1177
1178 static const char hlp_clear_passphrase[] = 
1179   "CLEAR_PASSPHRASE <cache_id>\n"
1180   "\n"
1181   "may be used to invalidate the cache entry for a passphrase.  The\n"
1182   "function returns with OK even when there is no cached passphrase.";
1183 static gpg_error_t
1184 cmd_clear_passphrase (assuan_context_t ctx, char *line)
1185 {
1186   char *cacheid = NULL;
1187   char *p;
1188
1189   /* parse the stuff */
1190   for (p=line; *p == ' '; p++)
1191     ;
1192   cacheid = p;
1193   p = strchr (cacheid, ' ');
1194   if (p)
1195     *p = 0; /* ignore garbage */
1196   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
1197     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
1198
1199   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
1200   return 0;
1201 }
1202
1203
1204 static const char hlp_get_confirmation[] = 
1205   "GET_CONFIRMATION <description>\n"
1206   "\n"
1207   "This command may be used to ask for a simple confirmation.\n"
1208   "DESCRIPTION is displayed along with a Okay and Cancel button.  This\n"
1209   "command uses a syntax which helps clients to use the agent with\n"
1210   "minimum effort.  The agent either returns with an error or with a\n"
1211   "OK.  Note, that the length of DESCRIPTION is implicitly limited by\n"
1212   "the maximum length of a command. DESCRIPTION should not contain\n"
1213   "any spaces, those must be encoded either percent escaped or simply\n"
1214   "as '+'.";
1215 static gpg_error_t
1216 cmd_get_confirmation (assuan_context_t ctx, char *line)
1217 {
1218   ctrl_t ctrl = assuan_get_pointer (ctx);
1219   int rc;
1220   char *desc = NULL;
1221   char *p;
1222
1223   /* parse the stuff */
1224   for (p=line; *p == ' '; p++)
1225     ;
1226   desc = p;
1227   p = strchr (desc, ' ');
1228   if (p)
1229     *p = 0; /* We ignore any garbage -may be later used for other args. */
1230
1231   if (!desc || !*desc)
1232     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
1233
1234   if (!strcmp (desc, "X"))
1235     desc = NULL;
1236
1237   /* Note, that we only need to replace the + characters and should
1238      leave the other escaping in place because the escaped string is
1239      send verbatim to the pinentry which does the unescaping (but not
1240      the + replacing) */
1241   if (desc)
1242     plus_to_blank (desc);
1243
1244   rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
1245   if (rc)
1246     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
1247   return rc;
1248 }
1249
1250
1251 \f
1252 static const char hlp_learn[] =
1253   "LEARN [--send]\n"
1254   "\n"
1255   "Learn something about the currently inserted smartcard.  With\n"
1256   "--send the new certificates are send back.";
1257 static gpg_error_t
1258 cmd_learn (assuan_context_t ctx, char *line)
1259 {
1260   ctrl_t ctrl = assuan_get_pointer (ctx);
1261   int rc;
1262
1263   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
1264   if (rc)
1265     log_error ("command learn failed: %s\n", gpg_strerror (rc));
1266   return rc;
1267 }
1268
1269
1270 \f
1271 static const char hlp_passwd[] = 
1272   "PASSWD <hexstring_with_keygrip>\n"
1273   "\n"
1274   "Change the passphrase/PIN for the key identified by keygrip in LINE.";
1275 static gpg_error_t
1276 cmd_passwd (assuan_context_t ctx, char *line)
1277 {
1278   ctrl_t ctrl = assuan_get_pointer (ctx);
1279   int rc;
1280   unsigned char grip[20];
1281   gcry_sexp_t s_skey = NULL;
1282   unsigned char *shadow_info = NULL;
1283
1284   rc = parse_keygrip (ctx, line, grip);
1285   if (rc)
1286     goto leave;
1287
1288   ctrl->in_passwd++;
1289   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
1290                             grip, &shadow_info, CACHE_MODE_IGNORE, NULL, 
1291                             &s_skey);
1292   if (rc)
1293     ;
1294   else if (!s_skey)
1295     {
1296       log_error ("changing a smartcard PIN is not yet supported\n");
1297       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1298     }
1299   else
1300     rc = agent_protect_and_store (ctrl, s_skey);
1301   ctrl->in_passwd--;
1302
1303   xfree (ctrl->server_local->keydesc);
1304   ctrl->server_local->keydesc = NULL;
1305
1306  leave:
1307   gcry_sexp_release (s_skey);
1308   xfree (shadow_info);
1309   if (rc)
1310     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
1311   return rc;
1312 }
1313
1314
1315 static const char hlp_preset_passphrase[] = 
1316   "PRESET_PASSPHRASE <string_or_keygrip> <timeout> <hexstring>\n"
1317   "\n"
1318   "Set the cached passphrase/PIN for the key identified by the keygrip\n"
1319   "to passwd for the given time, where -1 means infinite and 0 means\n"
1320   "the default (currently only a timeout of -1 is allowed, which means\n"
1321   "to never expire it).  If passwd is not provided, ask for it via the\n"
1322   "pinentry module.";
1323 static gpg_error_t
1324 cmd_preset_passphrase (assuan_context_t ctx, char *line)
1325 {
1326   int rc;
1327   char *grip_clear = NULL;
1328   char *passphrase = NULL;
1329   int ttl;
1330   size_t len;
1331
1332   if (!opt.allow_preset_passphrase)
1333     return set_error (GPG_ERR_NOT_SUPPORTED, "no --allow-preset-passphrase");
1334
1335   grip_clear = line;
1336   while (*line && (*line != ' ' && *line != '\t'))
1337     line++;
1338   if (!*line)
1339     return gpg_error (GPG_ERR_MISSING_VALUE);
1340   *line = '\0';
1341   line++;
1342   while (*line && (*line == ' ' || *line == '\t'))
1343     line++;
1344   
1345   /* Currently, only infinite timeouts are allowed.  */
1346   ttl = -1;
1347   if (line[0] != '-' || line[1] != '1')
1348     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1349   line++;
1350   line++;
1351   while (!(*line != ' ' && *line != '\t'))
1352     line++;
1353
1354   /* Syntax check the hexstring.  */
1355   len = 0;
1356   rc = parse_hexstring (ctx, line, &len);
1357   if (rc)
1358     return rc;
1359   line[len] = '\0';
1360
1361   /* If there is a passphrase, use it.  Currently, a passphrase is
1362      required.  */
1363   if (*line)
1364     {
1365       /* Do in-place conversion.  */
1366       passphrase = line;
1367       if (!hex2str (passphrase, passphrase, strlen (passphrase)+1, NULL))
1368         rc = set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
1369     }
1370   else
1371     rc = set_error (GPG_ERR_NOT_IMPLEMENTED, "passphrase is required");
1372
1373   if (!rc)
1374     rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
1375
1376   if (rc)
1377     log_error ("command preset_passphrase failed: %s\n", gpg_strerror (rc));
1378
1379   return rc;
1380 }
1381
1382
1383 \f
1384 static const char hlp_scd[] = 
1385   "SCD <commands to pass to the scdaemon>\n"
1386   " \n"
1387   "This is a general quote command to redirect everything to the\n"
1388   "SCdaemon.";
1389 static gpg_error_t
1390 cmd_scd (assuan_context_t ctx, char *line)
1391 {
1392   ctrl_t ctrl = assuan_get_pointer (ctx);
1393   int rc;
1394
1395   rc = divert_generic_cmd (ctrl, line, ctx);
1396
1397   return rc;
1398 }
1399
1400
1401 \f
1402 static const char hlp_getval[] = 
1403   "GETVAL <key>\n"
1404   "\n"
1405   "Return the value for KEY from the special environment as created by\n"
1406   "PUTVAL.";
1407 static gpg_error_t
1408 cmd_getval (assuan_context_t ctx, char *line)
1409 {
1410   int rc = 0;
1411   char *key = NULL;
1412   char *p;
1413   struct putval_item_s *vl;
1414
1415   for (p=line; *p == ' '; p++)
1416     ;
1417   key = p;
1418   p = strchr (key, ' ');
1419   if (p)
1420     {
1421       *p++ = 0; 
1422       for (; *p == ' '; p++)
1423         ;
1424       if (*p)
1425         return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
1426     }
1427   if (!key || !*key)
1428     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1429
1430
1431   for (vl=putval_list; vl; vl = vl->next)
1432     if ( !strcmp (vl->d, key) )
1433       break;
1434
1435   if (vl) /* Got an entry. */
1436     rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
1437   else
1438     return gpg_error (GPG_ERR_NO_DATA);
1439
1440   if (rc)
1441     log_error ("command getval failed: %s\n", gpg_strerror (rc));
1442   return rc;
1443 }
1444
1445
1446 static const char hlp_putval[] = 
1447   "PUTVAL <key> [<percent_escaped_value>]\n"
1448   "\n"
1449   "The gpg-agent maintains a kind of environment which may be used to\n"
1450   "store key/value pairs in it, so that they can be retrieved later.\n"
1451   "This may be used by helper daemons to daemonize themself on\n"
1452   "invocation and register them with gpg-agent.  Callers of the\n"
1453   "daemon's service may now first try connect to get the information\n"
1454   "for that service from gpg-agent through the GETVAL command and then\n"
1455   "try to connect to that daemon.  Only if that fails they may start\n"
1456   "an own instance of the service daemon. \n"
1457   "\n"
1458   "KEY is an an arbitrary symbol with the same syntax rules as keys\n"
1459   "for shell environment variables.  PERCENT_ESCAPED_VALUE is the\n"
1460   "corresponsing value; they should be similar to the values of\n"
1461   "envronment variables but gpg-agent does not enforce any\n"
1462   "restrictions.  If that value is not given any value under that KEY\n"
1463   "is removed from this special environment.";
1464 static gpg_error_t
1465 cmd_putval (assuan_context_t ctx, char *line)
1466 {
1467   int rc = 0;
1468   char *key = NULL;
1469   char *value = NULL;
1470   size_t valuelen = 0;
1471   char *p;
1472   struct putval_item_s *vl, *vlprev;
1473
1474   for (p=line; *p == ' '; p++)
1475     ;
1476   key = p;
1477   p = strchr (key, ' ');
1478   if (p)
1479     {
1480       *p++ = 0; 
1481       for (; *p == ' '; p++)
1482         ;
1483       if (*p)
1484         {
1485           value = p;
1486           p = strchr (value, ' ');
1487           if (p)
1488             *p = 0;
1489           valuelen = percent_plus_unescape_inplace (value, 0);
1490         }
1491     }
1492   if (!key || !*key)
1493     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1494
1495
1496   for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1497     if ( !strcmp (vl->d, key) )
1498       break;
1499
1500   if (vl) /* Delete old entry. */
1501     {
1502       if (vlprev)
1503         vlprev->next = vl->next;
1504       else
1505         putval_list = vl->next;
1506       xfree (vl);
1507     }
1508
1509   if (valuelen) /* Add entry. */  
1510     {
1511       vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1512       if (!vl)
1513         rc = gpg_error_from_syserror ();
1514       else
1515         {
1516           vl->len = valuelen;
1517           vl->off = strlen (key) + 1;
1518           strcpy (vl->d, key);
1519           memcpy (vl->d + vl->off, value, valuelen);
1520           vl->next = putval_list;
1521           putval_list = vl;
1522         }
1523     }
1524
1525   if (rc)
1526     log_error ("command putval failed: %s\n", gpg_strerror (rc));
1527   return rc;
1528 }
1529
1530
1531
1532 \f
1533 static const char hlp_updatestartuptty[] = 
1534   "UPDATESTARTUPTTY\n"
1535   "\n"
1536   "Set startup TTY and X11 DISPLAY variables to the values of this\n"
1537   "session.  This command is useful to pull future pinentries to\n"
1538   "another screen.  It is only required because there is no way in the\n"
1539   "ssh-agent protocol to convey this information.";
1540 static gpg_error_t
1541 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1542 {
1543   static const char *names[] = 
1544     { "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
1545   ctrl_t ctrl = assuan_get_pointer (ctx);
1546   gpg_error_t err = 0;
1547   session_env_t se;
1548   int idx;
1549   char *lc_ctype = NULL;
1550   char *lc_messages = NULL;
1551   
1552   (void)line;
1553
1554   se = session_env_new ();
1555   if (!se)
1556     err = gpg_error_from_syserror ();
1557
1558   for (idx=0; !err && names[idx]; idx++)
1559     {
1560       const char *value = session_env_getenv (ctrl->session_env, names[idx]);
1561       if (value)
1562         err = session_env_setenv (se, names[idx], value);
1563     }
1564
1565   if (!err && ctrl->lc_ctype) 
1566     if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
1567       err = gpg_error_from_syserror ();
1568
1569   if (!err && ctrl->lc_messages)
1570     if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
1571       err = gpg_error_from_syserror ();
1572    
1573   if (err)
1574     {
1575       session_env_release (se);
1576       xfree (lc_ctype);
1577       xfree (lc_messages);
1578     }
1579   else
1580     {
1581       session_env_release (opt.startup_env);
1582       opt.startup_env = se;
1583       xfree (opt.startup_lc_ctype);
1584       opt.startup_lc_ctype = lc_ctype;
1585       xfree (opt.startup_lc_messages);
1586       opt.startup_lc_messages = lc_messages;
1587     }
1588
1589   return err;
1590 }
1591
1592
1593 \f
1594 #ifdef HAVE_W32_SYSTEM
1595 static const char hlp_killagent[] =
1596   "KILLAGENT\n"
1597   "\n"
1598   "Under Windows we start the agent on the fly.  Thus it also make\n"
1599   "sense to allow a client to stop the agent.";
1600 static gpg_error_t
1601 cmd_killagent (assuan_context_t ctx, char *line)
1602 {
1603   ctrl_t ctrl = assuan_get_pointer (ctx);
1604
1605   (void)line;
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   "As signals are inconvenient under Windows, we provide this command\n"
1616   "to allow reloading of 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 #endif /*HAVE_W32_SYSTEM*/
1627
1628
1629 \f
1630 static const char hlp_getinfo[] = 
1631   "GETINFO <what>\n"
1632   "\n"
1633   "Multipurpose function to return a variety of information.\n"
1634   "Supported values for WHAT are:\n"
1635   "\n"
1636   "  version     - Return the version of the program.\n"
1637   "  pid         - Return the process id of the server.\n"
1638   "  socket_name - Return the name of the socket.\n"
1639   "  ssh_socket_name - Return the name of the ssh socket.\n"
1640   "  scd_running - Return OK if the SCdaemon is already running.\n"
1641   "  s2k_count   - Return the calibrated S2K count.\n"
1642   "  cmd_has_option\n"
1643   "              - Returns OK if the command CMD implements the option OPT.";
1644 static gpg_error_t
1645 cmd_getinfo (assuan_context_t ctx, char *line)
1646 {
1647   int rc = 0;
1648
1649   if (!strcmp (line, "version"))
1650     {
1651       const char *s = VERSION;
1652       rc = assuan_send_data (ctx, s, strlen (s));
1653     }
1654   else if (!strcmp (line, "pid"))
1655     {
1656       char numbuf[50];
1657
1658       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1659       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1660     }
1661   else if (!strcmp (line, "socket_name"))
1662     {
1663       const char *s = get_agent_socket_name ();
1664
1665       if (s)
1666         rc = assuan_send_data (ctx, s, strlen (s));
1667       else
1668         rc = gpg_error (GPG_ERR_NO_DATA);
1669     }
1670   else if (!strcmp (line, "ssh_socket_name"))
1671     {
1672       const char *s = get_agent_ssh_socket_name ();
1673
1674       if (s)
1675         rc = assuan_send_data (ctx, s, strlen (s));
1676       else
1677         rc = gpg_error (GPG_ERR_NO_DATA);
1678     }
1679   else if (!strcmp (line, "scd_running"))
1680     {
1681       rc = agent_scd_check_running ()? 0 : gpg_error (GPG_ERR_GENERAL);
1682     }
1683   else if (!strcmp (line, "s2k_count"))
1684     {
1685       char numbuf[50];
1686
1687       snprintf (numbuf, sizeof numbuf, "%lu", get_standard_s2k_count ());
1688       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
1689     }
1690   else if (!strncmp (line, "cmd_has_option", 14)
1691            && (line[14] == ' ' || line[14] == '\t' || !line[14]))
1692     {
1693       char *cmd, *cmdopt;
1694       line += 14;
1695       while (*line == ' ' || *line == '\t')
1696         line++;
1697       if (!*line)
1698         rc = gpg_error (GPG_ERR_MISSING_VALUE);
1699       else
1700         {
1701           cmd = line;
1702           while (*line && (*line != ' ' && *line != '\t'))
1703             line++;
1704           if (!*line)
1705             rc = gpg_error (GPG_ERR_MISSING_VALUE);
1706           else
1707             {
1708               *line++ = 0;
1709               while (*line == ' ' || *line == '\t')
1710                 line++;
1711               if (!*line)
1712                 rc = gpg_error (GPG_ERR_MISSING_VALUE);
1713               else
1714                 {
1715                   cmdopt = line;
1716                   if (!command_has_option (cmd, cmdopt))
1717                     rc = gpg_error (GPG_ERR_GENERAL);
1718                 }
1719             }
1720         }
1721     }
1722   else
1723     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1724   return rc;
1725 }
1726
1727
1728 \f
1729 static gpg_error_t
1730 option_handler (assuan_context_t ctx, const char *key, const char *value)
1731 {
1732   ctrl_t ctrl = assuan_get_pointer (ctx);
1733   gpg_error_t err = 0;
1734
1735   if (!strcmp (key, "putenv"))
1736     {
1737       /* Change the session's environment to be used for the
1738          Pinentry.  Valid values are:
1739           <NAME>            Delete envvar NAME
1740           <KEY>=            Set envvar NAME to the empty string
1741           <KEY>=<VALUE>     Set envvar NAME to VALUE
1742       */
1743       err = session_env_putenv (ctrl->session_env, value);
1744     }
1745   else if (!strcmp (key, "display"))
1746     {
1747       err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
1748     }
1749   else if (!strcmp (key, "ttyname"))
1750     {
1751       if (!opt.keep_tty)
1752         err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
1753     }
1754   else if (!strcmp (key, "ttytype"))
1755     {
1756       if (!opt.keep_tty)
1757         err = session_env_setenv (ctrl->session_env, "TERM", value);
1758     }
1759   else if (!strcmp (key, "lc-ctype"))
1760     {
1761       if (ctrl->lc_ctype)
1762         xfree (ctrl->lc_ctype);
1763       ctrl->lc_ctype = xtrystrdup (value);
1764       if (!ctrl->lc_ctype)
1765         return out_of_core ();
1766     }
1767   else if (!strcmp (key, "lc-messages"))
1768     {
1769       if (ctrl->lc_messages)
1770         xfree (ctrl->lc_messages);
1771       ctrl->lc_messages = xtrystrdup (value);
1772       if (!ctrl->lc_messages)
1773         return out_of_core ();
1774     }
1775   else if (!strcmp (key, "xauthority"))
1776     {
1777       err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
1778     }
1779   else if (!strcmp (key, "pinentry-user-data"))
1780     {
1781       err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
1782     }
1783   else if (!strcmp (key, "use-cache-for-signing"))
1784     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1785   else if (!strcmp (key, "allow-pinentry-notify"))
1786     ctrl->server_local->allow_pinentry_notify = 1;
1787   else
1788     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
1789
1790   return err;
1791 }
1792
1793
1794
1795 \f
1796 /* Called by libassuan after all commands. ERR is the error from the
1797    last assuan operation and not the one returned from the command. */
1798 static void
1799 post_cmd_notify (assuan_context_t ctx, gpg_error_t err)
1800 {
1801   ctrl_t ctrl = assuan_get_pointer (ctx);
1802   
1803   (void)err;
1804
1805   /* Switch off any I/O monitor controlled logging pausing. */
1806   ctrl->server_local->pause_io_logging = 0;
1807 }
1808
1809
1810 /* This function is called by libassuan for all I/O.  We use it here
1811    to disable logging for the GETEVENTCOUNTER commands.  This is so
1812    that the debug output won't get cluttered by this primitive
1813    command.  */
1814 static unsigned int
1815 io_monitor (assuan_context_t ctx, void *hook, int direction,
1816             const char *line, size_t linelen)
1817 {
1818   ctrl_t ctrl = assuan_get_pointer (ctx);
1819   
1820   (void) hook;
1821
1822   /* Note that we only check for the uppercase name.  This allows to
1823      see the logging for debugging if using a non-upercase command
1824      name. */
1825   if (ctx && direction == ASSUAN_IO_FROM_PEER
1826       && linelen >= 15
1827       && !strncmp (line, "GETEVENTCOUNTER", 15)
1828       && (linelen == 15 || spacep (line+15)))
1829     {
1830       ctrl->server_local->pause_io_logging = 1;
1831     }
1832
1833   return ctrl->server_local->pause_io_logging? ASSUAN_IO_MONITOR_NOLOG : 0;
1834 }
1835
1836
1837 /* Return true if the command CMD implements the option OPT.  */
1838 static int
1839 command_has_option (const char *cmd, const char *cmdopt)
1840 {
1841   if (!strcmp (cmd, "GET_PASSPHRASE"))
1842     {
1843       if (!strcmp (cmdopt, "repeat"))
1844           return 1;
1845     }
1846       
1847   return 0;
1848 }
1849
1850
1851 /* Tell the assuan library about our commands */
1852 static int
1853 register_commands (assuan_context_t ctx)
1854 {
1855   static struct {
1856     const char *name;
1857     assuan_handler_t handler;
1858     const char * const help;
1859   } table[] = {
1860     { "GETEVENTCOUNTER",cmd_geteventcounter, hlp_geteventcounter },
1861     { "ISTRUSTED",      cmd_istrusted, hlp_istrusted },
1862     { "HAVEKEY",        cmd_havekey,   hlp_havekey },
1863     { "KEYINFO",        cmd_keyinfo,   hlp_keyinfo },
1864     { "SIGKEY",         cmd_sigkey,    hlp_sigkey },
1865     { "SETKEY",         cmd_sigkey,    hlp_sigkey },
1866     { "SETKEYDESC",     cmd_setkeydesc,hlp_setkeydesc },
1867     { "SETHASH",        cmd_sethash,   hlp_sethash },
1868     { "PKSIGN",         cmd_pksign,    hlp_pksign },
1869     { "PKDECRYPT",      cmd_pkdecrypt, hlp_pkdecrypt },
1870     { "GENKEY",         cmd_genkey,    hlp_genkey },
1871     { "READKEY",        cmd_readkey,   hlp_readkey },
1872     { "GET_PASSPHRASE", cmd_get_passphrase, hlp_get_passphrase },
1873     { "PRESET_PASSPHRASE", cmd_preset_passphrase, hlp_preset_passphrase },
1874     { "CLEAR_PASSPHRASE", cmd_clear_passphrase,   hlp_clear_passphrase },
1875     { "GET_CONFIRMATION", cmd_get_confirmation,   hlp_get_confirmation },
1876     { "LISTTRUSTED",    cmd_listtrusted, hlp_listtrusted },
1877     { "MARKTRUSTED",    cmd_marktrusted, hlp_martrusted },
1878     { "LEARN",          cmd_learn,     hlp_learn },
1879     { "PASSWD",         cmd_passwd,    hlp_passwd },
1880     { "INPUT",          NULL }, 
1881     { "OUTPUT",         NULL }, 
1882     { "SCD",            cmd_scd,       hlp_scd },
1883     { "GETVAL",         cmd_getval,    hlp_getval },
1884     { "PUTVAL",         cmd_putval,    hlp_putval },
1885     { "UPDATESTARTUPTTY",  cmd_updatestartuptty, hlp_updatestartuptty },
1886 #ifdef HAVE_W32_SYSTEM
1887     { "KILLAGENT",      cmd_killagent,  hlp_killagent },
1888     { "RELOADAGENT",    cmd_reloadagent,hlp_reloadagent },
1889 #endif
1890     { "GETINFO",        cmd_getinfo,   hlp_getinfo },
1891     { NULL }
1892   };
1893   int i, rc;
1894
1895   for (i=0; table[i].name; i++)
1896     {
1897       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1898                                     table[i].help);
1899       if (rc)
1900         return rc;
1901     } 
1902   assuan_register_post_cmd_notify (ctx, post_cmd_notify);
1903   assuan_register_reset_notify (ctx, reset_notify);
1904   assuan_register_option_handler (ctx, option_handler);
1905   return 0;
1906 }
1907
1908
1909 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a
1910    simple piper server, otherwise it is a regular server.  CTRL is the
1911    control structure for this connection; it has only the basic
1912    intialization. */
1913 void
1914 start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
1915 {
1916   int rc;
1917   assuan_context_t ctx = NULL;
1918
1919   rc = assuan_new (&ctx);
1920   if (rc)
1921     {
1922       log_error ("failed to allocate assuan context: %s\n", gpg_strerror (rc));
1923       agent_exit (2);
1924     }
1925
1926   if (listen_fd == GNUPG_INVALID_FD && fd == GNUPG_INVALID_FD)
1927     {
1928       assuan_fd_t filedes[2];
1929
1930       filedes[0] = assuan_fdopen (0);
1931       filedes[1] = assuan_fdopen (1);
1932       rc = assuan_init_pipe_server (ctx, filedes);
1933     }
1934   else if (listen_fd != GNUPG_INVALID_FD)
1935     {
1936       rc = assuan_init_socket_server (ctx, listen_fd, 0);
1937       /* FIXME: Need to call assuan_sock_set_nonce for Windows.  But
1938          this branch is currently not used.  */
1939     }
1940   else 
1941     {
1942       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
1943     }
1944   if (rc)
1945     {
1946       log_error ("failed to initialize the server: %s\n",
1947                  gpg_strerror(rc));
1948       agent_exit (2);
1949     }
1950   rc = register_commands (ctx);
1951   if (rc)
1952     {
1953       log_error ("failed to register commands with Assuan: %s\n",
1954                  gpg_strerror(rc));
1955       agent_exit (2);
1956     }
1957
1958   assuan_set_pointer (ctx, ctrl);
1959   ctrl->server_local = xcalloc (1, sizeof *ctrl->server_local);
1960   ctrl->server_local->assuan_ctx = ctx;
1961   ctrl->server_local->message_fd = -1;
1962   ctrl->server_local->use_cache_for_signing = 1;
1963   ctrl->digest.raw_value = 0;
1964
1965   assuan_set_io_monitor (ctx, io_monitor, NULL);
1966
1967   for (;;)
1968     {
1969       rc = assuan_accept (ctx);
1970       if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1)
1971         {
1972           break;
1973         }
1974       else if (rc)
1975         {
1976           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1977           break;
1978         }
1979       
1980       rc = assuan_process (ctx);
1981       if (rc)
1982         {
1983           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1984           continue;
1985         }
1986     }
1987
1988   /* Reset the SCD if needed. */
1989   agent_reset_scd (ctrl);
1990
1991   /* Reset the pinentry (in case of popup messages). */
1992   agent_reset_query (ctrl);
1993
1994   /* Cleanup.  */
1995   assuan_release (ctx);
1996 #ifdef HAVE_W32_SYSTEM
1997   if (ctrl->server_local->stopme)
1998     agent_exit (0);
1999 #endif
2000   xfree (ctrl->server_local);
2001   ctrl->server_local = NULL;
2002 }
2003