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. */
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
47 /* Data used to associate an Assuan context with local server data */
48 struct server_local_s
{
49 ASSUAN_CONTEXT assuan_ctx
;
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 */
70 has_option (const char *line
, const char *name
)
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
87 cmd_istrusted (ASSUAN_CONTEXT ctx
, char *line
)
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");
101 strcpy (fpr
, "00000000");
104 for (p
=line
; i
< 40; p
++, i
++)
105 fpr
[i
] = *p
>= 'a'? (*p
& 0xdf): *p
;
107 rc
= agent_istrusted (fpr
);
111 return ASSUAN_Not_Trusted
;
113 return map_to_assuan_status (rc
);
118 List all entries from the trustlist */
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*/
130 cmd_marktrusted (ASSUAN_CONTEXT ctx
, char *line
)
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");
145 strcpy (fpr
, "00000000");
148 for (p
=line
; i
< 40; p
++, i
++)
149 fpr
[i
] = *p
>= 'a'? (*p
& 0xdf): *p
;
155 if ( (flag
!= 'S' && flag
!= 'P') || !spacep (p
) )
156 return set_error (Parameter_Error
, "invalid flag - must be P or S");
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 */
171 cmd_havekey (ASSUAN_CONTEXT ctx
, char *line
)
175 unsigned char buf
[20];
177 /* parse the hash value */
178 for (p
=line
,n
=0; hexdigitp (p
); p
++, n
++)
181 return set_error (Parameter_Error
, "invalid hexstring");
183 return set_error (Parameter_Error
, "odd number of digits");
186 return set_error (Parameter_Error
, "invalid length of keygrip");
188 for (p
=line
, n
=0; n
< 20; p
+= 2, n
++)
191 if (agent_key_available (buf
))
192 return ASSUAN_No_Secret_Key
;
198 /* SIGKEY <hexstring_with_keygrip>
199 SETKEY <hexstring_with_keygrip>
201 Set the key used for a sign or decrypt operation */
203 cmd_sigkey (ASSUAN_CONTEXT ctx
, char *line
)
207 CTRL ctrl
= assuan_get_pointer (ctx
);
210 /* parse the hash value */
211 for (p
=line
,n
=0; hexdigitp (p
); p
++, n
++)
214 return set_error (Parameter_Error
, "invalid hexstring");
216 return set_error (Parameter_Error
, "odd number of digits");
219 return set_error (Parameter_Error
, "invalid length of keygrip");
222 for (p
=line
, n
=0; n
< 20; p
+= 2, n
++)
224 ctrl
->have_keygrip
= 1;
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. */
233 cmd_sethash (ASSUAN_CONTEXT ctx
, char *line
)
237 CTRL ctrl
= assuan_get_pointer (ctx
);
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
++)
254 return set_error (Parameter_Error
, "invalid hexstring");
256 return set_error (Parameter_Error
, "odd number of digits");
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
++)
267 for (; n
< ctrl
->digest
.valuelen
; n
++)
275 Perform the actual sign operation. Neither input nor output are
276 sensitive to eavesdropping */
278 cmd_pksign (ASSUAN_CONTEXT ctx
, char *line
)
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 */
292 cmd_pkdecrypt (ASSUAN_CONTEXT ctx
, char *line
)
295 CTRL ctrl
= assuan_get_pointer (ctx
);
299 /* First inquire the data to decrypt */
300 rc
= assuan_inquire (ctx
, "CIPHERTEXT",
301 &value
, &valuelen
, MAXLEN_CIPHERTEXT
);
305 rc
= agent_pkdecrypt (ctrl
, value
, valuelen
, assuan_get_data_fp (ctx
));
307 return map_to_assuan_status (rc
);
313 Generate a new key, store the secret part and return the public
314 part. Here is an example transaction:
318 C: D (genkey (rsa (nbits 1024)))
321 S: D (rsa (n 326487324683264) (e 10001)))
326 cmd_genkey (ASSUAN_CONTEXT ctx
, char *line
)
328 CTRL ctrl
= assuan_get_pointer (ctx
);
333 /* First inquire the parameters */
334 rc
= assuan_inquire (ctx
, "KEYPARAM", &value
, &valuelen
, MAXLEN_KEYPARAM
);
338 rc
= agent_genkey (ctrl
, value
, valuelen
, assuan_get_data_fp (ctx
));
340 return map_to_assuan_status (rc
);
345 plus_to_blank (char *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.
366 cmd_get_passphrase (ASSUAN_CONTEXT ctx
, char *line
)
371 char *cacheid
= NULL
, *desc
= NULL
, *prompt
= NULL
, *errtext
= NULL
;
374 /* parse the stuff */
375 for (p
=line
; *p
== ' '; p
++)
378 p
= strchr (cacheid
, ' ');
385 p
= strchr (errtext
, ' ');
392 p
= strchr (prompt
, ' ');
399 p
= strchr (desc
, ' ');
401 *p
= 0; /* ignore garbage */
405 if (!cacheid
|| !*cacheid
|| strlen (cacheid
) > 50)
406 return set_error (Parameter_Error
, "invalid length of cacheID");
408 return set_error (Parameter_Error
, "no description given");
410 if (!strcmp (cacheid
, "X"))
412 if (!strcmp (errtext
, "X"))
414 if (!strcmp (prompt
, "X"))
416 if (!strcmp (desc
, "X"))
419 /* Note: we store the hexified versions in the cache. */
420 pw
= cacheid
? agent_get_cache (cacheid
) : NULL
;
423 assuan_begin_confidential (ctx
);
424 rc
= assuan_set_okay_line (ctx
, pw
);
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) */
433 plus_to_blank (errtext
);
435 plus_to_blank (prompt
);
437 plus_to_blank (desc
);
439 rc
= agent_get_passphrase (&response
, desc
, prompt
, errtext
);
443 agent_put_cache (cacheid
, response
, 0);
444 assuan_begin_confidential (ctx
);
445 rc
= assuan_set_okay_line (ctx
, 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.
461 cmd_clear_passphrase (ASSUAN_CONTEXT ctx
, char *line
)
463 char *cacheid
= NULL
;
466 /* parse the stuff */
467 for (p
=line
; *p
== ' '; p
++)
470 p
= strchr (cacheid
, ' ');
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);
483 Learn something about the currently inserted smartcard. With
484 --send the new certificates are send back. */
486 cmd_learn (ASSUAN_CONTEXT ctx
, char *line
)
490 rc
= agent_handle_learn (has_option (line
, "--send")? ctx
: NULL
);
492 log_error ("agent_handle_learn failed: %s\n", gnupg_strerror (rc
));
493 return map_to_assuan_status (rc
);
499 option_handler (ASSUAN_CONTEXT ctx
, const char *key
, const char *value
)
501 CTRL ctrl
= assuan_get_pointer (ctx
);
503 if (!strcmp (key
, "display"))
507 opt
.display
= strdup (value
);
509 return ASSUAN_Out_Of_Core
;
511 else if (!strcmp (key
, "ttyname"))
515 opt
.ttyname
= strdup (value
);
517 return ASSUAN_Out_Of_Core
;
519 else if (!strcmp (key
, "ttytype"))
523 opt
.ttytype
= strdup (value
);
525 return ASSUAN_Out_Of_Core
;
527 else if (!strcmp (key
, "lc-ctype"))
531 opt
.lc_ctype
= strdup (value
);
533 return ASSUAN_Out_Of_Core
;
535 else if (!strcmp (key
, "lc-messages"))
538 free (opt
.lc_messages
);
539 opt
.lc_messages
= strdup (value
);
540 if (!opt
.lc_messages
)
541 return ASSUAN_Out_Of_Core
;
544 return ASSUAN_Invalid_Option
;
550 /* Tell the assuan library about our commands */
552 register_commands (ASSUAN_CONTEXT ctx
)
557 int (*handler
)(ASSUAN_CONTEXT
, char *line
);
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
},
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
);
587 assuan_register_reset_notify (ctx
, reset_notify
);
588 assuan_register_option_handler (ctx
, option_handler
);
593 /* Startup the server. If LISTEN_FD is given as -1, this is a simple
594 piper server, otherwise it is a regular server */
596 start_command_handler (int listen_fd
)
600 struct server_control_s ctrl
;
602 memset (&ctrl
, 0, sizeof ctrl
);
611 rc
= assuan_init_pipe_server (&ctx
, filedes
);
615 rc
= assuan_init_socket_server (&ctx
, listen_fd
);
619 log_error ("failed to initialize the server: %s\n",
620 assuan_strerror(rc
));
623 rc
= register_commands (ctx
);
626 log_error ("failed to register commands with Assuan: %s\n",
627 assuan_strerror(rc
));
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;
637 assuan_set_log_stream (ctx
, log_get_stream ());
641 rc
= assuan_accept (ctx
);
648 log_info ("Assuan accept problem: %s\n", assuan_strerror (rc
));
652 rc
= assuan_process (ctx
);
655 log_info ("Assuan processing failed: %s\n", assuan_strerror (rc
));
661 assuan_deinit_server (ctx
);