2002-04-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / agent / command.c
blobb405ec61c0ce7518ce47ae22e8bfd421dd63384c
1 /* command.c - gpg-agent command handler
2 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
21 /* FIXME: we should not use the default assuan buffering but setup
22 some buffering in secure mempory to protect session keys etc. */
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>
32 #include "agent.h"
33 #include "../assuan/assuan.h"
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
40 #define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
43 #if MAX_DIGEST_LEN < 20
44 #error MAX_DIGEST_LEN shorter than keygrip
45 #endif
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;
57 static void
58 reset_notify (ASSUAN_CONTEXT ctx)
60 CTRL ctrl = assuan_get_pointer (ctx);
62 memset (ctrl->keygrip, 0, 20);
63 ctrl->have_keygrip = 0;
64 ctrl->digest.valuelen = 0;
68 /* Check whether the option NAME appears in LINE */
69 static int
70 has_option (const char *line, const char *name)
72 const char *s;
73 int n = strlen (name);
75 s = strstr (line, name);
76 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
82 /* ISTRUSTED <hexstring_with_fingerprint>
84 Return OK when we have an entry with this fingerprint in our
85 trustlist */
86 static int
87 cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
89 int rc, n, i;
90 char *p;
91 char fpr[41];
93 /* parse the fingerprint value */
94 for (p=line,n=0; hexdigitp (p); p++, n++)
96 if (*p || !(n == 40 || n == 32))
97 return set_error (Parameter_Error, "invalid fingerprint");
98 i = 0;
99 if (n==32)
101 strcpy (fpr, "00000000");
102 i += 8;
104 for (p=line; i < 40; p++, i++)
105 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
106 fpr[i] = 0;
107 rc = agent_istrusted (fpr);
108 if (!rc)
109 return 0;
110 else if (rc == -1)
111 return ASSUAN_Not_Trusted;
112 else
113 return map_to_assuan_status (rc);
116 /* LISTTRUSTED
118 List all entries from the trustlist */
119 static int
120 cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
122 return map_to_assuan_status (agent_listtrusted (ctx));
126 /* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
128 Store a new key in into the trustlist*/
129 static int
130 cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
132 int rc, n, i;
133 char *p;
134 char fpr[41];
135 int flag;
137 /* parse the fingerprint value */
138 for (p=line,n=0; hexdigitp (p); p++, n++)
140 if (!spacep (p) || !(n == 40 || n == 32))
141 return set_error (Parameter_Error, "invalid fingerprint");
142 i = 0;
143 if (n==32)
145 strcpy (fpr, "00000000");
146 i += 8;
148 for (p=line; i < 40; p++, i++)
149 fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
150 fpr[i] = 0;
152 while (spacep (p))
153 p++;
154 flag = *p++;
155 if ( (flag != 'S' && flag != 'P') || !spacep (p) )
156 return set_error (Parameter_Error, "invalid flag - must be P or S");
157 while (spacep (p))
158 p++;
160 rc = agent_marktrusted (p, fpr, flag);
161 return map_to_assuan_status (rc);
167 /* HAVEKEY <hexstring_with_keygrip>
169 Return success when the secret key is available */
170 static int
171 cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
173 int n;
174 char *p;
175 unsigned char buf[20];
177 /* parse the hash value */
178 for (p=line,n=0; hexdigitp (p); p++, n++)
180 if (*p)
181 return set_error (Parameter_Error, "invalid hexstring");
182 if ((n&1))
183 return set_error (Parameter_Error, "odd number of digits");
184 n /= 2;
185 if (n != 20)
186 return set_error (Parameter_Error, "invalid length of keygrip");
188 for (p=line, n=0; n < 20; p += 2, n++)
189 buf[n] = xtoi_2 (p);
191 if (agent_key_available (buf))
192 return ASSUAN_No_Secret_Key;
194 return 0;
198 /* SIGKEY <hexstring_with_keygrip>
199 SETKEY <hexstring_with_keygrip>
201 Set the key used for a sign or decrypt operation */
202 static int
203 cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
205 int n;
206 char *p;
207 CTRL ctrl = assuan_get_pointer (ctx);
208 unsigned char *buf;
210 /* parse the hash value */
211 for (p=line,n=0; hexdigitp (p); p++, n++)
213 if (*p)
214 return set_error (Parameter_Error, "invalid hexstring");
215 if ((n&1))
216 return set_error (Parameter_Error, "odd number of digits");
217 n /= 2;
218 if (n != 20)
219 return set_error (Parameter_Error, "invalid length of keygrip");
221 buf = ctrl->keygrip;
222 for (p=line, n=0; n < 20; p += 2, n++)
223 buf[n] = xtoi_2 (p);
224 ctrl->have_keygrip = 1;
225 return 0;
228 /* SETHASH <algonumber> <hexstring>
230 The client can use this command to tell the server about the data
231 (which usually is a hash) to be signed. */
232 static int
233 cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
235 int n;
236 char *p;
237 CTRL ctrl = assuan_get_pointer (ctx);
238 unsigned char *buf;
239 char *endp;
240 int algo;
242 /* parse the algo number and check it */
243 algo = (int)strtoul (line, &endp, 10);
244 for (line = endp; *line == ' ' || *line == '\t'; line++)
246 if (!algo || gcry_md_test_algo (algo))
247 return set_error (Unsupported_Algorithm, NULL);
248 ctrl->digest.algo = algo;
250 /* parse the hash value */
251 for (p=line,n=0; hexdigitp (p); p++, n++)
253 if (*p)
254 return set_error (Parameter_Error, "invalid hexstring");
255 if ((n&1))
256 return set_error (Parameter_Error, "odd number of digits");
257 n /= 2;
258 if (n != 16 && n != 20 && n != 24 && n != 32)
259 return set_error (Parameter_Error, "unsupported length of hash");
260 if (n > MAX_DIGEST_LEN)
261 return set_error (Parameter_Error, "hash value to long");
263 buf = ctrl->digest.value;
264 ctrl->digest.valuelen = n;
265 for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
266 buf[n] = xtoi_2 (p);
267 for (; n < ctrl->digest.valuelen; n++)
268 buf[n] = 0;
269 return 0;
273 /* PKSIGN <options>
275 Perform the actual sign operation. Neither input nor output are
276 sensitive to eavesdropping */
277 static int
278 cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
280 int rc;
281 CTRL ctrl = assuan_get_pointer (ctx);
283 rc = agent_pksign (ctrl, assuan_get_data_fp (ctx));
284 return map_to_assuan_status (rc);
287 /* PKDECRYPT <options>
289 Perform the actual decrypt operation. Input is not
290 sensitive to eavesdropping */
291 static int
292 cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
294 int rc;
295 CTRL ctrl = assuan_get_pointer (ctx);
296 char *value;
297 size_t valuelen;
299 /* First inquire the data to decrypt */
300 rc = assuan_inquire (ctx, "CIPHERTEXT",
301 &value, &valuelen, MAXLEN_CIPHERTEXT);
302 if (rc)
303 return rc;
305 rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
306 xfree (value);
307 return map_to_assuan_status (rc);
311 /* GENKEY
313 Generate a new key, store the secret part and return the public
314 part. Here is an example transaction:
316 C: GENKEY
317 S: INQUIRE KEYPARM
318 C: D (genkey (rsa (nbits 1024)))
319 C: END
320 S: D (public-key
321 S: D (rsa (n 326487324683264) (e 10001)))
322 S OK key created
325 static int
326 cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
328 CTRL ctrl = assuan_get_pointer (ctx);
329 int rc;
330 char *value;
331 size_t valuelen;
333 /* First inquire the parameters */
334 rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
335 if (rc)
336 return rc;
338 rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
339 xfree (value);
340 return map_to_assuan_status (rc);
344 static void
345 plus_to_blank (char *s)
347 for (; *s; s++)
349 if (*s == '+')
350 *s = ' ';
354 /* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
356 This function is usually used to ask for a passphrase to be used
357 for conventional encryption, but may also be used by programs which
358 need specal handling of passphrases. This command uses a syntax
359 which helps clients to use the agent with minimum effort. The
360 agent either returns with an error or with a OK followed by the hex
361 encoded passphrase. Note that the length of the strings is
362 implicitly limited by the maximum length of a command.
365 static int
366 cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
368 int rc;
369 const char *pw;
370 char *response;
371 char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
372 char *p;
374 /* parse the stuff */
375 for (p=line; *p == ' '; p++)
377 cacheid = p;
378 p = strchr (cacheid, ' ');
379 if (p)
381 *p++ = 0;
382 while (*p == ' ')
383 p++;
384 errtext = p;
385 p = strchr (errtext, ' ');
386 if (p)
388 *p++ = 0;
389 while (*p == ' ')
390 p++;
391 prompt = p;
392 p = strchr (prompt, ' ');
393 if (p)
395 *p++ = 0;
396 while (*p == ' ')
397 p++;
398 desc = p;
399 p = strchr (desc, ' ');
400 if (p)
401 *p = 0; /* ignore garbage */
405 if (!cacheid || !*cacheid || strlen (cacheid) > 50)
406 return set_error (Parameter_Error, "invalid length of cacheID");
407 if (!desc)
408 return set_error (Parameter_Error, "no description given");
410 if (!strcmp (cacheid, "X"))
411 cacheid = NULL;
412 if (!strcmp (errtext, "X"))
413 errtext = NULL;
414 if (!strcmp (prompt, "X"))
415 prompt = NULL;
416 if (!strcmp (desc, "X"))
417 desc = NULL;
419 /* Note: we store the hexified versions in the cache. */
420 pw = cacheid ? agent_get_cache (cacheid) : NULL;
421 if (pw)
423 assuan_begin_confidential (ctx);
424 rc = assuan_set_okay_line (ctx, pw);
426 else
428 /* Note, that we only need to repalce the + characters and
429 should leave the other escaping in place becuase the escaped
430 sting is send verbatim to the pinentry which does the
431 unescaping (but not the + replacing) */
432 if (errtext)
433 plus_to_blank (errtext);
434 if (prompt)
435 plus_to_blank (prompt);
436 if (desc)
437 plus_to_blank (desc);
439 rc = agent_get_passphrase (&response, desc, prompt, errtext);
440 if (!rc)
442 if (cacheid)
443 agent_put_cache (cacheid, response, 0);
444 assuan_begin_confidential (ctx);
445 rc = assuan_set_okay_line (ctx, response);
446 xfree (response);
450 return map_to_assuan_status (rc);
454 /* CLEAR_PASSPHRASE <cache_id>
456 may be used to invalidate the cache entry for a passphrase. The
457 function returns with OK even when there is no cached passphrase.
460 static int
461 cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
463 char *cacheid = NULL;
464 char *p;
466 /* parse the stuff */
467 for (p=line; *p == ' '; p++)
469 cacheid = p;
470 p = strchr (cacheid, ' ');
471 if (p)
472 *p = 0; /* ignore garbage */
473 if (!cacheid || !*cacheid || strlen (cacheid) > 50)
474 return set_error (Parameter_Error, "invalid length of cacheID");
476 agent_put_cache (cacheid, NULL, 0);
477 return 0;
481 /* LEARN [--send]
483 Learn something about the currently inserted smartcard. With
484 --send the new certificates are send back. */
485 static int
486 cmd_learn (ASSUAN_CONTEXT ctx, char *line)
488 int rc;
490 rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL);
491 if (rc)
492 log_error ("agent_handle_learn failed: %s\n", gnupg_strerror (rc));
493 return map_to_assuan_status (rc);
498 static int
499 option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
501 CTRL ctrl = assuan_get_pointer (ctx);
503 if (!strcmp (key, "display"))
505 if (opt.display)
506 free (opt.display);
507 opt.display = strdup (value);
508 if (!opt.display)
509 return ASSUAN_Out_Of_Core;
511 else if (!strcmp (key, "ttyname"))
513 if (opt.ttyname)
514 free (opt.ttyname);
515 opt.ttyname = strdup (value);
516 if (!opt.ttyname)
517 return ASSUAN_Out_Of_Core;
519 else if (!strcmp (key, "ttytype"))
521 if (opt.ttytype)
522 free (opt.ttytype);
523 opt.ttytype = strdup (value);
524 if (!opt.ttytype)
525 return ASSUAN_Out_Of_Core;
527 else if (!strcmp (key, "lc-ctype"))
529 if (opt.lc_ctype)
530 free (opt.lc_ctype);
531 opt.lc_ctype = strdup (value);
532 if (!opt.lc_ctype)
533 return ASSUAN_Out_Of_Core;
535 else if (!strcmp (key, "lc-messages"))
537 if (opt.lc_messages)
538 free (opt.lc_messages);
539 opt.lc_messages = strdup (value);
540 if (!opt.lc_messages)
541 return ASSUAN_Out_Of_Core;
543 else
544 return ASSUAN_Invalid_Option;
546 return 0;
550 /* Tell the assuan library about our commands */
551 static int
552 register_commands (ASSUAN_CONTEXT ctx)
554 static struct {
555 const char *name;
556 int cmd_id;
557 int (*handler)(ASSUAN_CONTEXT, char *line);
558 } table[] = {
559 { "ISTRUSTED", 0, cmd_istrusted },
560 { "HAVEKEY", 0, cmd_havekey },
561 { "SIGKEY", 0, cmd_sigkey },
562 { "SETKEY", 0, cmd_sigkey },
563 { "SETHASH", 0, cmd_sethash },
564 { "PKSIGN", 0, cmd_pksign },
565 { "PKDECRYPT", 0, cmd_pkdecrypt },
566 { "GENKEY", 0, cmd_genkey },
567 { "GET_PASSPHRASE",0, cmd_get_passphrase },
568 { "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
569 { "LISTTRUSTED", 0, cmd_listtrusted },
570 { "MARKTRUSTED", 0, cmd_marktrusted },
571 { "LEARN", 0, cmd_learn },
572 { "", ASSUAN_CMD_INPUT, NULL },
573 { "", ASSUAN_CMD_OUTPUT, NULL },
574 { NULL }
576 int i, j, rc;
578 for (i=j=0; table[i].name; i++)
580 rc = assuan_register_command (ctx,
581 table[i].cmd_id? table[i].cmd_id
582 : (ASSUAN_CMD_USER + j++),
583 table[i].name, table[i].handler);
584 if (rc)
585 return rc;
587 assuan_register_reset_notify (ctx, reset_notify);
588 assuan_register_option_handler (ctx, option_handler);
589 return 0;
593 /* Startup the server. If LISTEN_FD is given as -1, this is a simple
594 piper server, otherwise it is a regular server */
595 void
596 start_command_handler (int listen_fd)
598 int rc;
599 ASSUAN_CONTEXT ctx;
600 struct server_control_s ctrl;
602 memset (&ctrl, 0, sizeof ctrl);
605 if (listen_fd == -1)
607 int filedes[2];
609 filedes[0] = 0;
610 filedes[1] = 1;
611 rc = assuan_init_pipe_server (&ctx, filedes);
613 else
615 rc = assuan_init_socket_server (&ctx, listen_fd);
617 if (rc)
619 log_error ("failed to initialize the server: %s\n",
620 assuan_strerror(rc));
621 agent_exit (2);
623 rc = register_commands (ctx);
624 if (rc)
626 log_error ("failed to register commands with Assuan: %s\n",
627 assuan_strerror(rc));
628 agent_exit (2);
631 assuan_set_pointer (ctx, &ctrl);
632 ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
633 ctrl.server_local->assuan_ctx = ctx;
634 ctrl.server_local->message_fd = -1;
636 if (DBG_ASSUAN)
637 assuan_set_log_stream (ctx, log_get_stream ());
639 for (;;)
641 rc = assuan_accept (ctx);
642 if (rc == -1)
644 break;
646 else if (rc)
648 log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
649 break;
652 rc = assuan_process (ctx);
653 if (rc)
655 log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
656 continue;
661 assuan_deinit_server (ctx);