summaryrefslogtreecommitdiffstats
path: root/tools/symcryptrun.c
diff options
context:
space:
mode:
authorMarcus Brinkmann <mb@g10code.com>2005-07-04 06:58:04 +0200
committerMarcus Brinkmann <mb@g10code.com>2005-07-04 06:58:04 +0200
commit53a1347fbebb40a7e37a2751f1d55913dac5d3a2 (patch)
treedf157c6e10fc61c534f814579ddad1e7e6fc46b4 /tools/symcryptrun.c
parent2005-07-04 Marcus Brinkmann <marcus@g10code.de> (diff)
downloadgnupg2-53a1347fbebb40a7e37a2751f1d55913dac5d3a2.tar.xz
gnupg2-53a1347fbebb40a7e37a2751f1d55913dac5d3a2.zip
2005-07-04 Marcus Brinkmann <marcus@g10code.de>
* symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols, use instead constants. (hash_string): New function copied from simple-gettext.c. (confucius_get_pass): Take new argument CACHEID. (confucius_process): Calculate cacheid and pass it to confucius_get_pass. Clear passphrase from cache if necessary.
Diffstat (limited to '')
-rw-r--r--tools/symcryptrun.c68
1 files changed, 62 insertions, 6 deletions
diff --git a/tools/symcryptrun.c b/tools/symcryptrun.c
index fcecf1770..075e0b444 100644
--- a/tools/symcryptrun.c
+++ b/tools/symcryptrun.c
@@ -56,6 +56,9 @@
Other classes may be added in the future. */
+#define SYMC_BAD_PASSPHRASE 2
+#define SYMC_CANCELED 3
+
#include <config.h>
@@ -108,6 +111,37 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
}
+/* From simple-gettext.c. */
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+/* The so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+
+static __inline__ ulong
+hash_string( const char *str_param )
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned long int) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
+
+
/* Constants to identify the commands and options. */
enum cmd_and_opt_values
{
@@ -413,9 +447,10 @@ confucius_copy_file (char *infile, char *outfile, int plain)
pointer, it will be set to true or false, depending on if the user
canceled the operation or not. On error (including cancelation), a
null pointer is returned. The passphrase must be deallocated with
- confucius_drop_pass. */
+ confucius_drop_pass. CACHEID is the ID to be used for passphrase
+ caching and can be NULL to disable caching. */
char *
-confucius_get_pass (int again, int *canceled)
+confucius_get_pass (const char *cacheid, int again, int *canceled)
{
int err;
char *pw;
@@ -444,7 +479,7 @@ confucius_get_pass (int again, int *canceled)
}
#endif
- pw = simple_pwquery (NULL,
+ pw = simple_pwquery (cacheid,
again ? _("does not match - try again"):NULL,
_("Passphrase:"), NULL, &err);
@@ -497,6 +532,7 @@ confucius_process (int mode, char *infile, char *outfile,
pid_t pid;
pid_t wpid;
int tries = 0;
+ char cacheid[40];
signal (SIGPIPE, SIG_IGN);
@@ -518,6 +554,10 @@ confucius_process (int mode, char *infile, char *outfile,
return 1;
}
+ /* Generate a hash from the keyfile name for caching. */
+ snprintf (cacheid, sizeof (cacheid), "confucius:%lu",
+ hash_string (opt.keyfile));
+ cacheid[sizeof (cacheid) - 1] = '\0';
args = malloc (sizeof (char *) * (10 + argc));
if (!args)
{
@@ -708,13 +748,20 @@ confucius_process (int mode, char *infile, char *outfile,
char *pass;
int canceled;
- pass = confucius_get_pass (tries ? 1 : 0, &canceled);
+ /* If this is not the first attempt, the
+ passphrase seems to be wrong, so clear the
+ cache. */
+ if (tries)
+ simple_pwclear (cacheid);
+
+ pass = confucius_get_pass (cacheid,
+ tries ? 1 : 0, &canceled);
if (!pass)
{
kill (pid, SIGTERM);
close (master);
close (cstderr[0]);
- return canceled ? 3 : 1;
+ return canceled ? SYMC_CANCELED : 1;
}
write (master, pass, strlen (pass));
write (master, "\n", 1);
@@ -736,6 +783,8 @@ confucius_process (int mode, char *infile, char *outfile,
log_error (_("waitpid failed: %s\n"), strerror (errno));
kill (pid, SIGTERM);
+ /* State of cached password is unclear. Just remove it. */
+ simple_pwclear (cacheid);
return 1;
}
else
@@ -746,15 +795,22 @@ confucius_process (int mode, char *infile, char *outfile,
if (!WIFEXITED (res))
{
log_error (_("child aborted with status %i\n"), res);
+
+ /* State of cached password is unclear. Just remove it. */
+ simple_pwclear (cacheid);
+
return 1;
}
if (WEXITSTATUS (res))
{
+ /* The passphrase was wrong. Remove it from the cache. */
+ simple_pwclear (cacheid);
+
/* We probably exceeded our number of attempts at guessing
the password. */
if (tries >= 3)
- return 2;
+ return SYMC_BAD_PASSPHRASE;
else
return 1;
}