Take advantage of newer gpg-error features.
[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, gpg_error (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 out_of_core ();
107   ae = assuan_send_data (ctx, p, n);
108   memset (p, 0, n);
109   xfree (p);
110   return ae;
111 }
112
113
114 static void
115 reset_notify (assuan_context_t 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_t 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 (GPG_ERR_ASS_PARAMETER, "invalid hexstring");
200   if ((n&1))
201     return set_error (GPG_ERR_ASS_PARAMETER, "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_t 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 (GPG_ERR_ASS_PARAMETER, "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_t 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 (GPG_ERR_ASS_PARAMETER, "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 || gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
259     return rc;
260   else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
261     return gpg_error (GPG_ERR_NOT_TRUSTED);
262   else
263     {
264       log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
265       return rc;
266     }
267 }
268
269 /* LISTTRUSTED 
270
271    List all entries from the trustlist */
272 static int
273 cmd_listtrusted (assuan_context_t 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 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_t 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 (GPG_ERR_ASS_PARAMETER, "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 (GPG_ERR_ASS_PARAMETER, "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 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_t 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 gpg_error (GPG_ERR_NO_SECKEY);
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_t 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 (GPG_ERR_ASS_PARAMETER, "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 out_of_core ();
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_t 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 (GPG_ERR_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 (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
438   if (n > MAX_DIGEST_LEN)
439     return set_error (GPG_ERR_ASS_PARAMETER, "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_t 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 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_t 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 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_t 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 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_syserror ();
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           xfree (buf);
595         }
596       gcry_sexp_release (s_pkey);
597     }
598
599   if (rc)
600     log_error ("command readkey failed: %s\n", gpg_strerror (rc));
601   return rc;
602 }
603
604
605
606
607
608 \f
609 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
610
611    This function is usually used to ask for a passphrase to be used
612    for conventional encryption, but may also be used by programs which
613    need specal handling of passphrases.  This command uses a syntax
614    which helps clients to use the agent with minimum effort.  The
615    agent either returns with an error or with a OK followed by the hex
616    encoded passphrase.  Note that the length of the strings is
617    implicitly limited by the maximum length of a command.
618 */
619
620 static int
621 cmd_get_passphrase (assuan_context_t ctx, char *line)
622 {
623   ctrl_t ctrl = assuan_get_pointer (ctx);
624   int rc;
625   const char *pw;
626   char *response;
627   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
628   char *p;
629   void *cache_marker;
630
631   /* parse the stuff */
632   for (p=line; *p == ' '; p++)
633     ;
634   cacheid = p;
635   p = strchr (cacheid, ' ');
636   if (p)
637     {
638       *p++ = 0;
639       while (*p == ' ')
640         p++;
641       errtext = p;
642       p = strchr (errtext, ' ');
643       if (p)
644         {
645           *p++ = 0;
646           while (*p == ' ')
647             p++;
648           prompt = p;
649           p = strchr (prompt, ' ');
650           if (p)
651             {
652               *p++ = 0;
653               while (*p == ' ')
654                 p++;
655               desc = p;
656               p = strchr (desc, ' ');
657               if (p)
658                 *p = 0; /* ignore garbage */
659             }
660         }
661     }
662   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
663     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
664   if (!desc)
665     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
666
667   if (!strcmp (cacheid, "X"))
668     cacheid = NULL;
669   if (!strcmp (errtext, "X"))
670     errtext = NULL;
671   if (!strcmp (prompt, "X"))
672     prompt = NULL;
673   if (!strcmp (desc, "X"))
674     desc = NULL;
675
676   /* Note: we store the hexified versions in the cache. */
677   pw = cacheid ? agent_get_cache (cacheid, CACHE_MODE_NORMAL, &cache_marker)
678                : NULL;
679   if (pw)
680     {
681       assuan_begin_confidential (ctx);
682       rc = assuan_set_okay_line (ctx, pw);
683       agent_unlock_cache_entry (&cache_marker);
684     }
685   else
686     {
687       /* Note, that we only need to replace the + characters and
688          should leave the other escaping in place because the escaped
689          string is send verbatim to the pinentry which does the
690          unescaping (but not the + replacing) */
691       if (errtext)
692         plus_to_blank (errtext);
693       if (prompt)
694         plus_to_blank (prompt);
695       if (desc)
696         plus_to_blank (desc);
697
698       rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
699       if (!rc)
700         {
701           if (cacheid)
702             agent_put_cache (cacheid, CACHE_MODE_USER, response, 0);
703           assuan_begin_confidential (ctx);
704           rc = assuan_set_okay_line (ctx, response);
705           xfree (response);
706         }
707     }
708
709   if (rc)
710     log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
711   return rc;
712 }
713
714
715 /* CLEAR_PASSPHRASE <cache_id>
716
717    may be used to invalidate the cache entry for a passphrase.  The
718    function returns with OK even when there is no cached passphrase.
719 */
720
721 static int
722 cmd_clear_passphrase (assuan_context_t ctx, char *line)
723 {
724   char *cacheid = NULL;
725   char *p;
726
727   /* parse the stuff */
728   for (p=line; *p == ' '; p++)
729     ;
730   cacheid = p;
731   p = strchr (cacheid, ' ');
732   if (p)
733     *p = 0; /* ignore garbage */
734   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
735     return set_error (GPG_ERR_ASS_PARAMETER, "invalid length of cacheID");
736
737   agent_put_cache (cacheid, CACHE_MODE_USER, NULL, 0);
738   return 0;
739 }
740
741
742 /* GET_CONFIRMATION <description>
743
744    This command may be used to ask for a simple confirmation.
745    DESCRIPTION is displayed along with a Okay and Cancel button.  This
746    command uses a syntax which helps clients to use the agent with
747    minimum effort.  The agent either returns with an error or with a
748    OK.  Note, that the length of DESCRIPTION is implicitly limited by
749    the maximum length of a command. DESCRIPTION should not contain
750    any spaces, those must be encoded either percent escaped or simply
751    as '+'.
752 */
753
754 static int
755 cmd_get_confirmation (assuan_context_t ctx, char *line)
756 {
757   ctrl_t ctrl = assuan_get_pointer (ctx);
758   int rc;
759   char *desc = NULL;
760   char *p;
761
762   /* parse the stuff */
763   for (p=line; *p == ' '; p++)
764     ;
765   desc = p;
766   p = strchr (desc, ' ');
767   if (p)
768     *p = 0; /* We ignore any garbage -may be later used for other args. */
769
770   if (!desc || !*desc)
771     return set_error (GPG_ERR_ASS_PARAMETER, "no description given");
772
773   if (!strcmp (desc, "X"))
774     desc = NULL;
775
776   /* Note, that we only need to replace the + characters and should
777      leave the other escaping in place because the escaped string is
778      send verbatim to the pinentry which does the unescaping (but not
779      the + replacing) */
780   if (desc)
781     plus_to_blank (desc);
782
783   rc = agent_get_confirmation (ctrl, desc, NULL, NULL);
784   if (rc)
785     log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
786   return rc;
787 }
788
789
790 \f
791 /* LEARN [--send]
792
793    Learn something about the currently inserted smartcard.  With
794    --send the new certificates are send back.  */
795 static int
796 cmd_learn (assuan_context_t ctx, char *line)
797 {
798   ctrl_t ctrl = assuan_get_pointer (ctx);
799   int rc;
800
801   rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
802   if (rc)
803     log_error ("command learn failed: %s\n", gpg_strerror (rc));
804   return rc;
805 }
806
807
808 \f
809 /* PASSWD <hexstring_with_keygrip>
810   
811    Change the passphrase/PID for the key identified by keygrip in LINE. */
812 static int
813 cmd_passwd (assuan_context_t ctx, char *line)
814 {
815   ctrl_t ctrl = assuan_get_pointer (ctx);
816   int rc;
817   unsigned char grip[20];
818   gcry_sexp_t s_skey = NULL;
819   unsigned char *shadow_info = NULL;
820
821   rc = parse_keygrip (ctx, line, grip);
822   if (rc)
823     return rc; /* we can't jump to leave because this is already an
824                   Assuan error code. */
825
826   rc = agent_key_from_file (ctrl, ctrl->server_local->keydesc,
827                             grip, &shadow_info, CACHE_MODE_IGNORE, &s_skey);
828   if (rc)
829     ;
830   else if (!s_skey)
831     {
832       log_error ("changing a smartcard PIN is not yet supported\n");
833       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
834     }
835   else
836     rc = agent_protect_and_store (ctrl, s_skey);
837
838   xfree (ctrl->server_local->keydesc);
839   ctrl->server_local->keydesc = NULL;
840   gcry_sexp_release (s_skey);
841   xfree (shadow_info);
842   if (rc)
843     log_error ("command passwd failed: %s\n", gpg_strerror (rc));
844   return rc;
845 }
846
847 /* PRESET_PASSPHRASE <hexstring_with_keygrip> <timeout> <hexstring>
848   
849    Set the cached passphrase/PIN for the key identified by the keygrip
850    to passwd for the given time, where -1 means infinite and 0 means
851    the default (currently only a timeout of -1 is allowed, which means
852    to never expire it).  If passwd is not provided, ask for it via the
853    pinentry module.  */
854 static int
855 cmd_preset_passphrase (assuan_context_t ctx, char *line)
856 {
857   int rc;
858   unsigned char grip[20];
859   char *grip_clear = NULL;
860   char *passphrase = NULL;
861   int ttl;
862   size_t len;
863
864   if (!opt.allow_preset_passphrase)
865     return gpg_error (GPG_ERR_NOT_SUPPORTED);
866
867   rc = parse_keygrip (ctx, line, grip);
868   if (rc)
869     return rc;
870
871   /* FIXME: parse_keygrip should return a tail pointer.  */
872   grip_clear = line;
873   while (*line && (*line != ' ' && *line != '\t'))
874     line++;
875   if (!*line)
876     return gpg_error (GPG_ERR_MISSING_VALUE);
877   *line = '\0';
878   line++;
879   while (*line && (*line == ' ' || *line == '\t'))
880     line++;
881   
882   /* Currently, only infinite timeouts are allowed.  */
883   ttl = -1;
884   if (line[0] != '-' || line[1] != '1')
885     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
886   line++;
887   line++;
888   while (!(*line != ' ' && *line != '\t'))
889     line++;
890
891   /* Syntax check the hexstring.  */
892   rc = parse_hexstring (ctx, line, &len);
893   if (rc)
894     return rc;
895   line[len] = '\0';
896
897   /* If there is a passphrase, use it.  Currently, a passphrase is
898      required.  */
899   if (*line)
900     passphrase = line;
901   else
902     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
903
904   rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
905
906   if (rc)
907     log_error ("command preset_passwd failed: %s\n", gpg_strerror (rc));
908
909   return rc;
910 }
911
912 \f
913 /* SCD <commands to pass to the scdaemon>
914   
915    This is a general quote command to redirect everything to the
916    SCDAEMON. */
917 static int
918 cmd_scd (assuan_context_t ctx, char *line)
919 {
920   ctrl_t ctrl = assuan_get_pointer (ctx);
921   int rc;
922
923   rc = divert_generic_cmd (ctrl, line, ctx);
924
925   return rc;
926 }
927
928
929 \f
930 /* GETVAL <key>
931
932    Return the value for KEY from the special environment as created by
933    PUTVAL.
934  */
935 static int
936 cmd_getval (assuan_context_t ctx, char *line)
937 {
938   int rc = 0;
939   char *key = NULL;
940   char *p;
941   struct putval_item_s *vl;
942
943   for (p=line; *p == ' '; p++)
944     ;
945   key = p;
946   p = strchr (key, ' ');
947   if (p)
948     {
949       *p++ = 0; 
950       for (; *p == ' '; p++)
951         ;
952       if (*p)
953         return set_error (GPG_ERR_ASS_PARAMETER, "too many arguments");
954     }
955   if (!key || !*key)
956     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
957
958
959   for (vl=putval_list; vl; vl = vl->next)
960     if ( !strcmp (vl->d, key) )
961       break;
962
963   if (vl) /* Got an entry. */
964     rc = assuan_send_data (ctx, vl->d+vl->off, vl->len);
965   else
966     return gpg_error (GPG_ERR_NO_DATA);
967
968   if (rc)
969     log_error ("command getval failed: %s\n", gpg_strerror (rc));
970   return rc;
971 }
972
973
974 /* PUTVAL <key> [<percent_escaped_value>]
975
976    The gpg-agent maintains a kind of environment which may be used to
977    store key/value pairs in it, so that they can be retrieved later.
978    This may be used by helper daemons to daemonize themself on
979    invocation and register them with gpg-agent.  Callers of the
980    daemon's service may now first try connect to get the information
981    for that service from gpg-agent through the GETVAL command and then
982    try to connect to that daemon.  Only if that fails they may start
983    an own instance of the service daemon. 
984
985    KEY is an an arbitrary symbol with the same syntax rules as keys
986    for shell environment variables.  PERCENT_ESCAPED_VALUE is the
987    corresponsing value; they should be similar to the values of
988    envronment variables but gpg-agent does not enforce any
989    restrictions.  If that value is not given any value under that KEY
990    is removed from this special environment.
991 */
992 static int
993 cmd_putval (assuan_context_t ctx, char *line)
994 {
995   int rc = 0;
996   char *key = NULL;
997   char *value = NULL;
998   size_t valuelen = 0;
999   char *p;
1000   struct putval_item_s *vl, *vlprev;
1001
1002   for (p=line; *p == ' '; p++)
1003     ;
1004   key = p;
1005   p = strchr (key, ' ');
1006   if (p)
1007     {
1008       *p++ = 0; 
1009       for (; *p == ' '; p++)
1010         ;
1011       if (*p)
1012         {
1013           value = p;
1014           p = strchr (value, ' ');
1015           if (p)
1016             *p = 0;
1017           valuelen = percent_plus_unescape (value);
1018         }
1019     }
1020   if (!key || !*key)
1021     return set_error (GPG_ERR_ASS_PARAMETER, "no key given");
1022
1023
1024   for (vl=putval_list,vlprev=NULL; vl; vlprev=vl, vl = vl->next)
1025     if ( !strcmp (vl->d, key) )
1026       break;
1027
1028   if (vl) /* Delete old entry. */
1029     {
1030       if (vlprev)
1031         vlprev->next = vl->next;
1032       else
1033         putval_list = vl->next;
1034       xfree (vl);
1035     }
1036
1037   if (valuelen) /* Add entry. */  
1038     {
1039       vl = xtrymalloc (sizeof *vl + strlen (key) + valuelen);
1040       if (!vl)
1041         rc = gpg_error_from_syserror ();
1042       else
1043         {
1044           vl->len = valuelen;
1045           vl->off = strlen (key) + 1;
1046           strcpy (vl->d, key);
1047           memcpy (vl->d + vl->off, value, valuelen);
1048           vl->next = putval_list;
1049           putval_list = vl;
1050         }
1051     }
1052
1053   if (rc)
1054     log_error ("command putval failed: %s\n", gpg_strerror (rc));
1055   return rc;
1056 }
1057
1058
1059
1060 \f
1061 /* UPDATESTARTUPTTY 
1062   
1063   Set startup TTY and X DISPLAY variables to the values of this
1064   session.  This command is useful to pull future pinentries to
1065   another screen.  It is only required because there is no way in the
1066   ssh-agent protocol to convey this information.  */
1067 static int
1068 cmd_updatestartuptty (assuan_context_t ctx, char *line)
1069 {
1070   ctrl_t ctrl = assuan_get_pointer (ctx);
1071
1072   xfree (opt.startup_display); opt.startup_display = NULL;
1073   xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
1074   xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
1075   xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
1076   xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
1077
1078   if (ctrl->display)
1079     opt.startup_display = xtrystrdup (ctrl->display);
1080   if (ctrl->ttyname)
1081     opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
1082   if (ctrl->ttytype)
1083     opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
1084   if (ctrl->lc_ctype) 
1085     opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
1086   if (ctrl->lc_messages)
1087     opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
1088
1089   return 0;
1090 }
1091
1092
1093 \f
1094 static int
1095 option_handler (assuan_context_t ctx, const char *key, const char *value)
1096 {
1097   ctrl_t ctrl = assuan_get_pointer (ctx);
1098
1099   if (!strcmp (key, "display"))
1100     {
1101       if (ctrl->display)
1102         free (ctrl->display);
1103       ctrl->display = strdup (value);
1104       if (!ctrl->display)
1105         return out_of_core ();
1106     }
1107   else if (!strcmp (key, "ttyname"))
1108     {
1109       if (!opt.keep_tty)
1110         {
1111           if (ctrl->ttyname)
1112             free (ctrl->ttyname);
1113           ctrl->ttyname = strdup (value);
1114           if (!ctrl->ttyname)
1115             return out_of_core ();
1116         }
1117     }
1118   else if (!strcmp (key, "ttytype"))
1119     {
1120       if (!opt.keep_tty)
1121         {
1122           if (ctrl->ttytype)
1123             free (ctrl->ttytype);
1124           ctrl->ttytype = strdup (value);
1125           if (!ctrl->ttytype)
1126             return out_of_core ();
1127         }
1128     }
1129   else if (!strcmp (key, "lc-ctype"))
1130     {
1131       if (ctrl->lc_ctype)
1132         free (ctrl->lc_ctype);
1133       ctrl->lc_ctype = strdup (value);
1134       if (!ctrl->lc_ctype)
1135         return out_of_core ();
1136     }
1137   else if (!strcmp (key, "lc-messages"))
1138     {
1139       if (ctrl->lc_messages)
1140         free (ctrl->lc_messages);
1141       ctrl->lc_messages = strdup (value);
1142       if (!ctrl->lc_messages)
1143         return out_of_core ();
1144     }
1145   else if (!strcmp (key, "use-cache-for-signing"))
1146     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
1147   else
1148     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
1149
1150   return 0;
1151 }
1152
1153 \f
1154 /* Tell the assuan library about our commands */
1155 static int
1156 register_commands (assuan_context_t ctx)
1157 {
1158   static struct {
1159     const char *name;
1160     int (*handler)(assuan_context_t, char *line);
1161   } table[] = {
1162     { "ISTRUSTED",      cmd_istrusted },
1163     { "HAVEKEY",        cmd_havekey },
1164     { "SIGKEY",         cmd_sigkey },
1165     { "SETKEY",         cmd_sigkey },
1166     { "SETKEYDESC",     cmd_setkeydesc },
1167     { "SETHASH",        cmd_sethash },
1168     { "PKSIGN",         cmd_pksign },
1169     { "PKDECRYPT",      cmd_pkdecrypt },
1170     { "GENKEY",         cmd_genkey },
1171     { "READKEY",        cmd_readkey },
1172     { "GET_PASSPHRASE", cmd_get_passphrase },
1173     { "PRESET_PASSPHRASE", cmd_preset_passphrase },
1174     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
1175     { "GET_CONFIRMATION", cmd_get_confirmation },
1176     { "LISTTRUSTED",    cmd_listtrusted },
1177     { "MARKTRUSTED",    cmd_marktrusted },
1178     { "LEARN",          cmd_learn },
1179     { "PASSWD",         cmd_passwd },
1180     { "INPUT",          NULL }, 
1181     { "OUTPUT",         NULL }, 
1182     { "SCD",            cmd_scd },
1183     { "GETVAL",         cmd_getval },
1184     { "PUTVAL",         cmd_putval },
1185     { "UPDATESTARTUPTTY",  cmd_updatestartuptty },
1186     { NULL }
1187   };
1188   int i, rc;
1189
1190   for (i=0; table[i].name; i++)
1191     {
1192       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
1193       if (rc)
1194         return rc;
1195     } 
1196   assuan_register_reset_notify (ctx, reset_notify);
1197   assuan_register_option_handler (ctx, option_handler);
1198   return 0;
1199 }
1200
1201
1202 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
1203    piper server, otherwise it is a regular server */
1204 void
1205 start_command_handler (int listen_fd, int fd)
1206 {
1207   int rc;
1208   assuan_context_t ctx;
1209   struct server_control_s ctrl;
1210
1211   memset (&ctrl, 0, sizeof ctrl);
1212   agent_init_default_ctrl (&ctrl);
1213   
1214   if (listen_fd == -1 && fd == -1)
1215     {
1216       int filedes[2];
1217
1218       filedes[0] = 0;
1219       filedes[1] = 1;
1220       rc = assuan_init_pipe_server (&ctx, filedes);
1221     }
1222   else if (listen_fd != -1)
1223     {
1224       rc = assuan_init_socket_server_ext (&ctx, listen_fd, 0);
1225     }
1226   else 
1227     {
1228       rc = assuan_init_socket_server_ext (&ctx, fd, 2);
1229       ctrl.connection_fd = fd;
1230     }
1231   if (rc)
1232     {
1233       log_error ("failed to initialize the server: %s\n",
1234                  gpg_strerror(rc));
1235       agent_exit (2);
1236     }
1237   rc = register_commands (ctx);
1238   if (rc)
1239     {
1240       log_error ("failed to register commands with Assuan: %s\n",
1241                  gpg_strerror(rc));
1242       agent_exit (2);
1243     }
1244
1245   assuan_set_pointer (ctx, &ctrl);
1246   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
1247   ctrl.server_local->assuan_ctx = ctx;
1248   ctrl.server_local->message_fd = -1;
1249   ctrl.server_local->use_cache_for_signing = 1;
1250   ctrl.digest.raw_value = 0;
1251
1252   if (DBG_ASSUAN)
1253     assuan_set_log_stream (ctx, log_get_stream ());
1254
1255   for (;;)
1256     {
1257       rc = assuan_accept (ctx);
1258       if (rc == -1)
1259         {
1260           break;
1261         }
1262       else if (rc)
1263         {
1264           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
1265           break;
1266         }
1267       
1268       rc = assuan_process (ctx);
1269       if (rc)
1270         {
1271           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
1272           continue;
1273         }
1274     }
1275
1276   /* Reset the SCD if needed. */
1277   agent_reset_scd (&ctrl);
1278
1279   /* Reset the pinentry (in case of popup messages). */
1280   agent_reset_query (&ctrl);
1281
1282   assuan_deinit_server (ctx);
1283   if (ctrl.display)
1284     free (ctrl.display);
1285   if (ctrl.ttyname)
1286     free (ctrl.ttyname);
1287   if (ctrl.ttytype)
1288     free (ctrl.ttytype);
1289   if (ctrl.lc_ctype)
1290     free (ctrl.lc_ctype);
1291   if (ctrl.lc_messages)
1292     free (ctrl.lc_messages);
1293   xfree (ctrl.server_local);
1294 }
1295