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