Updated FSF's address.
[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, ASSUAN_ ## 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   ASSUAN_CONTEXT assuan_ctx;
54   int message_fd;
55   int use_cache_for_signing;
56   char *keydesc;  /* Allocated description for the next key
57                      operation. */
58 };
59
60
61
62
63 \f
64 /* Release the memory buffer MB but first wipe out the used memory. */
65 static void
66 clear_outbuf (membuf_t *mb)
67 {
68   void *p;
69   size_t n;
70
71   p = get_membuf (mb, &n);
72   if (p)
73     {
74       memset (p, 0, n);
75       xfree (p);
76     }
77 }
78
79
80 /* Write the content of memory buffer MB as assuan data to CTX and
81    wipe the buffer out afterwards. */
82 static gpg_error_t
83 write_and_clear_outbuf (assuan_context_t ctx, membuf_t *mb)
84 {
85   assuan_error_t ae;
86   void *p;
87   size_t n;
88
89   p = get_membuf (mb, &n);
90   if (!p)
91     return gpg_error (GPG_ERR_ENOMEM);
92   ae = assuan_send_data (ctx, p, n);
93   memset (p, 0, n);
94   xfree (p);
95   return map_assuan_err (ae);
96 }
97
98
99 static void
100 reset_notify (ASSUAN_CONTEXT ctx)
101 {
102   ctrl_t ctrl = assuan_get_pointer (ctx);
103
104   memset (ctrl->keygrip, 0, 20);
105   ctrl->have_keygrip = 0;
106   ctrl->digest.valuelen = 0;
107
108   xfree (ctrl->server_local->keydesc);
109   ctrl->server_local->keydesc = NULL;
110 }
111
112
113 /* Check whether the option NAME appears in LINE */
114 static int
115 has_option (const char *line, const char *name)
116 {
117   const char *s;
118   int n = strlen (name);
119
120   s = strstr (line, name);
121   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
122 }
123
124 /* Replace all '+' by a blank. */
125 static void
126 plus_to_blank (char *s)
127 {
128   for (; *s; s++)
129     {
130       if (*s == '+')
131         *s = ' ';
132     }
133 }
134
135
136 /* Parse a hex string.  Return an Assuan error code or 0 on success and the
137    length of the parsed string in LEN. */
138 static int
139 parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
140 {
141   const char *p;
142   size_t n;
143
144   /* parse the hash value */
145   for (p=string, n=0; hexdigitp (p); p++, n++)
146     ;
147   if (*p != ' ' && *p != '\t' && *p)
148     return set_error (Parameter_Error, "invalid hexstring");
149   if ((n&1))
150     return set_error (Parameter_Error, "odd number of digits");
151   *len = n;
152   return 0;
153 }
154
155 /* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
156    provide space for 20 bytes. BUF is not changed if the fucntions
157    returns an error. */
158 static int
159 parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
160 {
161   int rc;
162   size_t n;
163   const unsigned char *p;
164
165   rc = parse_hexstring (ctx, string, &n);
166   if (rc)
167     return rc;
168   n /= 2;
169   if (n != 20)
170     return set_error (Parameter_Error, "invalid length of keygrip");
171
172   for (p=(const unsigned char*)string, n=0; n < 20; p += 2, n++)
173     buf[n] = xtoi_2 (p);
174
175   return 0;
176 }
177
178
179
180
181 /* ISTRUSTED <hexstring_with_fingerprint>
182
183    Return OK when we have an entry with this fingerprint in our
184    trustlist */
185 static int
186 cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
187 {
188   int rc, n, i;
189   char *p;
190   char fpr[41];
191
192   /* parse the fingerprint value */
193   for (p=line,n=0; hexdigitp (p); p++, n++)
194     ;
195   if (*p || !(n == 40 || n == 32))
196     return set_error (Parameter_Error, "invalid fingerprint");
197   i = 0;
198   if (n==32)
199     {
200       strcpy (fpr, "00000000");
201       i += 8;
202     }
203   for (p=line; i < 40; p++, i++)
204     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
205   fpr[i] = 0;
206   rc = agent_istrusted (fpr);
207   if (!rc)
208     return 0;
209   else if (rc == -1)
210     return ASSUAN_Not_Trusted;
211   else
212     {
213       log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
214       return map_to_assuan_status (rc);
215     }
216 }
217
218 /* LISTTRUSTED 
219
220    List all entries from the trustlist */
221 static int
222 cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
223 {
224   int rc = agent_listtrusted (ctx);
225   if (rc)
226     log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
227   return map_to_assuan_status (rc);
228 }
229
230
231 /* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
232
233    Store a new key in into the trustlist*/
234 static int
235 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
236 {
237   ctrl_t ctrl = assuan_get_pointer (ctx);
238   int rc, n, i;
239   char *p;
240   char fpr[41];
241   int flag;
242
243   /* parse the fingerprint value */
244   for (p=line,n=0; hexdigitp (p); p++, n++)
245     ;
246   if (!spacep (p) || !(n == 40 || n == 32))
247     return set_error (Parameter_Error, "invalid fingerprint");
248   i = 0;
249   if (n==32)
250     {
251       strcpy (fpr, "00000000");
252       i += 8;
253     }
254   for (p=line; i < 40; p++, i++)
255     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
256   fpr[i] = 0;
257   
258   while (spacep (p))
259     p++;
260   flag = *p++;
261   if ( (flag != 'S' && flag != 'P') || !spacep (p) )
262     return set_error (Parameter_Error, "invalid flag - must be P or S");
263   while (spacep (p))
264     p++;
265
266   rc = agent_marktrusted (ctrl, p, fpr, flag);
267   if (rc)
268     log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
269   return map_to_assuan_status (rc);
270 }
271
272
273
274 \f
275 /* HAVEKEY <hexstring_with_keygrip>
276   
277    Return success when the secret key is available */
278 static int
279 cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
280 {
281   int rc;
282   unsigned char buf[20];
283
284   rc = parse_keygrip (ctx, line, buf);
285   if (rc)
286     return rc;
287
288   if (agent_key_available (buf))
289     return ASSUAN_No_Secret_Key;
290
291   return 0;
292 }
293
294
295 /* SIGKEY <hexstring_with_keygrip>
296    SETKEY <hexstring_with_keygrip>
297   
298    Set the  key used for a sign or decrypt operation */
299 static int
300 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
301 {
302   int rc;
303   ctrl_t ctrl = assuan_get_pointer (ctx);
304
305   rc = parse_keygrip (ctx, line, ctrl->keygrip);
306   if (rc)
307     return rc;
308   ctrl->have_keygrip = 1;
309   return 0;
310 }
311
312
313 /* SETKEYDESC plus_percent_escaped_string:
314
315    Set a description to be used for the next PKSIGN or PKDECRYPT
316    operation if this operation requires the entry of a passphrase.  If
317    this command is not used a default text will be used.  Note, that
318    this description implictly selects the label used for the entry
319    box; if the string contains the string PIN (which in general will
320    not be translated), "PIN" is used, otherwise the translation of
321    'passphrase" is used.  The description string should not contain
322    blanks unless they are percent or '+' escaped.
323
324    The description is only valid for the next PKSIGN or PKDECRYPT
325    operation.
326 */
327 static int
328 cmd_setkeydesc (assuan_context_t ctx, char *line)
329 {
330   ctrl_t ctrl = assuan_get_pointer (ctx);
331   char *desc, *p;
332
333   for (p=line; *p == ' '; p++)
334     ;
335   desc = p;
336   p = strchr (desc, ' ');
337   if (p)
338     *p = 0; /* We ignore any garbage; we might late use it for other args. */
339
340   if (!desc || !*desc)
341     return set_error (Parameter_Error, "no description given");
342
343   /* Note, that we only need to replace the + characters and should
344      leave the other escaping in place because the escaped string is
345      send verbatim to the pinentry which does the unescaping (but not
346      the + replacing) */
347   plus_to_blank (desc);
348
349   xfree (ctrl->server_local->keydesc);
350   ctrl->server_local->keydesc = xtrystrdup (desc);
351   if (!ctrl->server_local->keydesc)
352     return map_to_assuan_status (gpg_error_from_errno (errno));
353   return 0;
354 }
355
356
357 /* SETHASH <algonumber> <hexstring> 
358
359   The client can use this command to tell the server about the data
360   (which usually is a hash) to be signed. */
361 static int
362 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
363 {
364   int rc;
365   size_t n;
366   char *p;
367   ctrl_t ctrl = assuan_get_pointer (ctx);
368   unsigned char *buf;
369   char *endp;
370   int algo;
371
372   /* parse the algo number and check it */
373   algo = (int)strtoul (line, &endp, 10);
374   for (line = endp; *line == ' ' || *line == '\t'; line++)
375     ;
376   if (!algo || gcry_md_test_algo (algo))
377     return set_error (Unsupported_Algorithm, NULL);
378   ctrl->digest.algo = algo;
379
380   /* parse the hash value */
381   rc = parse_hexstring (ctx, line, &n);
382   if (rc)
383     return rc;
384   n /= 2;
385   if (n != 16 && n != 20 && n != 24 && n != 32)
386     return set_error (Parameter_Error, "unsupported length of hash");
387   if (n > MAX_DIGEST_LEN)
388     return set_error (Parameter_Error, "hash value to long");
389
390   buf = ctrl->digest.value;
391   ctrl->digest.valuelen = n;
392   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
393     buf[n] = xtoi_2 (p);
394   for (; n < ctrl->digest.valuelen; n++)
395     buf[n] = 0;
396   return 0;
397 }
398
399
400 /* PKSIGN <options>
401
402    Perform the actual sign operation. Neither input nor output are
403    sensitive to eavesdropping. */
404 static int
405 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
406 {
407   int rc;
408   cache_mode_t cache_mode = CACHE_MODE_NORMAL;
409   ctrl_t ctrl = assuan_get_pointer (ctx);
410   membuf_t outbuf;
411   
412   if (opt.ignore_cache_for_signing)
413     cache_mode = CACHE_MODE_IGNORE;
414   else if (!ctrl->server_local->use_cache_for_signing)
415     cache_mode = CACHE_MODE_IGNORE;
416
417   init_membuf (&outbuf, 512);
418
419   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
420                      &outbuf, cache_mode);
421   if (rc)
422     clear_outbuf (&outbuf);
423   else
424     rc = write_and_clear_outbuf (ctx, &outbuf);
425   if (rc)
426     log_error ("command pksign failed: %s\n", gpg_strerror (rc));
427   xfree (ctrl->server_local->keydesc);
428   ctrl->server_local->keydesc = NULL;
429   return map_to_assuan_status (rc);
430 }
431
432 /* PKDECRYPT <options>
433
434    Perform the actual decrypt operation.  Input is not 
435    sensitive to eavesdropping */
436 static int
437 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
438 {
439   int rc;
440   ctrl_t ctrl = assuan_get_pointer (ctx);
441   unsigned char *value;
442   size_t valuelen;
443   membuf_t outbuf;
444
445   /* First inquire the data to decrypt */
446   rc = assuan_inquire (ctx, "CIPHERTEXT",
447                        &value, &valuelen, MAXLEN_CIPHERTEXT);
448   if (rc)
449     return rc;
450
451   init_membuf (&outbuf, 512);
452
453   rc = agent_pkdecrypt (ctrl, ctrl->server_local->keydesc,
454                         value, valuelen, &outbuf);
455   xfree (value);
456   if (rc)
457     clear_outbuf (&outbuf);
458   else
459     rc = write_and_clear_outbuf (ctx, &outbuf);
460   if (rc)
461     log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
462   xfree (ctrl->server_local->keydesc);
463   ctrl->server_local->keydesc = NULL;
464   return map_to_assuan_status (rc);
465 }
466
467
468 /* GENKEY
469
470    Generate a new key, store the secret part and return the public
471    part.  Here is an example transaction:
472
473    C: GENKEY
474    S: INQUIRE KEYPARM
475    C: D (genkey (rsa (nbits  1024)))
476    C: END
477    S: D (public-key
478    S: D   (rsa (n 326487324683264) (e 10001)))
479    S  OK key created
480 */
481
482 static int
483 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
484 {
485   ctrl_t ctrl = assuan_get_pointer (ctx);
486   int rc;
487   unsigned char *value;
488   size_t valuelen;
489   membuf_t outbuf;
490
491   /* First inquire the parameters */
492   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
493   if (rc)
494     return rc;
495
496   init_membuf (&outbuf, 512);
497
498   rc = agent_genkey (ctrl, (char*)value, valuelen, &outbuf);
499   xfree (value);
500   if (rc)
501     clear_outbuf (&outbuf);
502   else
503     rc = write_and_clear_outbuf (ctx, &outbuf);
504   if (rc)
505     log_error ("command genkey failed: %s\n", gpg_strerror (rc));
506   return map_to_assuan_status (rc);
507 }
508
509
510
511 \f
512 /* READKEY <hexstring_with_keygrip>
513   
514    Return the public key for the given keygrip.  */
515 static int
516 cmd_readkey (assuan_context_t ctx, char *line)
517 {
518   ctrl_t ctrl = assuan_get_pointer (ctx);
519   int rc;
520   unsigned char grip[20];
521   gcry_sexp_t s_pkey = NULL;
522
523   rc = parse_keygrip (ctx, line, grip);
524   if (rc)
525     return rc; /* Return immediately as this is already an Assuan error code.*/
526
527   rc = agent_public_key_from_file (ctrl, grip, &s_pkey);
528   if (!rc)
529     {
530       size_t len;
531       unsigned char *buf;
532
533       len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
534       assert (len);
535       buf = xtrymalloc (len);
536       if (!buf)
537         rc = gpg_error_from_errno (errno);
538       else
539         {
540           len = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, buf, len);
541           assert (len);
542           rc = assuan_send_data (ctx, buf, len);
543           rc = map_assuan_err (rc);
544           xfree (buf);
545         }
546       gcry_sexp_release (s_pkey);
547     }
548
549   if (rc)
550     log_error ("command readkey failed: %s\n", gpg_strerror (rc));
551   return map_to_assuan_status (rc);
552 }
553
554
555
556
557
558 \f
559 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
560
561    This function is usually used to ask for a passphrase to be used
562    for conventional encryption, but may also be used by programs which
563    need specal handling of passphrases.  This command uses a syntax
564    which helps clients to use the agent with minimum effort.  The
565    agent either returns with an error or with a OK followed by the hex
566    encoded passphrase.  Note that the length of the strings is
567    implicitly limited by the maximum length of a command.
568 */
569
570 static int
571 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
572 {
573   ctrl_t ctrl = assuan_get_pointer (ctx);
574   int rc;
575   const char *pw;
576   char *response;
577   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
578   char *p;
579   void *cache_marker;
580
581   /* parse the stuff */
582   for (p=line; *p == ' '; p++)
583     ;
584   cacheid = p;
585   p = strchr (cacheid, ' ');
586   if (p)
587     {
588       *p++ = 0;
589       while (*p == ' ')
590         p++;
591       errtext = p;
592       p = strchr (errtext, ' ');
593       if (p)
594         {
595           *p++ = 0;
596           while (*p == ' ')
597             p++;
598           prompt = p;
599           p = strchr (prompt, ' ');
600           if (p)
601             {
602               *p++ = 0;
603               while (*p == ' ')
604                 p++;
605               desc = p;
606               p = strchr (desc, ' ');
607               if (p)
608                 *p = 0; /* ignore garbage */
609             }
610         }
611     }
612   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
613     return set_error (Parameter_Error, "invalid length of cacheID");
614   if (!desc)
615     return set_error (Parameter_Error, "no description given");
616
617   if (!strcmp (cacheid, "X"))
618     cacheid = NULL;
619   if (!strcmp (errtext, "X"))
620     errtext = NULL;
621   if (!strcmp (prompt, "X"))
622     prompt = NULL;
623   if (!strcmp (desc, "X"))
624     desc = NULL;
625
626   /* Note: we store the hexified versions in the cache. */
627   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
628                : NULL;
629   if (pw)
630     {
631       assuan_begin_confidential (ctx);
632       rc = assuan_set_okay_line (ctx, pw);
633       agent_unlock_cache_entry (&cache_marker);
634     }
635   else
636     {
637       /* Note, that we only need to replace the + characters and
638          should leave the other escaping in place because the escaped
639          string is send verbatim to the pinentry which does the
640          unescaping (but not the + replacing) */
641       if (errtext)
642         plus_to_blank (errtext);
643       if (prompt)
644         plus_to_blank (prompt);
645       if (desc)
646         plus_to_blank (desc);
647
648       rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
649       if (!rc)
650         {
651           if (cacheid)
652             agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
653           assuan_begin_confidential (ctx);
654           rc = assuan_set_okay_line (ctx, response);
655           xfree (response);
656         }
657     }
658
659   if (rc)
660     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
661   return map_to_assuan_status (rc);
662 }
663
664
665 /* CLEAR_PASSPHRASE <cache_id>
666
667    may be used to invalidate the cache entry for a passphrase.  The
668    function returns with OK even when there is no cached passphrase.
669 */
670
671 static int
672 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
673 {
674   char *cacheid = NULL;
675   char *p;
676
677   /* parse the stuff */
678   for (p=line; *p == ' '; p++)
679     ;
680   cacheid = p;
681   p = strchr (cacheid, ' ');
682   if (p)
683     *p = 0; /* ignore garbage */
684   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
685     return set_error (Parameter_Error, "invalid length of cacheID");
686
687   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
688   return 0;
689 }
690
691
692 /* GET_CONFIRMATION <description>
693
694    This command may be used to ask for a simple confirmation.
695    DESCRIPTION is displayed along with a Okay and Cancel button.  This
696    command uses a syntax which helps clients to use the agent with
697    minimum effort.  The agent either returns with an error or with a
698    OK.  Note, that the length of DESCRIPTION is implicitly limited by
699    the maximum length of a command. DESCRIPTION should not contain
700    any spaces, those must be encoded either percent escaped or simply
701    as '+'.
702 */
703
704 static int
705 cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line)
706 {
707   ctrl_t ctrl = assuan_get_pointer (ctx);
708   int rc;
709   char *desc = NULL;
710   char *p;
711
712   /* parse the stuff */
713   for (p=line; *p == ' '; p++)
714     ;
715   desc = p;
716   p = strchr (desc, ' ');
717   if (p)
718     *p = 0; /* We ignore any garbage -may be later used for other args. */
719
720   if (!desc || !*desc)
721     return set_error (Parameter_Error, "no description given");
722
723   if (!strcmp (desc, "X"))
724     desc = NULL;
725
726   /* Note, that we only need to replace the + characters and should
727      leave the other escaping in place because the escaped string is
728      send verbatim to the pinentry which does the unescaping (but not
729      the + replacing) */
730   if (desc)
731     plus_to_blank (desc);
732
733   rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
734   if (rc)
735     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
736   return map_to_assuan_status (rc);
737 }
738
739
740 \f
741 /* LEARN [--send]
742
743    Learn something about the currently inserted smartcard.  With
744    --send the new certificates are send back.  */
745 static int
746 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
747 {
748   ctrl_t ctrl = assuan_get_pointer (ctx);
749   int rc;
750
751   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
752   if (rc)
753     log_error ("command learn failed: %s\n", gpg_strerror (rc));
754   return map_to_assuan_status (rc);
755 }
756
757
758 \f
759 /* PASSWD <hexstring_with_keygrip>
760   
761    Change the passphrase/PID for the key identified by keygrip in LINE. */
762 static int
763 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
764 {
765   ctrl_t ctrl = assuan_get_pointer (ctx);
766   int rc;
767   unsigned char grip[20];
768   gcry_sexp_t s_skey = NULL;
769   unsigned char *shadow_info = NULL;
770
771   rc = parse_keygrip (ctx, line, grip);
772   if (rc)
773     return rc; /* we can't jump to leave because this is already an
774                   Assuan error code. */
775
776   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
777                             grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
778   if (rc)
779     ;
780   else if (!s_skey)
781     {
782       log_error ("changing a smartcard PIN is not yet supported\n");
783       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
784     }
785   else
786     rc = agent_protect_and_store (ctrl, s_skey);
787
788   xfree (ctrl->server_local->keydesc);
789   ctrl->server_local->keydesc = NULL;
790   gcry_sexp_release (s_skey);
791   xfree (shadow_info);
792   if (rc)
793     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
794   return map_to_assuan_status (rc);
795 }
796
797 /* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <passwd>
798   
799    Set the cached passphrase/PIN for the key identified by the keygrip
800    to passwd for the given time, where -1 means infinite and 0 means
801    the default (currently only a timeout of -1 is allowed, which means
802    to never expire it).  If passwd is not provided, ask for it via the
803    pinentry module.  */
804 static int
805 cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line)
806 {
807   int rc;
808   unsigned char grip[20];
809   char *grip_clear = NULL;
810   char *passphrase = NULL;
811   int ttl;
812
813   if (!opt.allow_preset_passphrase)
814     return gpg_error (GPG_ERR_NOT_SUPPORTED);
815
816   rc = parse_keygrip (ctx, line, grip);
817   if (rc)
818     return rc;
819
820   /* FIXME: parse_keygrip should return a tail pointer.  */
821   grip_clear = line;
822   while (*line && (*line != ' ' && *line != '\t'))
823     line++;
824   if (!*line)
825     return map_to_assuan_status (gpg_error (GPG_ERR_MISSING_VALUE));
826   *line = '\0';
827   line++;
828   while (*line && (*line == ' ' || *line == '\t'))
829     line++;
830   
831   /* Currently, only infinite timeouts are allowed.  */
832   ttl = -1;
833   if (line[0] != '-' || line[1] != '1')
834     return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED));
835   line++;
836   line++;
837   while (!(*line != ' ' && *line != '\t'))
838     line++;
839
840   /* If there is a passphrase, use it.  Currently, a passphrase is
841      required.  */
842   if (*line)
843     passphrase = line;
844   else
845     return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED));
846
847   rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
848
849   if (rc)
850     log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc));
851
852   return map_to_assuan_status (rc);
853 }
854
855 \f
856 /* SCD <commands to pass to the scdaemon>
857   
858    This is a general quote command to redirect everything to the
859    SCDAEMON. */
860 static int
861 cmd_scd (ASSUAN_CONTEXT ctx, char *line)
862 {
863   ctrl_t ctrl = assuan_get_pointer (ctx);
864   int rc;
865
866   rc = divert_generic_cmd (ctrl, line, ctx);
867
868   return map_to_assuan_status (rc);
869 }
870
871
872 \f
873 /* UPDATESTARTUPTTY 
874   
875   Set startup TTY and X DISPLAY variables to the values of this
876   session.  This command is useful to pull future pinentries to
877   another screen.  It is only required because there is no way in the
878   ssh-agent protocol to convey this information.  */
879 static int
880 cmd_updatestartuptty (assuan_context_t ctx, char *line)
881 {
882   ctrl_t ctrl = assuan_get_pointer (ctx);
883
884   xfree (opt.startup_display); opt.startup_display = NULL;
885   xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
886   xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
887   xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
888   xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
889
890   if (ctrl->display)
891     opt.startup_display = xtrystrdup (ctrl->display);
892   if (ctrl->ttyname)
893     opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
894   if (ctrl->ttytype)
895     opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
896   if (ctrl->lc_ctype) 
897     opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
898   if (ctrl->lc_messages)
899     opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
900
901   return 0;
902 }
903
904
905 \f
906 static int
907 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
908 {
909   ctrl_t ctrl = assuan_get_pointer (ctx);
910
911   if (!strcmp (key, "display"))
912     {
913       if (ctrl->display)
914         free (ctrl->display);
915       ctrl->display = strdup (value);
916       if (!ctrl->display)
917         return ASSUAN_Out_Of_Core;
918     }
919   else if (!strcmp (key, "ttyname"))
920     {
921       if (!opt.keep_tty)
922         {
923           if (ctrl->ttyname)
924             free (ctrl->ttyname);
925           ctrl->ttyname = strdup (value);
926           if (!ctrl->ttyname)
927             return ASSUAN_Out_Of_Core;
928         }
929     }
930   else if (!strcmp (key, "ttytype"))
931     {
932       if (!opt.keep_tty)
933         {
934           if (ctrl->ttytype)
935             free (ctrl->ttytype);
936           ctrl->ttytype = strdup (value);
937           if (!ctrl->ttytype)
938             return ASSUAN_Out_Of_Core;
939         }
940     }
941   else if (!strcmp (key, "lc-ctype"))
942     {
943       if (ctrl->lc_ctype)
944         free (ctrl->lc_ctype);
945       ctrl->lc_ctype = strdup (value);
946       if (!ctrl->lc_ctype)
947         return ASSUAN_Out_Of_Core;
948     }
949   else if (!strcmp (key, "lc-messages"))
950     {
951       if (ctrl->lc_messages)
952         free (ctrl->lc_messages);
953       ctrl->lc_messages = strdup (value);
954       if (!ctrl->lc_messages)
955         return ASSUAN_Out_Of_Core;
956     }
957   else if (!strcmp (key, "use-cache-for-signing"))
958     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
959   else
960     return ASSUAN_Invalid_Option;
961
962   return 0;
963 }
964
965 \f
966 /* Tell the assuan library about our commands */
967 static int
968 register_commands (ASSUAN_CONTEXT ctx)
969 {
970   static struct {
971     const char *name;
972     int (*handler)(ASSUAN_CONTEXT, char *line);
973   } table[] = {
974     { "ISTRUSTED",      cmd_istrusted },
975     { "HAVEKEY",        cmd_havekey },
976     { "SIGKEY",         cmd_sigkey },
977     { "SETKEY",         cmd_sigkey },
978     { "SETKEYDESC",     cmd_setkeydesc },
979     { "SETHASH",        cmd_sethash },
980     { "PKSIGN",         cmd_pksign },
981     { "PKDECRYPT",      cmd_pkdecrypt },
982     { "GENKEY",         cmd_genkey },
983     { "READKEY",        cmd_readkey },
984     { "GET_PASSPHRASE", cmd_get_passphrase },
985     { "PRESET_PASSPHRASE", cmd_preset_passphrase },
986     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
987     { "GET_CONFIRMATION", cmd_get_confirmation },
988     { "LISTTRUSTED",    cmd_listtrusted },
989     { "MARKTRUSTED",    cmd_marktrusted },
990     { "LEARN",          cmd_learn },
991     { "PASSWD",         cmd_passwd },
992     { "INPUT",          NULL }, 
993     { "OUTPUT",         NULL }, 
994     { "SCD",            cmd_scd },
995     { "UPDATESTARTUPTTY",  cmd_updatestartuptty },
996     { NULL }
997   };
998   int i, rc;
999
1000   for (i=0; table[i].name; i++)
1001     {
1002       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1003       if (rc)
1004         return rc;
1005     } 
1006   assuan_register_reset_notify (ctx, reset_notify);
1007   assuan_register_option_handler (ctx, option_handler);
1008   return 0;
1009 }
1010
1011
1012 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
1013    piper server, otherwise it is a regular server */
1014 void
1015 start_command_handler (int listen_fd, int fd)
1016 {
1017   int rc;
1018   ASSUAN_CONTEXT ctx;
1019   struct server_control_s ctrl;
1020
1021   memset (&ctrl, 0, sizeof ctrl);
1022   agent_init_default_ctrl (&ctrl);
1023   
1024   if (listen_fd == -1 && fd == -1)
1025     {
1026       int filedes[2];
1027
1028       filedes[0] = 0;
1029       filedes[1] = 1;
1030       rc = assuan_init_pipe_server (&ctx, filedes);
1031     }
1032   else if (listen_fd != -1)
1033     {
1034       rc = assuan_init_socket_server (&ctx, listen_fd);
1035     }
1036   else 
1037     {
1038       rc = assuan_init_connected_socket_server (&ctx, fd);
1039       ctrl.connection_fd = fd;
1040     }
1041   if (rc)
1042     {
1043       log_error ("failed to initialize the server: %s\n",
1044                  assuan_strerror(rc));
1045       agent_exit (2);
1046     }
1047   rc = register_commands (ctx);
1048   if (rc)
1049     {
1050       log_error ("failed to register commands with Assuan: %s\n",
1051                  assuan_strerror(rc));
1052       agent_exit (2);
1053     }
1054
1055   assuan_set_pointer (ctx, &ctrl);
1056   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1057   ctrl.server_local->assuan_ctx = ctx;
1058   ctrl.server_local->message_fd = -1;
1059   ctrl.server_local->use_cache_for_signing = 1;
1060   ctrl.digest.raw_value = 0;
1061
1062   if (DBG_ASSUAN)
1063     assuan_set_log_stream (ctx, log_get_stream ());
1064
1065   for (;;)
1066     {
1067       rc = assuan_accept (ctx);
1068       if (rc == -1)
1069         {
1070           break;
1071         }
1072       else if (rc)
1073         {
1074           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1075           break;
1076         }
1077       
1078       rc = assuan_process (ctx);
1079       if (rc)
1080         {
1081           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1082           continue;
1083         }
1084     }
1085
1086   /* Reset the SCD if needed. */
1087   agent_reset_scd (&ctrl);
1088
1089   /* Reset the pinentry (in case of popup messages). */
1090   agent_reset_query (&ctrl);
1091
1092   assuan_deinit_server (ctx);
1093   if (ctrl.display)
1094     free (ctrl.display);
1095   if (ctrl.ttyname)
1096     free (ctrl.ttyname);
1097   if (ctrl.ttytype)
1098     free (ctrl.ttytype);
1099   if (ctrl.lc_ctype)
1100     free (ctrl.lc_ctype);
1101   if (ctrl.lc_messages)
1102     free (ctrl.lc_messages);
1103   xfree (ctrl.server_local);
1104 }
1105