bbcab8e7dfcac53d63649b925624064994c8dac9
[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 };
52
53
54
55
56 \f
57 static void
58 reset_notify (ASSUAN_CONTEXT ctx)
59 {
60   CTRL ctrl = assuan_get_pointer (ctx);
61
62   memset (ctrl->keygrip, 0, 20);
63   ctrl->have_keygrip = 0;
64   ctrl->digest.valuelen = 0;
65 }
66
67 /* ISTRUSTED <hexstring_with_fingerprint>
68
69    Return OK when we have an entry with this fingerprint in our
70    trustlist */
71 static int
72 cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
73 {
74   int rc, n, i;
75   char *p;
76   char fpr[41];
77
78   /* parse the fingerprint value */
79   for (p=line,n=0; hexdigitp (p); p++, n++)
80     ;
81   if (*p || !(n == 40 || n == 32))
82     return set_error (Parameter_Error, "invalid fingerprint");
83   i = 0;
84   if (n==32)
85     {
86       strcpy (fpr, "00000000");
87       i += 8;
88     }
89   for (p=line; i < 40; p++, i++)
90     fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
91   fpr[i] = 0;
92   rc = agent_istrusted (fpr);
93   if (!rc)
94     return 0;
95   else if (rc == -1)
96     return ASSUAN_Not_Trusted;
97   else
98     return map_to_assuan_status (rc);
99 }
100
101 /* LISTTRUSTED 
102
103    List all entries from the trustlist */
104 static int
105 cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
106 {
107   return map_to_assuan_status (agent_listtrusted (ctx));
108 }
109
110
111 /* MARKTRUSTED <hexstring_with_fingerprint> <flag>
112
113    Store a new key in into the trustlist*/
114 static int
115 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
116 {
117   return ASSUAN_Not_Implemented;
118 }
119
120
121
122 \f
123 /* HAVEKEY <hexstring_with_keygrip>
124   
125    Return success when the secret key is available */
126 static int
127 cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
128 {
129   int n;
130   char *p;
131   unsigned char buf[20];
132
133   /* parse the hash value */
134   for (p=line,n=0; hexdigitp (p); p++, n++)
135     ;
136   if (*p)
137     return set_error (Parameter_Error, "invalid hexstring");
138   if ((n&1))
139     return set_error (Parameter_Error, "odd number of digits");
140   n /= 2;
141   if (n != 20)
142     return set_error (Parameter_Error, "invalid length of keygrip");
143
144   for (p=line, n=0; n < 20; p += 2, n++)
145     buf[n] = xtoi_2 (p);
146
147   if (agent_key_available (buf))
148     return ASSUAN_No_Secret_Key;
149
150   return 0;
151 }
152
153
154 /* SIGKEY <hexstring_with_keygrip>
155    SETKEY <hexstring_with_keygrip>
156   
157    Set the  key used for a sign or decrypt operation */
158 static int
159 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
160 {
161   int n;
162   char *p;
163   CTRL ctrl = assuan_get_pointer (ctx);
164   unsigned char *buf;
165
166   /* parse the hash value */
167   for (p=line,n=0; hexdigitp (p); p++, n++)
168     ;
169   if (*p)
170     return set_error (Parameter_Error, "invalid hexstring");
171   if ((n&1))
172     return set_error (Parameter_Error, "odd number of digits");
173   n /= 2;
174   if (n != 20)
175     return set_error (Parameter_Error, "invalid length of keygrip");
176
177   buf = ctrl->keygrip;
178   for (p=line, n=0; n < 20; p += 2, n++)
179     buf[n] = xtoi_2 (p);
180   ctrl->have_keygrip = 1;
181   return 0;
182 }
183
184 /* SETHASH <algonumber> <hexstring> 
185
186   The client can use this command to tell the server about the data
187   (which usually is a hash) to be signed. */
188 static int
189 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
190 {
191   int n;
192   char *p;
193   CTRL ctrl = assuan_get_pointer (ctx);
194   unsigned char *buf;
195   char *endp;
196   int algo;
197
198   /* parse the algo number and check it */
199   algo = (int)strtoul (line, &endp, 10);
200   for (line = endp; *line == ' ' || *line == '\t'; line++)
201     ;
202   if (!algo || gcry_md_test_algo (algo))
203     return set_error (Unsupported_Algorithm, NULL);
204   ctrl->digest.algo = algo;
205
206   /* parse the hash value */
207   for (p=line,n=0; hexdigitp (p); p++, n++)
208     ;
209   if (*p)
210     return set_error (Parameter_Error, "invalid hexstring");
211   if ((n&1))
212     return set_error (Parameter_Error, "odd number of digits");
213   n /= 2;
214   if (n != 16 && n != 20 && n != 24 && n != 32)
215     return set_error (Parameter_Error, "unsupported length of hash");
216   if (n > MAX_DIGEST_LEN)
217     return set_error (Parameter_Error, "hash value to long");
218
219   buf = ctrl->digest.value;
220   ctrl->digest.valuelen = n;
221   for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
222     buf[n] = xtoi_2 (p);
223   for (; n < ctrl->digest.valuelen; n++)
224     buf[n] = 0;
225   return 0;
226 }
227
228
229 /* PKSIGN <options>
230
231    Perform the actual sign operation. Neither input nor output are
232    sensitive to eavesdropping */
233 static int
234 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
235 {
236   int rc;
237   CTRL ctrl = assuan_get_pointer (ctx);
238
239   rc = agent_pksign (ctrl, assuan_get_data_fp (ctx));
240   return map_to_assuan_status (rc);
241 }
242
243 /* PKDECRYPT <options>
244
245    Perform the actual decrypt operation.  Input is not 
246    sensitive to eavesdropping */
247 static int
248 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
249 {
250   int rc;
251   CTRL ctrl = assuan_get_pointer (ctx);
252   char *value;
253   size_t valuelen;
254
255   /* First inquire the data to decrypt */
256   rc = assuan_inquire (ctx, "CIPHERTEXT",
257                        &value, &valuelen, MAXLEN_CIPHERTEXT);
258   if (rc)
259     return rc;
260
261   rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
262   xfree (value);
263   return map_to_assuan_status (rc);
264 }
265
266
267 /* GENKEY
268
269    Generate a new key, store the secret part and return the public
270    part.  Here is an example transaction:
271
272    C: GENKEY
273    S: INQUIRE KEYPARM
274    C: D (genkey (rsa (nbits  1024)))
275    C: END
276    S: D (public-key
277    S: D   (rsa (n 326487324683264) (e 10001)))
278    S  OK key created
279 */
280
281 static int
282 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
283 {
284   CTRL ctrl = assuan_get_pointer (ctx);
285   int rc;
286   char *value;
287   size_t valuelen;
288
289   /* First inquire the parameters */
290   rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
291   if (rc)
292     return rc;
293
294   rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
295   xfree (value);
296   return map_to_assuan_status (rc);
297 }
298
299
300 static void
301 plus_to_blank (char *s)
302 {
303   for (; *s; s++)
304     {
305       if (*s == '+')
306         *s = ' ';
307     }
308 }
309
310 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
311
312    This function is usually used to ask for a passphrase to be used
313    for conventional encryption, but may also be used by programs which
314    need specal handling of passphrases.  This command uses a syntax
315    which helps clients to use the agent with minimum effort.  The
316    agent either returns with an error or with a OK followed by the hex
317    encoded passphrase.  Note that the length of the strings is
318    implicitly limited by the maximum length of a command.
319 */
320
321 static int
322 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
323 {
324   int rc;
325   const char *pw;
326   char *response;
327   char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
328   char *p;
329
330   /* parse the stuff */
331   for (p=line; *p == ' '; p++)
332     ;
333   cacheid = p;
334   p = strchr (cacheid, ' ');
335   if (p)
336     {
337       *p++ = 0;
338       while (*p == ' ')
339         p++;
340       errtext = p;
341       p = strchr (errtext, ' ');
342       if (p)
343         {
344           *p++ = 0;
345           while (*p == ' ')
346             p++;
347           prompt = p;
348           p = strchr (prompt, ' ');
349           if (p)
350             {
351               *p++ = 0;
352               while (*p == ' ')
353                 p++;
354               desc = p;
355               p = strchr (desc, ' ');
356               if (p)
357                 *p = 0; /* ignore garbage */
358             }
359         }
360     }
361   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
362     return set_error (Parameter_Error, "invalid length of cacheID");
363   if (!desc)
364     return set_error (Parameter_Error, "no description given");
365
366   if (!strcmp (cacheid, "X"))
367     cacheid = NULL;
368   if (!strcmp (errtext, "X"))
369     errtext = NULL;
370   if (!strcmp (prompt, "X"))
371     prompt = NULL;
372   if (!strcmp (desc, "X"))
373     desc = NULL;
374
375   /* Note: we store the hexified versions in the cache. */
376   pw = cacheid ? agent_get_cache (cacheid) : NULL;
377   if (pw)
378     {
379       assuan_begin_confidential (ctx);
380       rc = assuan_set_okay_line (ctx, pw);
381     }
382   else
383     {
384       /* Note, that we only need to repalce the + characters and
385          should leave the other escaping in place becuase the escaped
386          sting is send verbatim to the pinentry which does the
387          unescaping (but not the + replacing) */
388       if (errtext)
389         plus_to_blank (errtext);
390       if (prompt)
391         plus_to_blank (prompt);
392       if (desc)
393         plus_to_blank (desc);
394
395       rc = agent_get_passphrase (&response, desc, prompt, errtext);
396       if (!rc)
397         {
398           if (cacheid)
399             agent_put_cache (cacheid, response, 0);
400           assuan_begin_confidential (ctx);
401           rc = assuan_set_okay_line (ctx, response);
402           xfree (response);
403         }
404     }
405
406   return map_to_assuan_status (rc);
407 }
408
409
410 /* CLEAR_PASSPHRASE <cache_id>
411
412    may be used to invalidate the cache entry for a passphrase.  The
413    function returns with OK even when there is no cached passphrase.
414 */
415
416 static int
417 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
418 {
419   char *cacheid = NULL;
420   char *p;
421
422   /* parse the stuff */
423   for (p=line; *p == ' '; p++)
424     ;
425   cacheid = p;
426   p = strchr (cacheid, ' ');
427   if (p)
428     *p = 0; /* ignore garbage */
429   if (!cacheid || !*cacheid || strlen (cacheid) > 50)
430     return set_error (Parameter_Error, "invalid length of cacheID");
431
432   agent_put_cache (cacheid, NULL, 0);
433   return 0;
434 }
435
436
437 \f
438 /* Tell the assuan library about our commands */
439 static int
440 register_commands (ASSUAN_CONTEXT ctx)
441 {
442   static struct {
443     const char *name;
444     int cmd_id;
445     int (*handler)(ASSUAN_CONTEXT, char *line);
446   } table[] = {
447     { "ISTRUSTED",  0,  cmd_istrusted },
448     { "HAVEKEY",    0,  cmd_havekey },
449     { "SIGKEY",     0,  cmd_sigkey },
450     { "SETKEY",     0,  cmd_sigkey },
451     { "SETHASH",    0,  cmd_sethash },
452     { "PKSIGN",     0,  cmd_pksign },
453     { "PKDECRYPT",  0,  cmd_pkdecrypt },
454     { "GENKEY",     0,  cmd_genkey },
455     { "GET_PASSPHRASE",0, cmd_get_passphrase },
456     { "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
457     { "LISTTRUSTED",  0,  cmd_listtrusted },
458     { "MARKTRUSTED",  0,  cmd_marktrusted },
459     { "",     ASSUAN_CMD_INPUT, NULL }, 
460     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
461     { NULL }
462   };
463   int i, j, rc;
464
465   for (i=j=0; table[i].name; i++)
466     {
467       rc = assuan_register_command (ctx,
468                                     table[i].cmd_id? table[i].cmd_id
469                                                    : (ASSUAN_CMD_USER + j++),
470                                     table[i].name, table[i].handler);
471       if (rc)
472         return rc;
473     } 
474   assuan_register_reset_notify (ctx, reset_notify);
475   return 0;
476 }
477
478
479 /* Startup the server.  If LISTEN_FD is given as -1, this is simple
480    piper server, otherwise it is a regular server */
481 void
482 start_command_handler (int listen_fd)
483 {
484   int rc;
485   ASSUAN_CONTEXT ctx;
486   struct server_control_s ctrl;
487
488   memset (&ctrl, 0, sizeof ctrl);
489
490   
491   if (listen_fd == -1)
492     {
493       int filedes[2];
494
495       filedes[0] = 0;
496       filedes[1] = 1;
497       rc = assuan_init_pipe_server (&ctx, filedes);
498     }
499   else
500     {
501       rc = assuan_init_socket_server (&ctx, listen_fd);
502     }
503   if (rc)
504     {
505       log_error ("failed to initialize the server: %s\n",
506                  assuan_strerror(rc));
507       agent_exit (2);
508     }
509   rc = register_commands (ctx);
510   if (rc)
511     {
512       log_error ("failed to register commands with Assuan: %s\n",
513                  assuan_strerror(rc));
514       agent_exit (2);
515     }
516
517   assuan_set_pointer (ctx, &ctrl);
518   ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
519   ctrl.server_local->assuan_ctx = ctx;
520   ctrl.server_local->message_fd = -1;
521
522   if (DBG_ASSUAN)
523     assuan_set_log_stream (ctx, log_get_stream ());
524
525   for (;;)
526     {
527       rc = assuan_accept (ctx);
528       if (rc == -1)
529         {
530           break;
531         }
532       else if (rc)
533         {
534           log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
535           break;
536         }
537       
538       rc = assuan_process (ctx);
539       if (rc)
540         {
541           log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
542           continue;
543         }
544     }
545
546
547   assuan_deinit_server (ctx);
548 }
549
550
551