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