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