* call-scd.c (init_membuf, put_membuf, get_membuf): Removed. We
[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)
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 \f
745 /* SCD <commands to pass to the scdaemon>
746   
747    This is a general quote command to redirect everything to the
748    SCDAEMON. */
749 static int
750 cmd_scd (ASSUAN_CONTEXT ctx, char *line)
751 {
752   ctrl_t ctrl = assuan_get_pointer (ctx);
753   int rc;
754
755   rc = divert_generic_cmd (ctrl, line, ctx);
756
757   return map_to_assuan_status (rc);
758 }
759
760
761 \f
762 static int
763 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
764 {
765   ctrl_t ctrl = assuan_get_pointer (ctx);
766
767   if (!strcmp (key, "display"))
768     {
769       if (ctrl->display)
770         free (ctrl->display);
771       ctrl->display = strdup (value);
772       if (!ctrl->display)
773         return ASSUAN_Out_Of_Core;
774     }
775   else if (!strcmp (key, "ttyname"))
776     {
777       if (!opt.keep_tty)
778         {
779           if (ctrl->ttyname)
780             free (ctrl->ttyname);
781           ctrl->ttyname = strdup (value);
782           if (!ctrl->ttyname)
783             return ASSUAN_Out_Of_Core;
784         }
785     }
786   else if (!strcmp (key, "ttytype"))
787     {
788       if (!opt.keep_tty)
789         {
790           if (ctrl->ttytype)
791             free (ctrl->ttytype);
792           ctrl->ttytype = strdup (value);
793           if (!ctrl->ttytype)
794             return ASSUAN_Out_Of_Core;
795         }
796     }
797   else if (!strcmp (key, "lc-ctype"))
798     {
799       if (ctrl->lc_ctype)
800         free (ctrl->lc_ctype);
801       ctrl->lc_ctype = strdup (value);
802       if (!ctrl->lc_ctype)
803         return ASSUAN_Out_Of_Core;
804     }
805   else if (!strcmp (key, "lc-messages"))
806     {
807       if (ctrl->lc_messages)
808         free (ctrl->lc_messages);
809       ctrl->lc_messages = strdup (value);
810       if (!ctrl->lc_messages)
811         return ASSUAN_Out_Of_Core;
812     }
813   else if (!strcmp (key, "use-cache-for-signing"))
814     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
815   else
816     return ASSUAN_Invalid_Option;
817
818   return 0;
819 }
820
821 \f
822 /* Tell the assuan library about our commands */
823 static int
824 register_commands (ASSUAN_CONTEXT ctx)
825 {
826   static struct {
827     const char *name;
828     int (*handler)(ASSUAN_CONTEXT, char *line);
829   } table[] = {
830     { "ISTRUSTED",      cmd_istrusted },
831     { "HAVEKEY",        cmd_havekey },
832     { "SIGKEY",         cmd_sigkey },
833     { "SETKEY",         cmd_sigkey },
834     { "SETKEYDESC",     cmd_setkeydesc },
835     { "SETHASH",        cmd_sethash },
836     { "PKSIGN",         cmd_pksign },
837     { "PKDECRYPT",      cmd_pkdecrypt },
838     { "GENKEY",         cmd_genkey },
839     { "GET_PASSPHRASE", cmd_get_passphrase },
840     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
841     { "GET_CONFIRMATION", cmd_get_confirmation },
842     { "LISTTRUSTED",    cmd_listtrusted },
843     { "MARKTRUSTED",    cmd_marktrusted },
844     { "LEARN",          cmd_learn },
845     { "PASSWD",         cmd_passwd },
846     { "INPUT",          NULL }, 
847     { "OUTPUT",         NULL }, 
848     { "SCD",            cmd_scd },
849     { NULL }
850   };
851   int i, rc;
852
853   for (i=0; table[i].name; i++)
854     {
855       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
856       if (rc)
857         return rc;
858     } 
859   assuan_register_reset_notify (ctx, reset_notify);
860   assuan_register_option_handler (ctx, option_handler);
861   return 0;
862 }
863
864
865 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
866    piper server, otherwise it is a regular server */
867 void
868 start_command_handler (int listen_fd, int fd)
869 {
870   int rc;
871   ASSUAN_CONTEXT ctx;
872   struct server_control_s ctrl;
873
874   memset (&ctrl, 0, sizeof ctrl);
875   agent_init_default_ctrl (&ctrl);
876   
877   if (listen_fd == -1 && fd == -1)
878     {
879       int filedes[2];
880
881       filedes[0] = 0;
882       filedes[1] = 1;
883       rc = assuan_init_pipe_server (&ctx, filedes);
884     }
885   else if (listen_fd != -1)
886     {
887       rc = assuan_init_socket_server (&ctx, listen_fd);
888     }
889   else 
890     {
891       rc = assuan_init_connected_socket_server (&ctx, fd);
892       ctrl.connection_fd = fd;
893     }
894   if (rc)
895     {
896       log_error ("failed to initialize the server: %s\n",
897                  assuan_strerror(rc));
898       agent_exit (2);
899     }
900   rc = register_commands (ctx);
901   if (rc)
902     {
903       log_error ("failed to register commands with Assuan: %s\n",
904                  assuan_strerror(rc));
905       agent_exit (2);
906     }
907
908   assuan_set_pointer (ctx, &ctrl);
909   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
910   ctrl.server_local->assuan_ctx = ctx;
911   ctrl.server_local->message_fd = -1;
912   ctrl.server_local->use_cache_for_signing = 1;
913   ctrl.digest.raw_value = 0;
914
915   if (DBG_ASSUAN)
916     assuan_set_log_stream (ctx, log_get_stream ());
917
918   for (;;)
919     {
920       rc = assuan_accept (ctx);
921       if (rc == -1)
922         {
923           break;
924         }
925       else if (rc)
926         {
927           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
928           break;
929         }
930       
931       rc = assuan_process (ctx);
932       if (rc)
933         {
934           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
935           continue;
936         }
937     }
938
939   /* Reset the SCD if needed. */
940   agent_reset_scd (&ctrl);
941
942   assuan_deinit_server (ctx);
943   if (ctrl.display)
944     free (ctrl.display);
945   if (ctrl.ttyname)
946     free (ctrl.ttyname);
947   if (ctrl.ttytype)
948     free (ctrl.ttytype);
949   if (ctrl.lc_ctype)
950     free (ctrl.lc_ctype);
951   if (ctrl.lc_messages)
952     free (ctrl.lc_messages);
953 }
954