Make use of libgpg-error
[gnupg.git] / agent / command.c
1 /* command.c - gpg-agent command handler
2  *      Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /* FIXME: we should not use the default assuan buffering but setup
22    some buffering in secure mempory to protect session keys etc. */
23
24 #include <config.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31
32 #include <assuan.h>
33
34 #include "agent.h"
35
36 /* maximum allowed size of the inquired ciphertext */
37 #define MAXLEN_CIPHERTEXT 4096
38 /* maximum allowed size of the key parameters */
39 #define MAXLEN_KEYPARAM 1024
40
41 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
42
43
44 #if MAX_DIGEST_LEN < 20
45 #error MAX_DIGEST_LEN shorter than keygrip
46 #endif
47
48 /* Data used to associate an Assuan context with local server data */
49 struct server_local_s {
50   ASSUAN_CONTEXT assuan_ctx;
51   int message_fd;
52   int use_cache_for_signing;
53 };
54
55
56
57
58 \f
59 static void
60 reset_notify (ASSUAN_CONTEXT ctx)
61 {
62   CTRL ctrl = assuan_get_pointer (ctx);
63
64   memset (ctrl->keygrip, 0, 20);
65   ctrl->have_keygrip = 0;
66   ctrl->digest.valuelen = 0;
67 }
68
69
70 /* Check whether the option NAME appears in LINE */
71 static int
72 has_option (const char *line, const char *name)
73 {
74   const char *s;
75   int n = strlen (name);
76
77   s = strstr (line, name);
78   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
79 }
80
81 /* Parse a hex string.  Return an Assuan error code or 0 on success and the
82    length of the parsed string in LEN. */
83 static int
84 parse_hexstring (ASSUAN_CONTEXT ctx, const char *string, size_t *len)
85 {
86   const char *p;
87   size_t n;
88
89   /* parse the hash value */
90   for (p=string, n=0; hexdigitp (p); p++, n++)
91     ;
92   if (*p)
93     return set_error (Parameter_Error, "invalid hexstring");
94   if ((n&1))
95     return set_error (Parameter_Error, "odd number of digits");
96   *len = n;
97   return 0;
98 }
99
100 /* Parse the keygrip in STRING into the provided buffer BUF.  BUF must
101    provide space for 20 bytes. BUF is not changed if the fucntions
102    returns an error. */
103 static int
104 parse_keygrip (ASSUAN_CONTEXT ctx, const char *string, unsigned char *buf)
105 {
106   int rc;
107   size_t n;
108   const unsigned char *p;
109
110   rc = parse_hexstring (ctx, string, &n);
111   if (rc)
112     return rc;
113   n /= 2;
114   if (n != 20)
115     return set_error (Parameter_Error, "invalid length of keygrip");
116
117   for (p=string, n=0; n < 20; p += 2, n++)
118     buf[n] = xtoi_2 (p);
119
120   return 0;
121 }
122
123
124
125
126 /* ISTRUSTED <hexstring_with_fingerprint>
127
128    Return OK when we have an entry with this fingerprint in our
129    trustlist */
130 static int
131 cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
132 {
133   int rc, n, i;
134   char *p;
135   char fpr[41];
136
137   /* parse the fingerprint value */
138   for (p=line,n=0; hexdigitp (p); p++, n++)
139     ;
140   if (*p || !(n == 40 || n == 32))
141     return set_error (Parameter_Error, "invalid fingerprint");
142   i = 0;
143   if (n==32)
144     {
145       strcpy (fpr, "00000000");
146       i += 8;
147     }
148   for (p=line; i < 40; p++, i++)
149     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
150   fpr[i] = 0;
151   rc = agent_istrusted (fpr);
152   if (!rc)
153     return 0;
154   else if (rc == -1)
155     return ASSUAN_Not_Trusted;
156   else
157     {
158       log_error ("command is_trusted failed: %s\n", gnupg_strerror (rc));
159       return map_to_assuan_status (rc);
160     }
161 }
162
163 /* LISTTRUSTED 
164
165    List all entries from the trustlist */
166 static int
167 cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
168 {
169   int rc = agent_listtrusted (ctx);
170   if (rc)
171     log_error ("command listtrusted failed: %s\n", gnupg_strerror (rc));
172   return map_to_assuan_status (rc);
173 }
174
175
176 /* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
177
178    Store a new key in into the trustlist*/
179 static int
180 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
181 {
182   CTRL ctrl = assuan_get_pointer (ctx);
183   int rc, n, i;
184   char *p;
185   char fpr[41];
186   int flag;
187
188   /* parse the fingerprint value */
189   for (p=line,n=0; hexdigitp (p); p++, n++)
190     ;
191   if (!spacep (p) || !(n == 40 || n == 32))
192     return set_error (Parameter_Error, "invalid fingerprint");
193   i = 0;
194   if (n==32)
195     {
196       strcpy (fpr, "00000000");
197       i += 8;
198     }
199   for (p=line; i < 40; p++, i++)
200     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
201   fpr[i] = 0;
202   
203   while (spacep (p))
204     p++;
205   flag = *p++;
206   if ( (flag != 'S' && flag != 'P') || !spacep (p) )
207     return set_error (Parameter_Error, "invalid flag - must be P or S");
208   while (spacep (p))
209     p++;
210
211   rc = agent_marktrusted (ctrl, p, fpr, flag);
212   if (rc)
213     log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc));
214   return map_to_assuan_status (rc);
215 }
216
217
218
219 \f
220 /* HAVEKEY <hexstring_with_keygrip>
221   
222    Return success when the secret key is available */
223 static int
224 cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
225 {
226   int rc;
227   unsigned char buf[20];
228
229   rc = parse_keygrip (ctx, line, buf);
230   if (rc)
231     return rc;
232
233   if (agent_key_available (buf))
234     return ASSUAN_No_Secret_Key;
235
236   return 0;
237 }
238
239
240 /* SIGKEY <hexstring_with_keygrip>
241    SETKEY <hexstring_with_keygrip>
242   
243    Set the  key used for a sign or decrypt operation */
244 static int
245 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
246 {
247   int rc;
248   CTRL ctrl = assuan_get_pointer (ctx);
249
250   rc = parse_keygrip (ctx, line, ctrl->keygrip);
251   if (rc)
252     return rc;
253   ctrl->have_keygrip = 1;
254   return 0;
255 }
256
257
258 /* SETHASH <algonumber> <hexstring> 
259
260   The client can use this command to tell the server about the data
261   (which usually is a hash) to be signed. */
262 static int
263 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
264 {
265   int rc;
266   size_t n;
267   char *p;
268   CTRL ctrl = assuan_get_pointer (ctx);
269   unsigned char *buf;
270   char *endp;
271   int algo;
272
273   /* parse the algo number and check it */
274   algo = (int)strtoul (line, &endp, 10);
275   for (line = endp; *line == ' ' || *line == '\t'; line++)
276     ;
277   if (!algo || gcry_md_test_algo (algo))
278     return set_error (Unsupported_Algorithm, NULL);
279   ctrl->digest.algo = algo;
280
281   /* parse the hash value */
282   rc = parse_hexstring (ctx, line, &n);
283   if (rc)
284     return rc;
285   n /= 2;
286   if (n != 16 && n != 20 && n != 24 && n != 32)
287     return set_error (Parameter_Error, "unsupported length of hash");
288   if (n > MAX_DIGEST_LEN)
289     return set_error (Parameter_Error, "hash value to long");
290
291   buf = ctrl->digest.value;
292   ctrl->digest.valuelen = n;
293   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
294     buf[n] = xtoi_2 (p);
295   for (; n < ctrl->digest.valuelen; n++)
296     buf[n] = 0;
297   return 0;
298 }
299
300
301 /* PKSIGN <options>
302
303    Perform the actual sign operation. Neither input nor output are
304    sensitive to eavesdropping */
305 static int
306 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
307 {
308   int rc;
309   int ignore_cache = 0;
310   CTRL ctrl = assuan_get_pointer (ctx);
311
312   if (opt.ignore_cache_for_signing)
313     ignore_cache = 1;
314   else if (!ctrl->server_local->use_cache_for_signing)
315     ignore_cache = 1;
316
317   rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache);
318   if (rc)
319     log_error ("command pksign failed: %s\n", gnupg_strerror (rc));
320   return map_to_assuan_status (rc);
321 }
322
323 /* PKDECRYPT <options>
324
325    Perform the actual decrypt operation.  Input is not 
326    sensitive to eavesdropping */
327 static int
328 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
329 {
330   int rc;
331   CTRL ctrl = assuan_get_pointer (ctx);
332   char *value;
333   size_t valuelen;
334
335   /* First inquire the data to decrypt */
336   rc = assuan_inquire (ctx, "CIPHERTEXT",
337                        &value, &valuelen, MAXLEN_CIPHERTEXT);
338   if (rc)
339     return rc;
340
341   rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
342   xfree (value);
343   if (rc)
344     log_error ("command pkdecrypt failed: %s\n", gnupg_strerror (rc));
345   return map_to_assuan_status (rc);
346 }
347
348
349 /* GENKEY
350
351    Generate a new key, store the secret part and return the public
352    part.  Here is an example transaction:
353
354    C: GENKEY
355    S: INQUIRE KEYPARM
356    C: D (genkey (rsa (nbits  1024)))
357    C: END
358    S: D (public-key
359    S: D   (rsa (n 326487324683264) (e 10001)))
360    S  OK key created
361 */
362
363 static int
364 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
365 {
366   CTRL ctrl = assuan_get_pointer (ctx);
367   int rc;
368   char *value;
369   size_t valuelen;
370
371   /* First inquire the parameters */
372   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
373   if (rc)
374     return rc;
375
376   rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
377   xfree (value);
378   if (rc)
379     log_error ("command genkey failed: %s\n", gnupg_strerror (rc));
380   return map_to_assuan_status (rc);
381 }
382
383
384 static void
385 plus_to_blank (char *s)
386 {
387   for (; *s; s++)
388     {
389       if (*s == '+')
390         *s = ' ';
391     }
392 }
393
394 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
395
396    This function is usually used to ask for a passphrase to be used
397    for conventional encryption, but may also be used by programs which
398    need specal handling of passphrases.  This command uses a syntax
399    which helps clients to use the agent with minimum effort.  The
400    agent either returns with an error or with a OK followed by the hex
401    encoded passphrase.  Note that the length of the strings is
402    implicitly limited by the maximum length of a command.
403 */
404
405 static int
406 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
407 {
408   CTRL ctrl = assuan_get_pointer (ctx);
409   int rc;
410   const char *pw;
411   char *response;
412   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
413   char *p;
414   void *cache_marker;
415
416   /* parse the stuff */
417   for (p=line; *p == ' '; p++)
418     ;
419   cacheid = p;
420   p = strchr (cacheid, ' ');
421   if (p)
422     {
423       *p++ = 0;
424       while (*p == ' ')
425         p++;
426       errtext = p;
427       p = strchr (errtext, ' ');
428       if (p)
429         {
430           *p++ = 0;
431           while (*p == ' ')
432             p++;
433           prompt = p;
434           p = strchr (prompt, ' ');
435           if (p)
436             {
437               *p++ = 0;
438               while (*p == ' ')
439                 p++;
440               desc = p;
441               p = strchr (desc, ' ');
442               if (p)
443                 *p = 0; /* ignore garbage */
444             }
445         }
446     }
447   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
448     return set_error (Parameter_Error, "invalid length of cacheID");
449   if (!desc)
450     return set_error (Parameter_Error, "no description given");
451
452   if (!strcmp (cacheid, "X"))
453     cacheid = NULL;
454   if (!strcmp (errtext, "X"))
455     errtext = NULL;
456   if (!strcmp (prompt, "X"))
457     prompt = NULL;
458   if (!strcmp (desc, "X"))
459     desc = NULL;
460
461   /* Note: we store the hexified versions in the cache. */
462   pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL;
463   if (pw)
464     {
465       assuan_begin_confidential (ctx);
466       rc = assuan_set_okay_line (ctx, pw);
467       agent_unlock_cache_entry (&cache_marker);
468     }
469   else
470     {
471       /* Note, that we only need to replace the + characters and
472          should leave the other escaping in place because the escaped
473          string is send verbatim to the pinentry which does the
474          unescaping (but not the + replacing) */
475       if (errtext)
476         plus_to_blank (errtext);
477       if (prompt)
478         plus_to_blank (prompt);
479       if (desc)
480         plus_to_blank (desc);
481
482       rc = agent_get_passphrase (ctrl, &response, desc, prompt, errtext);
483       if (!rc)
484         {
485           if (cacheid)
486             agent_put_cache (cacheid, response, 0);
487           assuan_begin_confidential (ctx);
488           rc = assuan_set_okay_line (ctx, response);
489           xfree (response);
490         }
491     }
492
493   if (rc)
494     log_error ("command get_passphrase failed: %s\n", gnupg_strerror (rc));
495   return map_to_assuan_status (rc);
496 }
497
498
499 /* CLEAR_PASSPHRASE <cache_id>
500
501    may be used to invalidate the cache entry for a passphrase.  The
502    function returns with OK even when there is no cached passphrase.
503 */
504
505 static int
506 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
507 {
508   char *cacheid = NULL;
509   char *p;
510
511   /* parse the stuff */
512   for (p=line; *p == ' '; p++)
513     ;
514   cacheid = p;
515   p = strchr (cacheid, ' ');
516   if (p)
517     *p = 0; /* ignore garbage */
518   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
519     return set_error (Parameter_Error, "invalid length of cacheID");
520
521   agent_put_cache (cacheid, NULL, 0);
522   return 0;
523 }
524
525 \f
526 /* LEARN [--send]
527
528    Learn something about the currently inserted smartcard.  With
529    --send the new certificates are send back.  */
530 static int
531 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
532 {
533   int rc;
534
535   rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL);
536   if (rc)
537     log_error ("command learn failed: %s\n", gnupg_strerror (rc));
538   return map_to_assuan_status (rc);
539 }
540
541
542 \f
543 /* PASSWD <hexstring_with_keygrip>
544   
545    Change the passphrase/PID for the key identified by keygrip in LINE. */
546 static int
547 cmd_passwd (ASSUAN_CONTEXT ctx, char *line)
548 {
549   CTRL ctrl = assuan_get_pointer (ctx);
550   int rc;
551   unsigned char grip[20];
552   GCRY_SEXP s_skey = NULL;
553   unsigned char *shadow_info = NULL;
554
555   rc = parse_keygrip (ctx, line, grip);
556   if (rc)
557     return rc; /* we can't jump to leave because this is already an
558                   Assuan error code. */
559
560   s_skey = agent_key_from_file (ctrl, grip, &shadow_info, 1);
561   if (!s_skey && !shadow_info)
562     rc = gpg_error (GPG_ERR_NO_SECKEY);
563   else if (!s_skey)
564     {
565       log_error ("changing a smartcard PIN is not yet supported\n");
566       rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
567     }
568   else
569     rc = agent_protect_and_store (ctrl, s_skey);
570
571   gcry_sexp_release (s_skey);
572   xfree (shadow_info);
573   if (rc)
574     log_error ("command passwd failed: %s\n", gnupg_strerror (rc));
575   return map_to_assuan_status (rc);
576 }
577
578
579 \f
580 static int
581 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
582 {
583    CTRL ctrl = assuan_get_pointer (ctx);
584
585   if (!strcmp (key, "display"))
586     {
587       if (ctrl->display)
588         free (ctrl->display);
589       ctrl->display = strdup (value);
590       if (!ctrl->display)
591         return ASSUAN_Out_Of_Core;
592     }
593   else if (!strcmp (key, "ttyname"))
594     {
595       if (!opt.keep_tty)
596         {
597           if (ctrl->ttyname)
598             free (ctrl->ttyname);
599           ctrl->ttyname = strdup (value);
600           if (!ctrl->ttyname)
601             return ASSUAN_Out_Of_Core;
602         }
603     }
604   else if (!strcmp (key, "ttytype"))
605     {
606       if (!opt.keep_tty)
607         {
608           if (ctrl->ttytype)
609             free (ctrl->ttytype);
610           ctrl->ttytype = strdup (value);
611           if (!ctrl->ttytype)
612             return ASSUAN_Out_Of_Core;
613         }
614     }
615   else if (!strcmp (key, "lc-ctype"))
616     {
617       if (ctrl->lc_ctype)
618         free (ctrl->lc_ctype);
619       ctrl->lc_ctype = strdup (value);
620       if (!ctrl->lc_ctype)
621         return ASSUAN_Out_Of_Core;
622     }
623   else if (!strcmp (key, "lc-messages"))
624     {
625       if (ctrl->lc_messages)
626         free (ctrl->lc_messages);
627       ctrl->lc_messages = strdup (value);
628       if (!ctrl->lc_messages)
629         return ASSUAN_Out_Of_Core;
630     }
631   else if (!strcmp (key, "use-cache-for-signing"))
632     ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
633   else
634     return ASSUAN_Invalid_Option;
635
636   return 0;
637 }
638
639 \f
640 /* Tell the assuan library about our commands */
641 static int
642 register_commands (ASSUAN_CONTEXT ctx)
643 {
644   static struct {
645     const char *name;
646     int (*handler)(ASSUAN_CONTEXT, char *line);
647   } table[] = {
648     { "ISTRUSTED",      cmd_istrusted },
649     { "HAVEKEY",        cmd_havekey },
650     { "SIGKEY",         cmd_sigkey },
651     { "SETKEY",         cmd_sigkey },
652     { "SETHASH",        cmd_sethash },
653     { "PKSIGN",         cmd_pksign },
654     { "PKDECRYPT",      cmd_pkdecrypt },
655     { "GENKEY",         cmd_genkey },
656     { "GET_PASSPHRASE", cmd_get_passphrase },
657     { "CLEAR_PASSPHRASE", cmd_clear_passphrase },
658     { "LISTTRUSTED",    cmd_listtrusted },
659     { "MARKTRUSTED",    cmd_marktrusted },
660     { "LEARN",          cmd_learn },
661     { "PASSWD",         cmd_passwd },
662     { "INPUT",          NULL }, 
663     { "OUTPUT",         NULL }, 
664     { NULL }
665   };
666   int i, rc;
667
668   for (i=0; table[i].name; i++)
669     {
670       rc = assuan_register_command (ctx, table[i].name, table[i].handler);
671       if (rc)
672         return rc;
673     } 
674   assuan_register_reset_notify (ctx, reset_notify);
675   assuan_register_option_handler (ctx, option_handler);
676   return 0;
677 }
678
679
680 /* Startup the server.  If LISTEN_FD and FD is given as -1, this is a simple
681    piper server, otherwise it is a regular server */
682 void
683 start_command_handler (int listen_fd, int fd)
684 {
685   int rc;
686   ASSUAN_CONTEXT ctx;
687   struct server_control_s ctrl;
688
689   memset (&ctrl, 0, sizeof ctrl);
690   agent_init_default_ctrl (&ctrl);
691   
692   if (listen_fd == -1 && fd == -1)
693     {
694       int filedes[2];
695
696       filedes[0] = 0;
697       filedes[1] = 1;
698       rc = assuan_init_pipe_server (&ctx, filedes);
699     }
700   else if (listen_fd != -1)
701     {
702       rc = assuan_init_socket_server (&ctx, listen_fd);
703     }
704   else 
705     {
706       rc = assuan_init_connected_socket_server (&ctx, fd);
707     }
708   if (rc)
709     {
710       log_error ("failed to initialize the server: %s\n",
711                  assuan_strerror(rc));
712       agent_exit (2);
713     }
714   rc = register_commands (ctx);
715   if (rc)
716     {
717       log_error ("failed to register commands with Assuan: %s\n",
718                  assuan_strerror(rc));
719       agent_exit (2);
720     }
721
722   assuan_set_pointer (ctx, &ctrl);
723   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
724   ctrl.server_local->assuan_ctx = ctx;
725   ctrl.server_local->message_fd = -1;
726   ctrl.server_local->use_cache_for_signing = 1;
727
728   if (DBG_ASSUAN)
729     assuan_set_log_stream (ctx, log_get_stream ());
730
731   for (;;)
732     {
733       rc = assuan_accept (ctx);
734       if (rc == -1)
735         {
736           break;
737         }
738       else if (rc)
739         {
740           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
741           break;
742         }
743       
744       rc = assuan_process (ctx);
745       if (rc)
746         {
747           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
748           continue;
749         }
750     }
751
752
753   assuan_deinit_server (ctx);
754   if (ctrl.display)
755     free (ctrl.display);
756   if (ctrl.ttyname)
757     free (ctrl.ttyname);
758   if (ctrl.ttytype)
759     free (ctrl.ttytype);
760   if (ctrl.lc_ctype)
761     free (ctrl.lc_ctype);
762   if (ctrl.lc_messages)
763     free (ctrl.lc_messages);
764 }
765