* command-ssh.c (get_passphrase): Removed.
[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=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   int ignore_cache = 0;
408   ctrl_t ctrl = assuan_get_pointer (ctx);
409   membuf_t outbuf;
410
411   if (opt.ignore_cache_for_signing)
412     ignore_cache = 1;
413   else if (!ctrl->server_local->use_cache_for_signing)
414     ignore_cache = 1;
415
416   init_membuf (&outbuf, 512);
417
418   rc = agent_pksign (ctrl, ctrl->server_local->keydesc,
419                      &outbuf, ignore_cache);
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, 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_marker) : NULL;
627   if (pw)
628     {
629       assuan_begin_confidential (ctx);
630       rc = assuan_set_okay_line (ctx, pw);
631       agent_unlock_cache_entry (&cache_marker);
632     }
633   else
634     {
635       /* Note, that we only need to replace the + characters and
636          should leave the other escaping in place because the escaped
637          string is send verbatim to the pinentry which does the
638          unescaping (but not the + replacing) */
639       if (errtext)
640         plus_to_blank (errtext);
641       if (prompt)
642         plus_to_blank (prompt);
643       if (desc)
644         plus_to_blank (desc);
645
646       rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
647       if (!rc)
648         {
649           if (cacheid)
650             agent_put_cache (cacheid, response, 0);
651           assuan_begin_confidential (ctx);
652           rc = assuan_set_okay_line (ctx, response);
653           xfree (response);
654         }
655     }
656
657   if (rc)
658     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
659   return map_to_assuan_status (rc);
660 }
661
662
663 /* CLEAR_PASSPHRASE <cache_id>
664
665    may be used to invalidate the cache entry for a passphrase.  The
666    function returns with OK even when there is no cached passphrase.
667 */
668
669 static int
670 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
671 {
672   char *cacheid = NULL;
673   char *p;
674
675   /* parse the stuff */
676   for (p=line; *p == ' '; p++)
677     ;
678   cacheid = p;
679   p = strchr (cacheid, ' ');
680   if (p)
681     *p = 0; /* ignore garbage */
682   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
683     return set_error (Parameter_Error, "invalid length of cacheID");
684
685   agent_put_cache (cacheid, NULL, 0);
686   return 0;
687 }
688
689
690 /* GET_CONFIRMATION <description>
691
692    This command may be used to ask for a simple confirmation.
693    DESCRIPTION is displayed along with a Okay and Cancel button.  This
694    command uses a syntax which helps clients to use the agent with
695    minimum effort.  The agent either returns with an error or with a
696    OK.  Note, that the length of DESCRIPTION is implicitly limited by
697    the maximum length of a command. DESCRIPTION should not contain
698    any spaces, those must be encoded either percent escaped or simply
699    as '+'.
700 */
701
702 static int
703 cmd_get_confirmation (ASSUAN_CONTEXT ctx, char *line)
704 {
705   ctrl_t ctrl = assuan_get_pointer (ctx);
706   int rc;
707   char *desc = NULL;
708   char *p;
709
710   /* parse the stuff */
711   for (p=line; *p == ' '; p++)
712     ;
713   desc = p;
714   p = strchr (desc, ' ');
715   if (p)
716     *p = 0; /* We ignore any garbage -may be later used for other args. */
717
718   if (!desc || !*desc)
719     return set_error (Parameter_Error, "no description given");
720
721   if (!strcmp (desc, "X"))
722     desc = NULL;
723
724   /* Note, that we only need to replace the + characters and should
725      leave the other escaping in place because the escaped string is
726      send verbatim to the pinentry which does the unescaping (but not
727      the + replacing) */
728   if (desc)
729     plus_to_blank (desc);
730
731   rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
732   if (rc)
733     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
734   return map_to_assuan_status (rc);
735 }
736
737
738 \f
739 /* LEARN [--send]
740
741    Learn something about the currently inserted smartcard.  With
742    --send the new certificates are send back.  */
743 static int
744 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
745 {
746   ctrl_t ctrl = assuan_get_pointer (ctx);
747   int rc;
748
749   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
750   if (rc)
751     log_error ("command learn failed: %s\n", gpg_strerror (rc));
752   return map_to_assuan_status (rc);
753 }
754
755
756 \f
757 /* PASSWD <hexstring_with_keygrip>
758   
759    Change the passphrase/PID for the key identified by keygrip in LINE. */
760 static int
761 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
762 {
763   ctrl_t ctrl = assuan_get_pointer (ctx);
764   int rc;
765   unsigned char grip[20];
766   gcry_sexp_t s_skey = NULL;
767   unsigned char *shadow_info = NULL;
768
769   rc = parse_keygrip (ctx, line, grip);
770   if (rc)
771     return rc; /* we can't jump to leave because this is already an
772                   Assuan error code. */
773
774   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
775                             grip, &shadow_info, 1, &s_skey);
776   if (rc)
777     ;
778   else if (!s_skey)
779     {
780       log_error ("changing a smartcard PIN is not yet supported\n");
781       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
782     }
783   else
784     rc = agent_protect_and_store (ctrl, s_skey);
785
786   xfree (ctrl->server_local->keydesc);
787   ctrl->server_local->keydesc = NULL;
788   gcry_sexp_release (s_skey);
789   xfree (shadow_info);
790   if (rc)
791     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
792   return map_to_assuan_status (rc);
793 }
794
795 /* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <passwd>
796   
797    Set the cached passphrase/PIN for the key identified by the keygrip
798    to passwd for the given time, where -1 means infinite and 0 means
799    the default (currently only a timeout of -1 is allowed, which means
800    to never expire it).  If passwd is not provided, ask for it via the
801    pinentry module.  */
802 static int
803 cmd_preset_passphrase (ASSUAN_CONTEXT ctx, char *line)
804 {
805   int rc;
806   unsigned char grip[20];
807   char *grip_clear = NULL;
808   char *passphrase = NULL;
809   int ttl;
810
811   if (!opt.allow_preset_passphrase)
812     return gpg_error (GPG_ERR_NOT_SUPPORTED);
813
814   rc = parse_keygrip (ctx, line, grip);
815   if (rc)
816     return rc;
817
818   /* FIXME: parse_keygrip should return a tail pointer.  */
819   grip_clear = line;
820   while (*line && (*line != ' ' && *line != '\t'))
821     line++;
822   if (!*line)
823     return map_to_assuan_status (gpg_error (GPG_ERR_MISSING_VALUE));
824   *line = '\0';
825   line++;
826   while (*line && (*line == ' ' || *line == '\t'))
827     line++;
828   
829   /* Currently, only infinite timeouts are allowed.  */
830   ttl = -1;
831   if (line[0] != '-' || line[1] != '1')
832     return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED));
833   line++;
834   line++;
835   while (!(*line != ' ' && *line != '\t'))
836     line++;
837
838   /* If there is a passphrase, use it.  Currently, a passphrase is
839      required.  */
840   if (*line)
841     passphrase = line;
842   else
843     return map_to_assuan_status (gpg_error (GPG_ERR_NOT_IMPLEMENTED));
844
845   rc = agent_put_cache (grip_clear, passphrase, ttl);
846
847   if (rc)
848     log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc));
849
850   return map_to_assuan_status (rc);
851 }
852
853 \f
854 /* SCD <commands to pass to the scdaemon>
855   
856    This is a general quote command to redirect everything to the
857    SCDAEMON. */
858 static int
859 cmd_scd (ASSUAN_CONTEXT ctx, char *line)
860 {
861   ctrl_t ctrl = assuan_get_pointer (ctx);
862   int rc;
863
864   rc = divert_generic_cmd (ctrl, line, ctx);
865
866   return map_to_assuan_status (rc);
867 }
868
869
870 \f
871 static int
872 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
873 {
874   ctrl_t ctrl = assuan_get_pointer (ctx);
875
876   if (!strcmp (key, "display"))
877     {
878       if (ctrl->display)
879         free (ctrl->display);
880       ctrl->display = strdup (value);
881       if (!ctrl->display)
882         return ASSUAN_Out_Of_Core;
883     }
884   else if (!strcmp (key, "ttyname"))
885     {
886       if (!opt.keep_tty)
887         {
888           if (ctrl->ttyname)
889             free (ctrl->ttyname);
890           ctrl->ttyname = strdup (value);
891           if (!ctrl->ttyname)
892             return ASSUAN_Out_Of_Core;
893         }
894     }
895   else if (!strcmp (key, "ttytype"))
896     {
897       if (!opt.keep_tty)
898         {
899           if (ctrl->ttytype)
900             free (ctrl->ttytype);
901           ctrl->ttytype = strdup (value);
902           if (!ctrl->ttytype)
903             return ASSUAN_Out_Of_Core;
904         }
905     }
906   else if (!strcmp (key, "lc-ctype"))
907     {
908       if (ctrl->lc_ctype)
909         free (ctrl->lc_ctype);
910       ctrl->lc_ctype = strdup (value);
911       if (!ctrl->lc_ctype)
912         return ASSUAN_Out_Of_Core;
913     }
914   else if (!strcmp (key, "lc-messages"))
915     {
916       if (ctrl->lc_messages)
917         free (ctrl->lc_messages);
918       ctrl->lc_messages = strdup (value);
919       if (!ctrl->lc_messages)
920         return ASSUAN_Out_Of_Core;
921     }
922   else if (!strcmp (key, "use-cache-for-signing"))
923     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
924   else
925     return ASSUAN_Invalid_Option;
926
927   return 0;
928 }
929
930 \f
931 /* Tell the assuan library about our commands */
932 static int
933 register_commands (ASSUAN_CONTEXT ctx)
934 {
935   static struct {
936     const char *name;
937     int (*handler)(ASSUAN_CONTEXT, char *line);
938   } table[] = {
939     { "ISTRUSTED",      cmd_istrusted },
940     { "HAVEKEY",        cmd_havekey },
941     { "SIGKEY",         cmd_sigkey },
942     { "SETKEY",         cmd_sigkey },
943     { "SETKEYDESC",     cmd_setkeydesc },
944     { "SETHASH",        cmd_sethash },
945     { "PKSIGN",         cmd_pksign },
946     { "PKDECRYPT",      cmd_pkdecrypt },
947     { "GENKEY",         cmd_genkey },
948     { "READKEY",        cmd_readkey },
949     { "GET_PASSPHRASE", cmd_get_passphrase },
950     { "PRESET_PASSPHRASE", cmd_preset_passphrase },
951     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
952     { "GET_CONFIRMATION", cmd_get_confirmation },
953     { "LISTTRUSTED",    cmd_listtrusted },
954     { "MARKTRUSTED",    cmd_marktrusted },
955     { "LEARN",          cmd_learn },
956     { "PASSWD",         cmd_passwd },
957     { "INPUT",          NULL }, 
958     { "OUTPUT",         NULL }, 
959     { "SCD",            cmd_scd },
960     { NULL }
961   };
962   int i, rc;
963
964   for (i=0; table[i].name; i++)
965     {
966       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
967       if (rc)
968         return rc;
969     } 
970   assuan_register_reset_notify (ctx, reset_notify);
971   assuan_register_option_handler (ctx, option_handler);
972   return 0;
973 }
974
975
976 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
977    piper server, otherwise it is a regular server */
978 void
979 start_command_handler (int listen_fd, int fd)
980 {
981   int rc;
982   ASSUAN_CONTEXT ctx;
983   struct server_control_s ctrl;
984
985   memset (&ctrl, 0, sizeof ctrl);
986   agent_init_default_ctrl (&ctrl);
987   
988   if (listen_fd == -1 && fd == -1)
989     {
990       int filedes[2];
991
992       filedes[0] = 0;
993       filedes[1] = 1;
994       rc = assuan_init_pipe_server (&ctx, filedes);
995     }
996   else if (listen_fd != -1)
997     {
998       rc = assuan_init_socket_server (&ctx, listen_fd);
999     }
1000   else 
1001     {
1002       rc = assuan_init_connected_socket_server (&ctx, fd);
1003       ctrl.connection_fd = fd;
1004     }
1005   if (rc)
1006     {
1007       log_error ("failed to initialize the server: %s\n",
1008                  assuan_strerror(rc));
1009       agent_exit (2);
1010     }
1011   rc = register_commands (ctx);
1012   if (rc)
1013     {
1014       log_error ("failed to register commands with Assuan: %s\n",
1015                  assuan_strerror(rc));
1016       agent_exit (2);
1017     }
1018
1019   assuan_set_pointer (ctx, &ctrl);
1020   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1021   ctrl.server_local->assuan_ctx = ctx;
1022   ctrl.server_local->message_fd = -1;
1023   ctrl.server_local->use_cache_for_signing = 1;
1024   ctrl.digest.raw_value = 0;
1025
1026   if (DBG_ASSUAN)
1027     assuan_set_log_stream (ctx, log_get_stream ());
1028
1029   for (;;)
1030     {
1031       rc = assuan_accept (ctx);
1032       if (rc == -1)
1033         {
1034           break;
1035         }
1036       else if (rc)
1037         {
1038           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
1039           break;
1040         }
1041       
1042       rc = assuan_process (ctx);
1043       if (rc)
1044         {
1045           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
1046           continue;
1047         }
1048     }
1049
1050   /* Reset the SCD if needed. */
1051   agent_reset_scd (&ctrl);
1052
1053   assuan_deinit_server (ctx);
1054   if (ctrl.display)
1055     free (ctrl.display);
1056   if (ctrl.ttyname)
1057     free (ctrl.ttyname);
1058   if (ctrl.ttytype)
1059     free (ctrl.ttytype);
1060   if (ctrl.lc_ctype)
1061     free (ctrl.lc_ctype);
1062   if (ctrl.lc_messages)
1063     free (ctrl.lc_messages);
1064 }
1065