Allow pkcs#10 creation directkly from a smart card
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  * Copyright (C) 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 /* FIXME: we should not use the default assuan buffering but setup
23    some buffering in secure mempory to protect session keys etc. */
24
25 #include <config.h>
26
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <unistd.h>
33 #include <assert.h>
34
35 #include <assuan.h>
36
37 #include "agent.h"
38
39 /* maximum allowed size of the inquired ciphertext */
40 #define MAXLEN_CIPHERTEXT 4096
41 /* maximum allowed size of the key parameters */
42 #define MAXLEN_KEYPARAM 1024
43
44 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
45
46
47 #if MAX_DIGEST_LEN < 20
48 #error MAX_DIGEST_LEN shorter than keygrip
49 #endif
50
51 /* Data used to associate an Assuan context with local server data */
52 struct server_local_s
53 {
54   assuan_context_t assuan_ctx;
55   int message_fd;
56   int use_cache_for_signing;
57   char *keydesc;  /* Allocated description for the next key
58                      operation. */
59 };
60
61
62 /* An entry for the getval/putval commands. */
63 struct putval_item_s
64 {
65   struct putval_item_s *next;
66   size_t off;  /* Offset to the value into DATA.  */
67   size_t len;  /* Length of the value.  */
68   char d[1];   /* Key | Nul | value.  */ 
69 };
70
71
72 /* A list of key value pairs fpr the getval/putval commands.  */
73 static struct putval_item_s *putval_list;
74
75
76
77
78 \f
79 /* Release the memory buffer MB but first wipe out the used memory. */
80 static void
81 clear_outbuf (membuf_t *mb)
82 {
83   void *p;
84   size_t n;
85
86   p = get_membuf (mb, &n);
87   if (p)
88     {
89       memset (p, 0, n);
90       xfree (p);
91     }
92 }
93
94
95 /* Write the content of memory buffer MB as assuan data to CTX and
96    wipe the buffer out afterwards. */
97 static gpg_error_t
98 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
99 {
100   assuan_error_t ae;
101   void *p;
102   size_t n;
103
104   p = get_membuf (mb, &n);
105   if (!p)
106     return out_of_core ();
107   ae = assuan_send_data (ctx, p, n);
108   memset (p, 0, n);
109   xfree (p);
110   return ae;
111 }
112
113
114 static void
115 reset_notify (assuan_context_t ctx)
116 {
117   ctrl_t ctrl = assuan_get_pointer (ctx);
118
119   memset (ctrl->keygrip, 0, 20);
120   ctrl->have_keygrip = 0;
121   ctrl->digest.valuelen = 0;
122
123   xfree (ctrl->server_local->keydesc);
124   ctrl->server_local->keydesc = NULL;
125 }
126
127
128 /* Check whether the option NAME appears in LINE */
129 static int
130 has_option (const char *line, const char *name)
131 {
132   const char *s;
133   int n = strlen (name);
134
135   s = strstr (line, name);
136   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
137 }
138
139 /* Same as has_option but does only test for the name of the option
140    and ignores an argument, i.e. with NAME being "--hash" it would
141    return true for "--hash" as well as for "--hash=foo". */
142 static int
143 has_option_name (const char *line, const char *name)
144 {
145   const char *s;
146   int n = strlen (name);
147
148   s = strstr (line, name);
149   return (s && (s == line || spacep (s-1))
150           && (!s[n] || spacep (s+n) || s[n] == '='));
151 }
152
153
154 /* Skip over options.  It is assumed that leading spaces have been
155    removed (this is the case for lines passed to a handler from
156    assuan).  Bkanls after the options are also removed. */
157 static char *
158 skip_options (char *line)
159 {
160   while ( *line == '-' && line[1] == '-' )
161     {
162       while (*line && !spacep (line))
163         line++;
164       while (spacep (line))
165         line++;
166     }
167   return line;
168 }
169
170
171 /* Replace all '+' by a blank. */
172 static void
173 plus_to_blank (char *s)
174 {
175   for (; *s; s++)
176     {
177       if (*s == '+')
178         *s = ' ';
179     }
180 }
181
182
183 /* Do the percent and plus/space unescaping in place and return the
184    length of the valid buffer. */
185 static size_t
186 percent_plus_unescape (char *string)
187 {
188   unsigned char *p = (unsigned char *)string;
189   size_t n = 0;
190
191   while (*string)
192     {
193       if (*string == '%' && string[1] && string[2])
194         { 
195           string++;
196           *p++ = xtoi_2 (string);
197           n++;
198           string+= 2;
199         }
200       else if (*string == '+')
201         {
202           *p++ = ' ';
203           n++;
204           string++;
205         }
206       else
207         {
208           *p++ = *string++;
209           n++;
210         }
211     }
212
213   return n;
214 }
215
216
217
218
219 /* Parse a hex string.  Return an Assuan error code or 0 on success and the
220    length of the parsed string in LEN. */
221 static int
222 parse_hexstring (assuan_context_t ctx, const char *string, size_t *len)
223 {
224   const char *p;
225   size_t n;
226
227   /* parse the hash value */
228   for (p=string, n=0; hexdigitp (p); p++, n++)
229     ;
230   if (*p != ' ' && *p != '\t' && *p)
231     return set_error (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
232   if ((n&1))
233     return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
234   *len = n;
235   return 0;
236 }
237
238 /* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
239    provide space for 20 bytes. BUF is not changed if the function
240    returns an error. */
241 static int
242 parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
243 {
244   int rc;
245   size_t n;
246   const unsigned char *p;
247
248   rc = parse_hexstring (ctx, string, &n);
249   if (rc)
250     return rc;
251   n /= 2;
252   if (n != 20)
253     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of keygrip");
254
255   for (p=(const unsigned char*)string, n=0; n < 20; p += 2, n++)
256     buf[n] = xtoi_2 (p);
257
258   return 0;
259 }
260
261
262 /* Write an assuan status line. */
263 gpg_error_t
264 agent_write_status (ctrl_t ctrl, const char *keyword, ...)
265 {
266   gpg_error_t err = 0;
267   va_list arg_ptr;
268   const char *text;
269   assuan_context_t ctx = ctrl->server_local->assuan_ctx;
270   char buf[950], *p;
271   size_t n;
272
273   va_start (arg_ptr, keyword);
274
275   p = buf; 
276   n = 0;
277   while ( (text = va_arg (arg_ptr, const char *)) )
278     {
279       if (n)
280         {
281           *p++ = ' ';
282           n++;
283         }
284       for ( ; *text && n < DIM (buf)-2; n++)
285         *p++ = *text++;
286     }
287   *p = 0;
288   err = assuan_write_status (ctx, keyword, buf);
289
290   va_end (arg_ptr);
291   return err;
292 }
293
294
295 \f
296 /* ISTRUSTED <hexstring_with_fingerprint>
297
298    Return OK when we have an entry with this fingerprint in our
299    trustlist */
300 static int
301 cmd_istrusted (assuan_context_t ctx, char *line)
302 {
303   ctrl_t ctrl = assuan_get_pointer (ctx);
304   int rc, n, i;
305   char *p;
306   char fpr[41];
307
308   /* Parse the fingerprint value. */
309   for (p=line,n=0; hexdigitp (p); p++, n++)
310     ;
311   if (*p || !(n == 40 || n == 32))
312     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
313   i = 0;
314   if (n==32)
315     {
316       strcpy (fpr, "00000000");
317       i += 8;
318     }
319   for (p=line; i < 40; p++, i++)
320     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
321   fpr[i] = 0;
322   rc = agent_istrusted (ctrl, fpr);
323   if (!rc || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
324     return rc;
325   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
326     return gpg_error (GPG_ERR_NOT_TRUSTED);
327   else
328     {
329       log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
330       return rc;
331     }
332 }
333
334 /* LISTTRUSTED 
335
336    List all entries from the trustlist */
337 static int
338 cmd_listtrusted (assuan_context_t ctx, char *line)
339 {
340   int rc = agent_listtrusted (ctx);
341   if (rc)
342     log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
343   return rc;
344 }
345
346
347 /* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
348
349    Store a new key in into the trustlist*/
350 static int
351 cmd_marktrusted (assuan_context_t ctx, char *line)
352 {
353   ctrl_t ctrl = assuan_get_pointer (ctx);
354   int rc, n, i;
355   char *p;
356   char fpr[41];
357   int flag;
358
359   /* parse the fingerprint value */
360   for (p=line,n=0; hexdigitp (p); p++, n++)
361     ;
362   if (!spacep (p) || !(n == 40 || n == 32))
363     return set_error (GPG_ERR_ASS_PARAMETER, "invalid fingerprint");
364   i = 0;
365   if (n==32)
366     {
367       strcpy (fpr, "00000000");
368       i += 8;
369     }
370   for (p=line; i < 40; p++, i++)
371     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
372   fpr[i] = 0;
373   
374   while (spacep (p))
375     p++;
376   flag = *p++;
377   if ( (flag != 'S' && flag != 'P') || !spacep (p) )
378     return set_error (GPG_ERR_ASS_PARAMETER, "invalid flag - must be P or S");
379   while (spacep (p))
380     p++;
381
382   rc = agent_marktrusted (ctrl, p, fpr, flag);
383   if (rc)
384     log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
385   return rc;
386 }
387
388
389
390 \f
391 /* HAVEKEY <hexstring_with_keygrip>
392   
393    Return success when the secret key is available */
394 static int
395 cmd_havekey (assuan_context_t ctx, char *line)
396 {
397   int rc;
398   unsigned char buf[20];
399
400   rc = parse_keygrip (ctx, line, buf);
401   if (rc)
402     return rc;
403
404   if (agent_key_available (buf))
405     return gpg_error (GPG_ERR_NO_SECKEY);
406
407   return 0;
408 }
409
410
411 /* SIGKEY <hexstring_with_keygrip>
412    SETKEY <hexstring_with_keygrip>
413   
414    Set the  key used for a sign or decrypt operation */
415 static int
416 cmd_sigkey (assuan_context_t ctx, char *line)
417 {
418   int rc;
419   ctrl_t ctrl = assuan_get_pointer (ctx);
420
421   rc = parse_keygrip (ctx, line, ctrl->keygrip);
422   if (rc)
423     return rc;
424   ctrl->have_keygrip = 1;
425   return 0;
426 }
427
428
429 /* SETKEYDESC plus_percent_escaped_string
430
431    Set a description to be used for the next PKSIGN or PKDECRYPT
432    operation if this operation requires the entry of a passphrase.  If
433    this command is not used a default text will be used.  Note, that
434    this description implictly selects the label used for the entry
435    box; if the string contains the string PIN (which in general will
436    not be translated), "PIN" is used, otherwise the translation of
437    "passphrase" is used.  The description string should not contain
438    blanks unless they are percent or '+' escaped.
439
440    The description is only valid for the next PKSIGN or PKDECRYPT
441    operation.
442 */
443 static int
444 cmd_setkeydesc (assuan_context_t ctx, char *line)
445 {
446   ctrl_t ctrl = assuan_get_pointer (ctx);
447   char *desc, *p;
448
449   for (p=line; *p == ' '; p++)
450     ;
451   desc = p;
452   p = strchr (desc, ' ');
453   if (p)
454     *p = 0; /* We ignore any garbage; we might late use it for other args. */
455
456   if (!desc || !*desc)
457     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
458
459   /* Note, that we only need to replace the + characters and should
460      leave the other escaping in place because the escaped string is
461      send verbatim to the pinentry which does the unescaping (but not
462      the + replacing) */
463   plus_to_blank (desc);
464
465   xfree (ctrl->server_local->keydesc);
466   ctrl->server_local->keydesc = xtrystrdup (desc);
467   if (!ctrl->server_local->keydesc)
468     return out_of_core ();
469   return 0;
470 }
471
472
473 /* SETHASH --hash=<name>|<algonumber> <hexstring> 
474
475   The client can use this command to tell the server about the data
476   (which usually is a hash) to be signed. */
477 static int
478 cmd_sethash (assuan_context_t ctx, char *line)
479 {
480   int rc;
481   size_t n;
482   char *p;
483   ctrl_t ctrl = assuan_get_pointer (ctx);
484   unsigned char *buf;
485   char *endp;
486   int algo;
487
488   /* Parse the alternative hash options which may be used instead of
489      the algo number.  */
490   if (has_option_name (line, "--hash"))
491     {
492       if (has_option (line, "--hash=sha1"))
493         algo = GCRY_MD_SHA1;
494       else if (has_option (line, "--hash=sha256"))
495         algo = GCRY_MD_SHA256;
496       else if (has_option (line, "--hash=rmd160"))
497         algo = GCRY_MD_RMD160;
498       else if (has_option (line, "--hash=md5"))
499         algo = GCRY_MD_MD5;
500       else if (has_option (line, "--hash=tls-md5sha1"))
501         algo = GCRY_MD_USER_TLS_MD5SHA1;
502       else
503         return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
504     }
505   else
506     algo = 0;
507
508   line = skip_options (line);
509   
510   if (!algo)
511     {
512       /* No hash option has been given: require an algo number instead  */
513       algo = (int)strtoul (line, &endp, 10);
514       for (line = endp; *line == ' ' || *line == '\t'; line++)
515         ;
516       if (!algo || gcry_md_test_algo (algo))
517         return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
518     }
519   ctrl->digest.algo = algo;
520
521   /* Parse the hash value. */
522   rc = parse_hexstring (ctx, line, &n);
523   if (rc)
524     return rc;
525   n /= 2;
526   if (algo == GCRY_MD_USER_TLS_MD5SHA1 && n == 36)
527     ;
528   else if (n != 16 && n != 20 && n != 24 && n != 32)
529     return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
530
531   if (n > MAX_DIGEST_LEN)
532     return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
533
534   buf = ctrl->digest.value;
535   ctrl->digest.valuelen = n;
536   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
537     buf[n] = xtoi_2 (p);
538   for (; n < ctrl->digest.valuelen; n++)
539     buf[n] = 0;
540   return 0;
541 }
542
543
544 /* PKSIGN <options>
545
546    Perform the actual sign operation. Neither input nor output are
547    sensitive to eavesdropping. */
548 static int
549 cmd_pksign (assuan_context_t ctx, char *line)
550 {
551   int rc;
552   cache_mode_t cache_mode = CACHE_MODE_NORMAL;
553   ctrl_t ctrl = assuan_get_pointer (ctx);
554   membuf_t outbuf;
555   
556   if (opt.ignore_cache_for_signing)
557     cache_mode = CACHE_MODE_IGNORE;
558   else if (!ctrl->server_local->use_cache_for_signing)
559     cache_mode = CACHE_MODE_IGNORE;
560
561   init_membuf (&outbuf, 512);
562
563   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
564                      &outbuf, cache_mode);
565   if (rc)
566     clear_outbuf (&outbuf);
567   else
568     rc = write_and_clear_outbuf (ctx, &outbuf);
569   if (rc)
570     log_error ("command pksign failed: %s\n", gpg_strerror (rc));
571   xfree (ctrl->server_local->keydesc);
572   ctrl->server_local->keydesc = NULL;
573   return rc;
574 }
575
576 /* PKDECRYPT <options>
577
578    Perform the actual decrypt operation.  Input is not 
579    sensitive to eavesdropping */
580 static int
581 cmd_pkdecrypt (assuan_context_t ctx, char *line)
582 {
583   int rc;
584   ctrl_t ctrl = assuan_get_pointer (ctx);
585   unsigned char *value;
586   size_t valuelen;
587   membuf_t outbuf;
588
589   /* First inquire the data to decrypt */
590   rc = assuan_inquire (ctx, "CIPHERTEXT",
591                        &value, &valuelen, MAXLEN_CIPHERTEXT);
592   if (rc)
593     return rc;
594
595   init_membuf (&outbuf, 512);
596
597   rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
598                         value, valuelen, &outbuf);
599   xfree (value);
600   if (rc)
601     clear_outbuf (&outbuf);
602   else
603     rc = write_and_clear_outbuf (ctx, &outbuf);
604   if (rc)
605     log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
606   xfree (ctrl->server_local->keydesc);
607   ctrl->server_local->keydesc = NULL;
608   return rc;
609 }
610
611
612 /* GENKEY
613
614    Generate a new key, store the secret part and return the public
615    part.  Here is an example transaction:
616
617    C: GENKEY
618    S: INQUIRE KEYPARM
619    C: D (genkey (rsa (nbits  1024)))
620    C: END
621    S: D (public-key
622    S: D   (rsa (n 326487324683264) (e 10001)))
623    S  OK key created
624 */
625
626 static int
627 cmd_genkey (assuan_context_t ctx, char *line)
628 {
629   ctrl_t ctrl = assuan_get_pointer (ctx);
630   int rc;
631   unsigned char *value;
632   size_t valuelen;
633   membuf_t outbuf;
634
635   /* First inquire the parameters */
636   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
637   if (rc)
638     return rc;
639
640   init_membuf (&outbuf, 512);
641
642   rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
643   xfree (value);
644   if (rc)
645     clear_outbuf (&outbuf);
646   else
647     rc = write_and_clear_outbuf (ctx, &outbuf);
648   if (rc)
649     log_error ("command genkey failed: %s\n", gpg_strerror (rc));
650   return rc;
651 }
652
653
654
655 \f
656 /* READKEY <hexstring_with_keygrip>
657   
658    Return the public key for the given keygrip.  */
659 static int
660 cmd_readkey (assuan_context_t ctx, char *line)
661 {
662   ctrl_t ctrl = assuan_get_pointer (ctx);
663   int rc;
664   unsigned char grip[20];
665   gcry_sexp_t s_pkey = NULL;
666
667   rc = parse_keygrip (ctx, line, grip);
668   if (rc)
669     return rc; /* Return immediately as this is already an Assuan error code.*/
670
671   rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
672   if (!rc)
673     {
674       size_t len;
675       unsigned char *buf;
676
677       len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
678       assert (len);
679       buf = xtrymalloc (len);
680       if (!buf)
681         rc = gpg_error_from_syserror ();
682       else
683         {
684           len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
685           assert (len);
686           rc = assuan_send_data (ctx, buf, len);
687           xfree (buf);
688         }
689       gcry_sexp_release (s_pkey);
690     }
691
692   if (rc)
693     log_error ("command readkey failed: %s\n", gpg_strerror (rc));
694   return rc;
695 }
696
697
698
699
700
701 \f
702 static int
703 send_back_passphrase (assuan_context_t ctx, int via_data, const char *pw)
704 {
705   size_t n;
706   int rc;
707
708   assuan_begin_confidential (ctx);
709   n = strlen (pw);
710   if (via_data)
711     rc = assuan_send_data (ctx, pw, n);
712   else
713     {
714       char *p = xtrymalloc_secure (n*2+1);
715       if (!p)
716         rc = gpg_error_from_syserror ();
717       else
718         {
719           bin2hex (pw, n, p);
720           rc = assuan_set_okay_line (ctx, p);
721           xfree (p);
722         }
723     }
724   return rc;
725 }
726
727
728 /* GET_PASSPHRASE [--data] <cache_id> [<error_message> <prompt> <description>]
729
730    This function is usually used to ask for a passphrase to be used
731    for conventional encryption, but may also be used by programs which
732    need specal handling of passphrases.  This command uses a syntax
733    which helps clients to use the agent with minimum effort.  The
734    agent either returns with an error or with a OK followed by the hex
735    encoded passphrase.  Note that the length of the strings is
736    implicitly limited by the maximum length of a command.
737
738    If the option "--data" is used the passphrase is returned by usual
739    data lines and not on the okay line.
740 */
741
742 static int
743 cmd_get_passphrase (assuan_context_t ctx, char *line)
744 {
745   ctrl_t ctrl = assuan_get_pointer (ctx);
746   int rc;
747   const char *pw;
748   char *response;
749   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
750   char *p;
751   void *cache_marker;
752   int opt_data;
753
754   opt_data = has_option (line, "--data");
755   line = skip_options (line);
756
757   cacheid = line;
758   p = strchr (cacheid, ' ');
759   if (p)
760     {
761       *p++ = 0;
762       while (*p == ' ')
763         p++;
764       errtext = p;
765       p = strchr (errtext, ' ');
766       if (p)
767         {
768           *p++ = 0;
769           while (*p == ' ')
770             p++;
771           prompt = p;
772           p = strchr (prompt, ' ');
773           if (p)
774             {
775               *p++ = 0;
776               while (*p == ' ')
777                 p++;
778               desc = p;
779               p = strchr (desc, ' ');
780               if (p)
781                 *p = 0; /* ignore garbage */
782             }
783         }
784     }
785   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
786     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
787   if (!desc)
788     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
789
790   if (!strcmp (cacheid, "X"))
791     cacheid = NULL;
792   if (!strcmp (errtext, "X"))
793     errtext = NULL;
794   if (!strcmp (prompt, "X"))
795     prompt = NULL;
796   if (!strcmp (desc, "X"))
797     desc = NULL;
798
799   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
800                : NULL;
801   if (pw)
802     {
803       rc = send_back_passphrase (ctx, opt_data, pw);
804       agent_unlock_cache_entry (&cache_marker);
805     }
806   else
807     {
808       /* Note, that we only need to replace the + characters and
809          should leave the other escaping in place because the escaped
810          string is send verbatim to the pinentry which does the
811          unescaping (but not the + replacing) */
812       if (errtext)
813         plus_to_blank (errtext);
814       if (prompt)
815         plus_to_blank (prompt);
816       if (desc)
817         plus_to_blank (desc);
818
819       rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
820       if (!rc)
821         {
822           if (cacheid)
823             agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
824           rc = send_back_passphrase (ctx, opt_data, response);
825           xfree (response);
826         }
827     }
828
829   if (rc)
830     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
831   return rc;
832 }
833
834
835 /* CLEAR_PASSPHRASE <cache_id>
836
837    may be used to invalidate the cache entry for a passphrase.  The
838    function returns with OK even when there is no cached passphrase.
839 */
840
841 static int
842 cmd_clear_passphrase (assuan_context_t ctx, char *line)
843 {
844   char *cacheid = NULL;
845   char *p;
846
847   /* parse the stuff */
848   for (p=line; *p == ' '; p++)
849     ;
850   cacheid = p;
851   p = strchr (cacheid, ' ');
852   if (p)
853     *p = 0; /* ignore garbage */
854   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
855     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
856
857   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
858   return 0;
859 }
860
861
862 /* GET_CONFIRMATION <description>
863
864    This command may be used to ask for a simple confirmation.
865    DESCRIPTION is displayed along with a Okay and Cancel button.  This
866    command uses a syntax which helps clients to use the agent with
867    minimum effort.  The agent either returns with an error or with a
868    OK.  Note, that the length of DESCRIPTION is implicitly limited by
869    the maximum length of a command. DESCRIPTION should not contain
870    any spaces, those must be encoded either percent escaped or simply
871    as '+'.
872 */
873
874 static int
875 cmd_get_confirmation (assuan_context_t ctx, char *line)
876 {
877   ctrl_t ctrl = assuan_get_pointer (ctx);
878   int rc;
879   char *desc = NULL;
880   char *p;
881
882   /* parse the stuff */
883   for (p=line; *p == ' '; p++)
884     ;
885   desc = p;
886   p = strchr (desc, ' ');
887   if (p)
888     *p = 0; /* We ignore any garbage -may be later used for other args. */
889
890   if (!desc || !*desc)
891     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
892
893   if (!strcmp (desc, "X"))
894     desc = NULL;
895
896   /* Note, that we only need to replace the + characters and should
897      leave the other escaping in place because the escaped string is
898      send verbatim to the pinentry which does the unescaping (but not
899      the + replacing) */
900   if (desc)
901     plus_to_blank (desc);
902
903   rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
904   if (rc)
905     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
906   return rc;
907 }
908
909
910 \f
911 /* LEARN [--send]
912
913    Learn something about the currently inserted smartcard.  With
914    --send the new certificates are send back.  */
915 static int
916 cmd_learn (assuan_context_t ctx, char *line)
917 {
918   ctrl_t ctrl = assuan_get_pointer (ctx);
919   int rc;
920
921   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
922   if (rc)
923     log_error ("command learn failed: %s\n", gpg_strerror (rc));
924   return rc;
925 }
926
927
928 \f
929 /* PASSWD <hexstring_with_keygrip>
930   
931    Change the passphrase/PID for the key identified by keygrip in LINE. */
932 static int
933 cmd_passwd (assuan_context_t ctx, char *line)
934 {
935   ctrl_t ctrl = assuan_get_pointer (ctx);
936   int rc;
937   unsigned char grip[20];
938   gcry_sexp_t s_skey = NULL;
939   unsigned char *shadow_info = NULL;
940
941   rc = parse_keygrip (ctx, line, grip);
942   if (rc)
943     return rc; /* we can't jump to leave because this is already an
944                   Assuan error code. */
945
946   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
947                             grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
948   if (rc)
949     ;
950   else if (!s_skey)
951     {
952       log_error ("changing a smartcard PIN is not yet supported\n");
953       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
954     }
955   else
956     rc = agent_protect_and_store (ctrl, s_skey);
957
958   xfree (ctrl->server_local->keydesc);
959   ctrl->server_local->keydesc = NULL;
960   gcry_sexp_release (s_skey);
961   xfree (shadow_info);
962   if (rc)
963     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
964   return rc;
965 }
966
967 /* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <hexstring>
968   
969    Set the cached passphrase/PIN for the key identified by the keygrip
970    to passwd for the given time, where -1 means infinite and 0 means
971    the default (currently only a timeout of -1 is allowed, which means
972    to never expire it).  If passwd is not provided, ask for it via the
973    pinentry module.  */
974 static int
975 cmd_preset_passphrase (assuan_context_t ctx, char *line)
976 {
977   int rc;
978   unsigned char grip[20];
979   char *grip_clear = NULL;
980   char *passphrase = NULL;
981   int ttl;
982   size_t len;
983
984   if (!opt.allow_preset_passphrase)
985     return gpg_error (GPG_ERR_NOT_SUPPORTED);
986
987   rc = parse_keygrip (ctx, line, grip);
988   if (rc)
989     return rc;
990
991   /* FIXME: parse_keygrip should return a tail pointer.  */
992   grip_clear = line;
993   while (*line && (*line != ' ' && *line != '\t'))
994     line++;
995   if (!*line)
996     return gpg_error (GPG_ERR_MISSING_VALUE);
997   *line = '\0';
998   line++;
999   while (*line && (*line == ' ' || *line == '\t'))
1000     line++;
1001   
1002   /* Currently, only infinite timeouts are allowed.  */
1003   ttl = -1;
1004   if (line[0] != '-' || line[1] != '1')
1005     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1006   line++;
1007   line++;
1008   while (!(*line != ' ' && *line != '\t'))
1009     line++;
1010
1011   /* Syntax check the hexstring.  */
1012   rc = parse_hexstring (ctx, line, &len);
1013   if (rc)
1014     return rc;
1015   line[len] = '\0';
1016
1017   /* If there is a passphrase, use it.  Currently, a passphrase is
1018      required.  */
1019   if (*line)
1020     passphrase = line;
1021   else
1022     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1023
1024   rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
1025
1026   if (rc)
1027     log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc));
1028
1029   return rc;
1030 }
1031
1032 \f
1033 /* SCD <commands to pass to the scdaemon>
1034   
1035    This is a general quote command to redirect everything to the
1036    SCDAEMON. */
1037 static int
1038 cmd_scd (assuan_context_t ctx, char *line)
1039 {
1040   ctrl_t ctrl = assuan_get_pointer (ctx);
1041   int rc;
1042
1043   rc = divert_generic_cmd (ctrl, line, ctx);
1044
1045   return rc;
1046 }
1047
1048
1049 \f
1050 /* GETVAL <key>
1051
1052    Return the value for KEY from the special environment as created by
1053    PUTVAL.
1054  */
1055 static int
1056 cmd_getval (assuan_context_t ctx, char *line)
1057 {
1058   int rc = 0;
1059   char *key = NULL;
1060   char *p;
1061   struct putval_item_s *vl;
1062
1063   for (p=line; *p == ' '; p++)
1064     ;
1065   key = p;
1066   p = strchr (key, ' ');
1067   if (p)
1068     {
1069       *p++ = 0; 
1070       for (; *p == ' '; p++)
1071         ;
1072       if (*p)
1073         return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
1074     }
1075   if (!key || !*key)
1076     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1077
1078
1079   for (vl=putval_list; vl; vl = vl->next)
1080     if ( !strcmp (vl->d, key) )
1081       break;
1082
1083   if (vl) /* Got an entry. */
1084     rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
1085   else
1086     return gpg_error (GPG_ERR_NO_DATA);
1087
1088   if (rc)
1089     log_error ("command getval failed: %s\n", gpg_strerror (rc));
1090   return rc;
1091 }
1092
1093
1094 /* PUTVAL <key> [<percent_escaped_value>]
1095
1096    The gpg-agent maintains a kind of environment which may be used to
1097    store key/value pairs in it, so that they can be retrieved later.
1098    This may be used by helper daemons to daemonize themself on
1099    invocation and register them with gpg-agent.  Callers of the
1100    daemon's service may now first try connect to get the information
1101    for that service from gpg-agent through the GETVAL command and then
1102    try to connect to that daemon.  Only if that fails they may start
1103    an own instance of the service daemon. 
1104
1105    KEY is an an arbitrary symbol with the same syntax rules as keys
1106    for shell environment variables.  PERCENT_ESCAPED_VALUE is the
1107    corresponsing value; they should be similar to the values of
1108    envronment variables but gpg-agent does not enforce any
1109    restrictions.  If that value is not given any value under that KEY
1110    is removed from this special environment.
1111 */
1112 static int
1113 cmd_putval (assuan_context_t ctx, char *line)
1114 {
1115   int rc = 0;
1116   char *key = NULL;
1117   char *value = NULL;
1118   size_t valuelen = 0;
1119   char *p;
1120   struct putval_item_s *vl, *vlprev;
1121
1122   for (p=line; *p == ' '; p++)
1123     ;
1124   key = p;
1125   p = strchr (key, ' ');
1126   if (p)
1127     {
1128       *p++ = 0; 
1129       for (; *p == ' '; p++)
1130         ;
1131       if (*p)
1132         {
1133           value = p;
1134           p = strchr (value, ' ');
1135           if (p)
1136             *p = 0;
1137           valuelen = percent_plus_unescape (value);
1138         }
1139     }
1140   if (!key || !*key)
1141     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1142
1143
1144   for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1145     if ( !strcmp (vl->d, key) )
1146       break;
1147
1148   if (vl) /* Delete old entry. */
1149     {
1150       if (vlprev)
1151         vlprev->next = vl->next;
1152       else
1153         putval_list = vl->next;
1154       xfree (vl);
1155     }
1156
1157   if (valuelen) /* Add entry. */  
1158     {
1159       vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1160       if (!vl)
1161         rc = gpg_error_from_syserror ();
1162       else
1163         {
1164           vl->len = valuelen;
1165           vl->off = strlen (key) + 1;
1166           strcpy (vl->d, key);
1167           memcpy (vl->d + vl->off, value, valuelen);
1168           vl->next = putval_list;
1169           putval_list = vl;
1170         }
1171     }
1172
1173   if (rc)
1174     log_error ("command putval failed: %s\n", gpg_strerror (rc));
1175   return rc;
1176 }
1177
1178
1179
1180 \f
1181 /* UPDATESTARTUPTTY 
1182   
1183   Set startup TTY and X DISPLAY variables to the values of this
1184   session.  This command is useful to pull future pinentries to
1185   another screen.  It is only required because there is no way in the
1186   ssh-agent protocol to convey this information.  */
1187 static int
1188 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1189 {
1190   ctrl_t ctrl = assuan_get_pointer (ctx);
1191
1192   xfree (opt.startup_display); opt.startup_display = NULL;
1193   xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
1194   xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
1195   xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
1196   xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
1197
1198   if (ctrl->display)
1199     opt.startup_display = xtrystrdup (ctrl->display);
1200   if (ctrl->ttyname)
1201     opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
1202   if (ctrl->ttytype)
1203     opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
1204   if (ctrl->lc_ctype) 
1205     opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
1206   if (ctrl->lc_messages)
1207     opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
1208
1209   return 0;
1210 }
1211
1212
1213 \f
1214 static int
1215 option_handler (assuan_context_t ctx, const char *key, const char *value)
1216 {
1217   ctrl_t ctrl = assuan_get_pointer (ctx);
1218
1219   if (!strcmp (key, "display"))
1220     {
1221       if (ctrl->display)
1222         free (ctrl->display);
1223       ctrl->display = strdup (value);
1224       if (!ctrl->display)
1225         return out_of_core ();
1226     }
1227   else if (!strcmp (key, "ttyname"))
1228     {
1229       if (!opt.keep_tty)
1230         {
1231           if (ctrl->ttyname)
1232             free (ctrl->ttyname);
1233           ctrl->ttyname = strdup (value);
1234           if (!ctrl->ttyname)
1235             return out_of_core ();
1236         }
1237     }
1238   else if (!strcmp (key, "ttytype"))
1239     {
1240       if (!opt.keep_tty)
1241         {
1242           if (ctrl->ttytype)
1243             free (ctrl->ttytype);
1244           ctrl->ttytype = strdup (value);
1245           if (!ctrl->ttytype)
1246             return out_of_core ();
1247         }
1248     }
1249   else if (!strcmp (key, "lc-ctype"))
1250     {
1251       if (ctrl->lc_ctype)
1252         free (ctrl->lc_ctype);
1253       ctrl->lc_ctype = strdup (value);
1254       if (!ctrl->lc_ctype)
1255         return out_of_core ();
1256     }
1257   else if (!strcmp (key, "lc-messages"))
1258     {
1259       if (ctrl->lc_messages)
1260         free (ctrl->lc_messages);
1261       ctrl->lc_messages = strdup (value);
1262       if (!ctrl->lc_messages)
1263         return out_of_core ();
1264     }
1265   else if (!strcmp (key, "use-cache-for-signing"))
1266     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1267   else
1268     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
1269
1270   return 0;
1271 }
1272
1273
1274
1275 \f
1276 /* Tell the assuan library about our commands */
1277 static int
1278 register_commands (assuan_context_t ctx)
1279 {
1280   static struct {
1281     const char *name;
1282     int (*handler)(assuan_context_t, char *line);
1283   } table[] = {
1284     { "ISTRUSTED",      cmd_istrusted },
1285     { "HAVEKEY",        cmd_havekey },
1286     { "SIGKEY",         cmd_sigkey },
1287     { "SETKEY",         cmd_sigkey },
1288     { "SETKEYDESC",     cmd_setkeydesc },
1289     { "SETHASH",        cmd_sethash },
1290     { "PKSIGN",         cmd_pksign },
1291     { "PKDECRYPT",      cmd_pkdecrypt },
1292     { "GENKEY",         cmd_genkey },
1293     { "READKEY",        cmd_readkey },
1294     { "GET_PASSPHRASE", cmd_get_passphrase },
1295     { "PRESET_PASSPHRASE", cmd_preset_passphrase },
1296     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
1297     { "GET_CONFIRMATION", cmd_get_confirmation },
1298     { "LISTTRUSTED",    cmd_listtrusted },
1299     { "MARKTRUSTED",    cmd_marktrusted },
1300     { "LEARN",          cmd_learn },
1301     { "PASSWD",         cmd_passwd },
1302     { "INPUT",          NULL }, 
1303     { "OUTPUT",         NULL }, 
1304     { "SCD",            cmd_scd },
1305     { "GETVAL",         cmd_getval },
1306     { "PUTVAL",         cmd_putval },
1307     { "UPDATESTARTUPTTY",  cmd_updatestartuptty },
1308     { NULL }
1309   };
1310   int i, rc;
1311
1312   for (i=0; table[i].name; i++)
1313     {
1314       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1315       if (rc)
1316         return rc;
1317     } 
1318   assuan_register_reset_notify (ctx, reset_notify);
1319   assuan_register_option_handler (ctx, option_handler);
1320   return 0;
1321 }
1322
1323
1324 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
1325    piper server, otherwise it is a regular server */
1326 void
1327 start_command_handler (int listen_fd, int fd)
1328 {
1329   int rc;
1330   assuan_context_t ctx;
1331   struct server_control_s ctrl;
1332
1333   memset (&ctrl, 0, sizeof ctrl);
1334   agent_init_default_ctrl (&ctrl);
1335   
1336   if (listen_fd == -1 && fd == -1)
1337     {
1338       int filedes[2];
1339
1340       filedes[0] = 0;
1341       filedes[1] = 1;
1342       rc = assuan_init_pipe_server (&ctx, filedes);
1343     }
1344   else if (listen_fd != -1)
1345     {
1346       rc = assuan_init_socket_server_ext (&ctx, listen_fd, 0);
1347     }
1348   else 
1349     {
1350       rc = assuan_init_socket_server_ext (&ctx, fd, 2);
1351       ctrl.connection_fd = fd;
1352     }
1353   if (rc)
1354     {
1355       log_error ("failed to initialize the server: %s\n",
1356                  gpg_strerror(rc));
1357       agent_exit (2);
1358     }
1359   rc = register_commands (ctx);
1360   if (rc)
1361     {
1362       log_error ("failed to register commands with Assuan: %s\n",
1363                  gpg_strerror(rc));
1364       agent_exit (2);
1365     }
1366
1367   assuan_set_pointer (ctx, &ctrl);
1368   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1369   ctrl.server_local->assuan_ctx = ctx;
1370   ctrl.server_local->message_fd = -1;
1371   ctrl.server_local->use_cache_for_signing = 1;
1372   ctrl.digest.raw_value = 0;
1373
1374   if (DBG_ASSUAN)
1375     assuan_set_log_stream (ctx, log_get_stream ());
1376
1377   for (;;)
1378     {
1379       rc = assuan_accept (ctx);
1380       if (rc == -1)
1381         {
1382           break;
1383         }
1384       else if (rc)
1385         {
1386           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1387           break;
1388         }
1389       
1390       rc = assuan_process (ctx);
1391       if (rc)
1392         {
1393           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1394           continue;
1395         }
1396     }
1397
1398   /* Reset the SCD if needed. */
1399   agent_reset_scd (&ctrl);
1400
1401   /* Reset the pinentry (in case of popup messages). */
1402   agent_reset_query (&ctrl);
1403
1404   assuan_deinit_server (ctx);
1405   if (ctrl.display)
1406     free (ctrl.display);
1407   if (ctrl.ttyname)
1408     free (ctrl.ttyname);
1409   if (ctrl.ttytype)
1410     free (ctrl.ttytype);
1411   if (ctrl.lc_ctype)
1412     free (ctrl.lc_ctype);
1413   if (ctrl.lc_messages)
1414     free (ctrl.lc_messages);
1415   xfree (ctrl.server_local);
1416 }
1417