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