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