aboutsummaryrefslogtreecommitdiffstats
path: root/g10/passphrase.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2006-10-04 16:45:04 +0000
committerWerner Koch <[email protected]>2006-10-04 16:45:04 +0000
commit8684a78518691a9d033a8af2d743b8d2fa9d2351 (patch)
tree1e2ace515eb108ef7c191f008582cdd282d15ec2 /g10/passphrase.c
parentPreparing a new release (diff)
downloadgnupg-8684a78518691a9d033a8af2d743b8d2fa9d2351.tar.gz
gnupg-8684a78518691a9d033a8af2d743b8d2fa9d2351.zip
Fixed agent access for gpg.
Diffstat (limited to 'g10/passphrase.c')
-rw-r--r--g10/passphrase.c1048
1 files changed, 289 insertions, 759 deletions
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 1c5cf3b27..e8359814f 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -1,6 +1,6 @@
/* passphrase.c - Get a passphrase
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- * 2005 Free Software Foundation, Inc.
+ * 2005, 2006 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -27,13 +27,6 @@
#include <string.h>
#include <unistd.h>
#include <assert.h>
-#if !defined(HAVE_DOSISH_SYSTEM) && !defined(__riscos__)
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif
-#if defined (_WIN32)
-#include <windows.h>
-#endif
#include <errno.h>
#ifdef HAVE_LOCALE_H
#include <locale.h>
@@ -51,22 +44,96 @@
#include "main.h"
#include "i18n.h"
#include "status.h"
-#ifdef ENABLE_AGENT_SUPPORT
-#include "assuan.h"
-#endif /*ENABLE_AGENT_SUPPORT*/
+#include "call-agent.h"
+
static char *fd_passwd = NULL;
static char *next_pw = NULL;
static char *last_pw = NULL;
-static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create );
+
+/* Hash a passphrase using the supplied s2k. If create is true, create
+ a new salt or what else must be filled into the s2k for a new key.
+ always needs: dek->algo, s2k->mode, s2k->hash_algo. */
+static void
+hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k, int create )
+{
+ gcry_md_hd_t md;
+ int pass, i;
+ int used = 0;
+ int pwlen = strlen(pw);
+
+ assert ( s2k->hash_algo );
+ dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
+ if ( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) )
+ BUG();
+
+ if (gcry_md_open (&md, s2k->hash_algo, 1))
+ BUG ();
+ for (pass=0; used < dek->keylen ; pass++ )
+ {
+ if ( pass )
+ {
+ gcry_md_reset (md);
+ for (i=0; i < pass; i++ ) /* Preset the hash context. */
+ gcry_md_putc (md, 0 );
+ }
+
+ if ( s2k->mode == 1 || s2k->mode == 3 )
+ {
+ int len2 = pwlen + 8;
+ ulong count = len2;
+
+ if ( create && !pass )
+ {
+ gcry_randomize (s2k->salt, 8, GCRY_STRONG_RANDOM);
+ if ( s2k->mode == 3 )
+ s2k->count = 96; /* 65536 iterations. */
+ }
+
+ if ( s2k->mode == 3 )
+ {
+ count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
+ if ( count < len2 )
+ count = len2;
+ }
+
+ /* A little bit complicated because we need a ulong for count. */
+ while ( count > len2 ) /* maybe iterated+salted */
+ {
+ gcry_md_write ( md, s2k->salt, 8 );
+ gcry_md_write ( md, pw, pwlen );
+ count -= len2;
+ }
+ if ( count < 8 )
+ gcry_md_write ( md, s2k->salt, count );
+ else
+ {
+ gcry_md_write ( md, s2k->salt, 8 );
+ count -= 8;
+ gcry_md_write ( md, pw, count );
+ }
+ }
+ else
+ gcry_md_write ( md, pw, pwlen );
+ gcry_md_final( md );
+
+ i = gcry_md_get_algo_dlen ( s2k->hash_algo );
+ if ( i > dek->keylen - used )
+ i = dek->keylen - used;
+
+ memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i);
+ used += i;
+ }
+ gcry_md_close(md);
+}
+
+
int
have_static_passphrase()
{
- if ( opt.use_agent )
- return 0;
- return !!fd_passwd;
+ return 0;
}
/****************
@@ -76,11 +143,12 @@ have_static_passphrase()
void
set_next_passphrase( const char *s )
{
- xfree(next_pw);
- next_pw = NULL;
- if( s ) {
- next_pw = xmalloc_secure( strlen(s)+1 );
- strcpy(next_pw, s );
+ xfree(next_pw);
+ next_pw = NULL;
+ if ( s )
+ {
+ next_pw = xmalloc_secure( strlen(s)+1 );
+ strcpy (next_pw, s );
}
}
@@ -92,16 +160,16 @@ set_next_passphrase( const char *s )
char *
get_last_passphrase()
{
- char *p = last_pw;
- last_pw = NULL;
- return p;
+ char *p = last_pw;
+ last_pw = NULL;
+ return p;
}
/* As if we had used the passphrase - make it the last_pw. */
void
next_to_last_passphrase(void)
{
- if(next_pw)
+ if (next_pw)
{
last_pw=next_pw;
next_pw=NULL;
@@ -125,335 +193,16 @@ set_passphrase_from_string(const char *pass)
void
read_passphrase_from_fd( int fd )
{
- int i, len;
- char *pw;
-
- if ( opt.use_agent )
- { /* Not used but we have to do a dummy read, so that it won't end
- up at the begin of the message if the quite usual trick to
- prepend the passphtrase to the message is used. */
- char buf[1];
-
- while (!(read (fd, buf, 1) != 1 || *buf == '\n' ))
- ;
- *buf = 0;
- return;
- }
-
- if (!opt.batch )
- tty_printf("Reading passphrase from file descriptor %d ...", fd );
- for (pw = NULL, i = len = 100; ; i++ )
- {
- if (i >= len-1 )
- {
- char *pw2 = pw;
- len += 100;
- pw = xmalloc_secure( len );
- if( pw2 )
- {
- memcpy(pw, pw2, i );
- xfree (pw2);
- }
- else
- i=0;
- }
- if (read( fd, pw+i, 1) != 1 || pw[i] == '\n' )
- break;
- }
- pw[i] = 0;
- if (!opt.batch)
- tty_printf("\b\b\b \n" );
-
- xfree( fd_passwd );
- fd_passwd = pw;
-}
-
-
-
-#ifdef ENABLE_AGENT_SUPPORT
-/* Send one option to the gpg-agent. */
-static int
-agent_send_option (assuan_context_t ctx, const char *name, const char *value)
-{
- char *line;
- int rc;
-
- if (!value || !*value)
- return 0; /* Avoid sending empty option values. */
-
- line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 1);
- strcpy (stpcpy (stpcpy (stpcpy (line, "OPTION "), name), "="), value);
- rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- xfree (line);
- return rc? -1 : 0;
-}
-
-/* Send all required options to the gpg-agent. */
-static int
-agent_send_all_options (assuan_context_t ctx)
-{
- char *dft_display = NULL;
- const char *dft_ttyname = NULL;
- char *dft_ttytype = NULL;
- char *old_lc = NULL;
- char *dft_lc = NULL;
- int rc = 0;
-
- dft_display = getenv ("DISPLAY");
- if (opt.display || dft_display)
- {
- if (agent_send_option (ctx, "display",
- opt.display ? opt.display : dft_display))
- return -1;
- }
-
- if (!opt.ttyname)
- {
- const char *tmp;
-
- dft_ttyname = getenv ("GPG_TTY");
- if ((!dft_ttyname || !*dft_ttyname) && (tmp=ttyname (0)))
- dft_ttyname = tmp;
- if ((!dft_ttyname || !*dft_ttyname) && (tmp=tty_get_ttyname ()))
- dft_ttyname = tmp;
- }
- if (opt.ttyname || dft_ttyname)
- {
- if (agent_send_option (ctx, "ttyname",
- opt.ttyname ? opt.ttyname : dft_ttyname))
- return -1;
- }
-
- dft_ttytype = getenv ("TERM");
- if (opt.ttytype || (dft_ttyname && dft_ttytype))
- {
- if (agent_send_option (ctx, "ttytype",
- opt.ttyname ? opt.ttytype : dft_ttytype))
- return -1;
- }
-
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
- old_lc = setlocale (LC_CTYPE, NULL);
- if (old_lc)
- old_lc = xstrdup (old_lc);
- dft_lc = setlocale (LC_CTYPE, "");
-#endif
- if (opt.lc_ctype || (dft_ttyname && dft_lc))
- {
- rc = agent_send_option (ctx, "lc-ctype",
- opt.lc_ctype ? opt.lc_ctype : dft_lc);
- }
-#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
- if (old_lc)
- {
- setlocale (LC_CTYPE, old_lc);
- xfree (old_lc);
- }
-#endif
- if (rc)
- return rc;
-
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
- old_lc = setlocale (LC_MESSAGES, NULL);
- if (old_lc)
- old_lc = xstrdup (old_lc);
- dft_lc = setlocale (LC_MESSAGES, "");
-#endif
- if (opt.lc_messages || (dft_ttyname && dft_lc))
- {
- rc = agent_send_option (ctx, "lc-messages",
- opt.lc_messages ? opt.lc_messages : dft_lc);
- }
-#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
- if (old_lc)
- {
- setlocale (LC_MESSAGES, old_lc);
- xfree (old_lc);
- }
-#endif
- return rc;
-}
-#endif /*ENABLE_AGENT_SUPPORT*/
-
-
-/*
- * Open a connection to the agent and initializes the connection.
- * Returns: -1 on error; on success an Assuan context for that
- * connection is returned. With TRY set to true, no error messages
- * are printed and the use of the agent won't get disabled on failure.
- * If ORIG_CODESET is not NULL, the function will swithc the codeset
- * back to that one before printing error messages.
- */
-#ifdef ENABLE_AGENT_SUPPORT
-assuan_context_t
-agent_open (int try, const char *orig_codeset)
-{
- int rc;
- assuan_context_t ctx;
- char *infostr, *p;
- int prot;
- int pid;
-
- if (opt.gpg_agent_info)
- infostr = xstrdup (opt.gpg_agent_info);
- else
- {
- infostr = getenv ( "GPG_AGENT_INFO" );
- if (!infostr || !*infostr)
- {
- if (!try)
- {
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif /*ENABLE_NLS*/
- log_info (_("gpg-agent is not available in this session\n"));
- opt.use_agent = 0;
- }
- return NULL;
- }
- infostr = xstrdup ( infostr );
- }
-
- if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
- {
- if (!try)
- {
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif /*ENABLE_NLS*/
- log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
- opt.use_agent = 0;
- }
- xfree (infostr);
- return NULL;
- }
- *p++ = 0;
- pid = atoi (p);
- while (*p && *p != PATHSEP_C)
- p++;
- prot = *p? atoi (p+1) : 0;
- if (prot != 1)
- {
- if (!try)
- {
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif /*ENABLE_NLS*/
- log_error (_("gpg-agent protocol version %d is not supported\n"),
- prot);
- opt.use_agent = 0;
- }
- xfree (infostr);
- return NULL;
- }
-
- rc = assuan_socket_connect (&ctx, infostr, pid);
- if (rc)
- {
- if (!try)
- {
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif /*ENABLE_NLS*/
- log_error ( _("can't connect to `%s': %s\n"),
- infostr, assuan_strerror (rc));
- opt.use_agent = 0;
- }
- xfree (infostr );
- return NULL;
- }
- xfree (infostr);
-
- if (agent_send_all_options (ctx))
- {
- if (!try)
- {
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif /*ENABLE_NLS*/
- log_error (_("problem with the agent - disabling agent use\n"));
- opt.use_agent = 0;
- }
- assuan_disconnect (ctx);
- return NULL;
- }
-
- return ctx;
-}
-#endif/*ENABLE_AGENT_SUPPORT*/
-
-
-#ifdef ENABLE_AGENT_SUPPORT
-void
-agent_close (assuan_context_t ctx)
-{
- assuan_disconnect (ctx);
-}
-#endif /*ENABLE_AGENT_SUPPORT*/
-
-
-/* Copy the text ATEXT into the buffer P and do plus '+' and percent
- escaping. Note that the provided buffer needs to be 3 times the
- size of ATEXT plus 1. Returns a pointer to the leading Nul in P. */
-#ifdef ENABLE_AGENT_SUPPORT
-static char *
-percent_plus_escape (char *p, const char *atext)
-{
- const unsigned char *s;
-
- for (s=atext; *s; s++)
- {
- if (*s < ' ' || *s == '+')
- {
- sprintf (p, "%%%02X", *s);
- p += 3;
- }
- else if (*s == ' ')
- *p++ = '+';
- else
- *p++ = *s;
- }
- *p = 0;
- return p;
-}
-#endif /*ENABLE_AGENT_SUPPORT*/
-
-
-#ifdef ENABLE_AGENT_SUPPORT
-
-/* Object for the agent_okay_cb function. */
-struct agent_okay_cb_s {
- char *pw;
-};
-
-/* A callback used to get the passphrase from the okay line. See
- agent-get_passphrase for details. LINE is the rest of the OK
- status line without leading white spaces. */
-static assuan_error_t
-agent_okay_cb (void *opaque, const char *line)
-{
- struct agent_okay_cb_s *parm = opaque;
- int i;
-
- /* Note: If the malloc below fails we won't be able to wipe the
- memory at LINE given the current implementation of the Assuan
- code. There is no easy ay around this w/o adding a lot of more
- memory function code to allow wiping arbitrary stuff on memory
- failure. */
- parm->pw = xmalloc_secure (strlen (line)/2+2);
+ /* Not used but we have to do a dummy read, so that it won't end up
+ at the begin of the message if the quite usual trick to prepend
+ the passphtrase to the message is used. */
+ char buf[1];
- for (i=0; hexdigitp (line) && hexdigitp (line+1); line += 2)
- parm->pw[i++] = xtoi_2 (line);
- parm->pw[i] = 0;
- return 0;
+ while (!(read (fd, buf, 1) != 1 || *buf == '\n' ))
+ ;
+ *buf = 0;
+ return;
}
-#endif /*ENABLE_AGENT_SUPPORT*/
-
/*
@@ -462,26 +211,28 @@ agent_okay_cb (void *opaque, const char *line)
* 1: No cached passphrase FIXME: Not really implemented
* 2: Ditto, but change the text to "repeat entry"
*
- * Note that TRYAGAIN_TEXT must not be translated. If canceled is not
+ * Note that TRYAGAIN_TEXT must not be translated. If CANCELED is not
* NULL, the function does set it to 1 if the user canceled the
* operation. If CACHEID is not NULL, it will be used as the cacheID
* for the gpg-agent; if is NULL and a key fingerprint can be
* computed, this will be used as the cacheid.
*/
static char *
-agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
- const char *tryagain_text,
- const char *custom_description,
- const char *custom_prompt, int *canceled)
+passphrase_get ( u32 *keyid, int mode, const char *cacheid,
+ const char *tryagain_text,
+ const char *custom_description,
+ const char *custom_prompt, int *canceled)
{
-#ifdef ENABLE_AGENT_SUPPORT
+ int rc;
char *atext = NULL;
- assuan_context_t ctx = NULL;
char *pw = NULL;
PKT_public_key *pk = xmalloc_clear( sizeof *pk );
byte fpr[MAX_FINGERPRINT_LEN];
int have_fpr = 0;
char *orig_codeset = NULL;
+ char *my_prompt;
+ char hexfprbuf[20*2+1];
+ const char *my_cacheid;
if (canceled)
*canceled = 0;
@@ -513,16 +264,13 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
}
#endif
- if ( !(ctx = agent_open (0, orig_codeset)) )
- goto failure;
-
if (custom_description)
atext = native_to_utf8 (custom_description);
else if ( !mode && pk && keyid )
{
char *uid;
size_t uidlen;
- const char *algo_name = pubkey_algo_to_string ( pk->pubkey_algo );
+ const char *algo_name = gcry_pk_algo_name ( pk->pubkey_algo );
const char *timestr;
char *maink;
@@ -572,93 +320,35 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
else
atext = xstrdup ( _("Enter passphrase\n") );
- {
- char *line, *p;
- int i, rc;
- struct agent_okay_cb_s okay_cb_parm;
-
- if (!tryagain_text)
- tryagain_text = "X";
- else
- tryagain_text = _(tryagain_text);
-
- /* We allocate 23 times the needed space for thye texts so that
- there is enough space for escaping. */
- line = xmalloc (15 + 46
- + 3*strlen (atext)
- + 3*strlen (custom_prompt? custom_prompt:"")
- + (cacheid? (3*strlen (cacheid)): 0)
- + 3*strlen (tryagain_text)
- + 1);
- strcpy (line, "GET_PASSPHRASE ");
- p = line+15;
- if (!mode && cacheid)
- {
- p = percent_plus_escape (p, cacheid);
- }
- else if (!mode && have_fpr)
- {
- for (i=0; i < 20; i++, p +=2 )
- sprintf (p, "%02X", fpr[i]);
- }
- else
- *p++ = 'X'; /* No caching. */
- *p++ = ' ';
- p = percent_plus_escape (p, tryagain_text);
- *p++ = ' ';
+ if (!mode && cacheid)
+ my_cacheid = cacheid;
+ else if (!mode && have_fpr)
+ my_cacheid = bin2hex (fpr, 20, hexfprbuf);
+ else
+ my_cacheid = NULL;
- /* The prompt. */
- if (custom_prompt)
- {
- char *tmp = native_to_utf8 (custom_prompt);
- p = percent_plus_escape (p, tmp);
- xfree (tmp);
- }
- else
- *p++ = 'X'; /* Use the standard prompt. */
- *p++ = ' ';
+ if (tryagain_text)
+ tryagain_text = _(tryagain_text);
- /* Copy description. */
- percent_plus_escape (p, atext);
+ my_prompt = custom_prompt ? native_to_utf8 (custom_prompt): NULL;
- /* Call gpg-agent. */
- memset (&okay_cb_parm, 0, sizeof okay_cb_parm);
- rc = assuan_transact2 (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL,
- agent_okay_cb, &okay_cb_parm);
+ rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext, &pw);
+
+ xfree (my_prompt);
+ xfree (atext); atext = NULL;
- xfree (line);
- xfree (atext); atext = NULL;
- if (!rc)
- {
- assert (okay_cb_parm.pw);
- pw = okay_cb_parm.pw;
- agent_close (ctx);
- if (pk)
- free_public_key( pk );
-#ifdef ENABLE_NLS
- if (orig_codeset)
- bind_textdomain_codeset (PACKAGE, orig_codeset);
-#endif
- xfree (orig_codeset);
- return pw;
- }
- else if (rc && (rc & 0xffff) == 99)
- {
- /* 99 is GPG_ERR_CANCELED. */
- log_info (_("cancelled by user\n") );
- if (canceled)
- *canceled = 1;
- }
- else
- {
- log_error (_("problem with the agent - disabling agent use\n"));
- opt.use_agent = 0;
- }
- }
+ if (!rc)
+ ;
+ else if ( gpg_err_code (rc) == GPG_ERR_CANCELED )
+ {
+ log_info (_("cancelled by user\n") );
+ if (canceled)
+ *canceled = 1;
+ }
+ else
+ log_error (_("problem with the agent: %s\n"), gpg_strerror (rc));
-
- failure:
#ifdef ENABLE_NLS
if (orig_codeset)
{
@@ -666,15 +356,14 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
xfree (orig_codeset);
}
#endif
- xfree (atext);
- agent_close (ctx);
- xfree (pw );
if (pk)
free_public_key( pk );
-
-#endif /*ENABLE_AGENT_SUPPORT*/
-
- return NULL;
+ if (rc)
+ {
+ xfree (pw);
+ return NULL;
+ }
+ return pw;
}
@@ -685,73 +374,36 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
void
passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
{
-#ifdef ENABLE_AGENT_SUPPORT
- assuan_context_t ctx = NULL;
- PKT_public_key *pk;
- byte fpr[MAX_FINGERPRINT_LEN];
-
-#if MAX_FINGERPRINT_LEN < 20
-#error agent needs a 20 byte fingerprint
-#endif
+ int rc;
- if (!opt.use_agent)
- return;
-
if (!cacheid)
{
+ PKT_public_key *pk;
+# if MAX_FINGERPRINT_LEN < 20
+# error agent needs a 20 byte fingerprint
+# endif
+ byte fpr[MAX_FINGERPRINT_LEN];
+ char hexfprbuf[2*20+1];
+ size_t dummy;
+
pk = xcalloc (1, sizeof *pk);
- memset (fpr, 0, MAX_FINGERPRINT_LEN );
- if( !keyid || get_pubkey( pk, keyid ) )
+ if ( !keyid || get_pubkey( pk, keyid ) )
{
- goto failure; /* oops: no key for some reason */
+ log_error ("key not found in passphrase_clear_cache\n");
+ free_public_key (pk);
+ return;
}
-
- {
- size_t dummy;
- fingerprint_from_pk( pk, fpr, &dummy );
- }
+ memset (fpr, 0, MAX_FINGERPRINT_LEN );
+ fingerprint_from_pk ( pk, fpr, &dummy );
+ bin2hex (fpr, 20, hexfprbuf);
+ rc = agent_clear_passphrase (hexfprbuf);
+ free_public_key ( pk );
}
else
- pk = NULL;
-
- if ( !(ctx = agent_open (0, NULL)) )
- goto failure;
+ rc = agent_clear_passphrase (cacheid);
- {
- char *line, *p;
- int i, rc;
-
- if (cacheid)
- {
- line = xmalloc (17 + 3*strlen (cacheid) + 2);
- strcpy (line, "CLEAR_PASSPHRASE ");
- p = line+17;
- p = percent_plus_escape (p, cacheid);
- }
- else
- {
- line = xmalloc (17 + 40 + 2);
- strcpy (line, "CLEAR_PASSPHRASE ");
- p = line+17;
- for (i=0; i < 20; i++, p +=2 )
- sprintf (p, "%02X", fpr[i]);
- }
- *p = 0;
-
- rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- xfree (line);
- if (rc)
- {
- log_error (_("problem with the agent - disabling agent use\n"));
- opt.use_agent = 0;
- }
- }
-
- failure:
- agent_close (ctx);
- if (pk)
- free_public_key( pk );
-#endif /*ENABLE_AGENT_SUPPORT*/
+ if (rc)
+ log_error (_("problem with the agent: %s\n"), gpg_strerror (rc));
}
@@ -782,36 +434,9 @@ ask_passphrase (const char *description,
tty_printf ("\n%s\n",description);
}
- agent_died:
- if ( opt.use_agent )
- {
- pw = agent_get_passphrase (NULL, 0, cacheid,
- tryagain_text, description, prompt,
- canceled );
- if (!pw)
- {
- if (!opt.use_agent)
- goto agent_died;
- pw = NULL;
- }
- }
- else if (fd_passwd)
- {
- pw = xmalloc_secure (strlen(fd_passwd)+1);
- strcpy (pw, fd_passwd);
- }
- else if (opt.batch)
- {
- log_error(_("can't query passphrase in batch mode\n"));
- pw = NULL;
- }
- else {
- if (tryagain_text)
- tty_printf(_("%s.\n"), tryagain_text);
- pw = cpr_get_hidden(promptid? promptid : "passphrase.ask",
- prompt?prompt : _("Enter passphrase: ") );
- tty_kill_prompt();
- }
+ pw = passphrase_get (NULL, 0, cacheid,
+ tryagain_text, description, prompt,
+ canceled );
if (!pw || !*pw)
write_status( STATUS_MISSING_PASSPHRASE );
@@ -828,246 +453,151 @@ ask_passphrase (const char *description,
2: Ditto, but change the text to "repeat entry"
*/
DEK *
-passphrase_to_dek( u32 *keyid, int pubkey_algo,
+passphrase_to_dek (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
const char *tryagain_text, int *canceled)
{
- char *pw = NULL;
- DEK *dek;
- STRING2KEY help_s2k;
-
- if (canceled)
- *canceled = 0;
-
- if( !s2k ) {
- /* This is used for the old rfc1991 mode
- * Note: This must match the code in encode.c with opt.rfc1991 set */
- s2k = &help_s2k;
- s2k->mode = 0;
- s2k->hash_algo = S2K_DIGEST_ALGO;
+ char *pw = NULL;
+ DEK *dek;
+ STRING2KEY help_s2k;
+
+ if (canceled)
+ *canceled = 0;
+
+ if ( !s2k )
+ {
+ /* This is used for the old rfc1991 mode
+ * Note: This must match the code in encode.c with opt.rfc1991 set */
+ s2k = &help_s2k;
+ s2k->mode = 0;
+ s2k->hash_algo = S2K_DIGEST_ALGO;
}
- /* If we do not have a passphrase available in NEXT_PW and status
- information are request, we print them now. */
- if( !next_pw && is_status_enabled() ) {
- char buf[50];
-
- if( keyid ) {
- u32 used_kid[2];
- char *us;
-
- if( keyid[2] && keyid[3] ) {
- used_kid[0] = keyid[2];
- used_kid[1] = keyid[3];
+ /* If we do not have a passphrase available in NEXT_PW and status
+ information are request, we print them now. */
+ if ( !next_pw && is_status_enabled() )
+ {
+ char buf[50];
+
+ if ( keyid )
+ {
+ u32 used_kid[2];
+ char *us;
+
+ if ( keyid[2] && keyid[3] )
+ {
+ used_kid[0] = keyid[2];
+ used_kid[1] = keyid[3];
}
- else {
- used_kid[0] = keyid[0];
- used_kid[1] = keyid[1];
+ else
+ {
+ used_kid[0] = keyid[0];
+ used_kid[1] = keyid[1];
}
-
- us = get_long_user_id_string( keyid );
- write_status_text( STATUS_USERID_HINT, us );
- xfree(us);
-
- sprintf( buf, "%08lX%08lX %08lX%08lX %d 0",
- (ulong)keyid[0], (ulong)keyid[1],
- (ulong)used_kid[0], (ulong)used_kid[1],
- pubkey_algo );
-
- write_status_text( STATUS_NEED_PASSPHRASE, buf );
+
+ us = get_long_user_id_string ( keyid );
+ write_status_text ( STATUS_USERID_HINT, us );
+ xfree(us);
+
+ snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
+ (ulong)keyid[0], (ulong)keyid[1],
+ (ulong)used_kid[0], (ulong)used_kid[1],
+ pubkey_algo );
+
+ write_status_text ( STATUS_NEED_PASSPHRASE, buf );
}
- else {
- sprintf( buf, "%d %d %d", cipher_algo, s2k->mode, s2k->hash_algo );
- write_status_text( STATUS_NEED_PASSPHRASE_SYM, buf );
+ else
+ {
+ snprintf (buf, sizeof buf -1, "%d %d %d",
+ cipher_algo, s2k->mode, s2k->hash_algo );
+ write_status_text ( STATUS_NEED_PASSPHRASE_SYM, buf );
}
}
- /* If we do have a keyID, we do not have a passphrase available in
- NEXT_PW, we are not running in batch mode and we do not want to
- ignore the passphrase cache (mode!=1), print a prompt with
- information on that key. */
- if( keyid && !opt.batch && !next_pw && mode!=1 ) {
- PKT_public_key *pk = xmalloc_clear( sizeof *pk );
- char *p;
-
- p=get_user_id_native(keyid);
- tty_printf("\n");
- tty_printf(_("You need a passphrase to unlock the secret key for\n"
- "user: \"%s\"\n"),p);
- xfree(p);
+ /* If we do have a keyID, we do not have a passphrase available in
+ NEXT_PW, we are not running in batch mode and we do not want to
+ ignore the passphrase cache (mode!=1), print a prompt with
+ information on that key. */
+ if ( keyid && !opt.batch && !next_pw && mode!=1 )
+ {
+ PKT_public_key *pk = xmalloc_clear( sizeof *pk );
+ char *p;
+
+ p = get_user_id_native(keyid);
+ tty_printf ("\n");
+ tty_printf (_("You need a passphrase to unlock the secret key for\n"
+ "user: \"%s\"\n"),p);
+ xfree(p);
- if( !get_pubkey( pk, keyid ) ) {
- const char *s = gcry_pk_algo_name ( pk->pubkey_algo );
- tty_printf( _("%u-bit %s key, ID %s, created %s"),
- nbits_from_pk( pk ), s?s:"?", keystr(keyid),
- strtimestamp(pk->timestamp) );
- if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
- && keyid[1] != keyid[3] )
- {
- if(keystrlen()>10)
- {
- tty_printf("\n");
- tty_printf(_(" (subkey on main key ID %s)"),
- keystr(&keyid[2]) );
- }
- else
- tty_printf( _(" (main key ID %s)"), keystr(&keyid[2]) );
- }
- tty_printf("\n");
+ if ( !get_pubkey( pk, keyid ) )
+ {
+ const char *s = gcry_pk_algo_name ( pk->pubkey_algo );
+
+ tty_printf (_("%u-bit %s key, ID %s, created %s"),
+ nbits_from_pk( pk ), s?s:"?", keystr(keyid),
+ strtimestamp(pk->timestamp) );
+ if ( keyid[2] && keyid[3]
+ && keyid[0] != keyid[2] && keyid[1] != keyid[3] )
+ {
+ if ( keystrlen () > 10 )
+ {
+ tty_printf ("\n");
+ tty_printf (_(" (subkey on main key ID %s)"),
+ keystr(&keyid[2]) );
+ }
+ else
+ tty_printf ( _(" (main key ID %s)"), keystr(&keyid[2]) );
+ }
+ tty_printf("\n");
}
- tty_printf("\n");
- if (pk)
- free_public_key( pk );
+ tty_printf("\n");
+ if (pk)
+ free_public_key( pk );
}
- agent_died:
- if( next_pw ) {
- /* Simply return the passphrase we already have in NEXT_PW. */
- pw = next_pw;
- next_pw = NULL;
+ if ( next_pw )
+ {
+ /* Simply return the passphrase we already have in NEXT_PW. */
+ pw = next_pw;
+ next_pw = NULL;
}
- else if ( opt.use_agent ) {
+ else
+ {
/* Divert to the gpg-agent. */
- pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, NULL,
- tryagain_text, NULL, NULL, canceled );
- if (!pw)
- {
- if (!opt.use_agent)
- goto agent_died;
- pw = xstrdup ("");
- }
- if( *pw && mode == 2 ) {
- char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL, NULL,
- NULL, canceled );
- if (!pw2)
- {
- if (!opt.use_agent)
- {
- xfree (pw);
- pw = NULL;
- goto agent_died;
- }
- pw2 = xstrdup ("");
- }
- if( strcmp(pw, pw2) ) {
- xfree(pw2);
- xfree(pw);
- return NULL;
- }
- xfree(pw2);
- }
- }
- else if( fd_passwd ) {
- /* Return the passphrase we have store in FD_PASSWD. */
- pw = xmalloc_secure( strlen(fd_passwd)+1 );
- strcpy( pw, fd_passwd );
- }
- else if( opt.batch )
- {
- log_error(_("can't query passphrase in batch mode\n"));
- pw = xstrdup( "" ); /* return an empty passphrase */
- }
- else {
- /* Read the passphrase from the tty or the command-fd. */
- pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") );
- tty_kill_prompt();
- if( mode == 2 && !cpr_enabled() ) {
- char *pw2 = cpr_get_hidden("passphrase.repeat",
- _("Repeat passphrase: ") );
- tty_kill_prompt();
- if( strcmp(pw, pw2) ) {
- xfree(pw2);
- xfree(pw);
- return NULL;
- }
- xfree(pw2);
+ pw = passphrase_get ( keyid, mode == 2? 1: 0, NULL,
+ tryagain_text, NULL, NULL, canceled );
+ if (!pw)
+ pw = xstrdup ("");
+ if ( *pw && mode == 2 )
+ {
+ char *pw2 = passphrase_get ( keyid, 2, NULL, NULL, NULL,
+ NULL, canceled );
+ if (!pw2)
+ pw2 = xstrdup ("");
+ if ( strcmp(pw, pw2) )
+ {
+ xfree(pw2);
+ xfree(pw);
+ return NULL;
+ }
+ xfree(pw2);
}
}
+
+ if ( !pw || !*pw )
+ write_status( STATUS_MISSING_PASSPHRASE );
- if( !pw || !*pw )
- write_status( STATUS_MISSING_PASSPHRASE );
-
- /* Hash the passphrase and store it in a newly allocated DEK
- object. Keep a copy of the passphrase in LAST_PW for use by
- get_last_passphrase(). */
- dek = xmalloc_secure_clear ( sizeof *dek );
- dek->algo = cipher_algo;
- if( !*pw && mode == 2 )
- dek->keylen = 0;
- else
- hash_passphrase( dek, pw, s2k, mode==2 );
- xfree(last_pw);
- last_pw = pw;
- return dek;
-}
-
-
-/****************
- * Hash a passphrase using the supplied s2k. If create is true, create
- * a new salt or what else must be filled into the s2k for a new key.
- * always needs: dek->algo, s2k->mode, s2k->hash_algo.
- */
-static void
-hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
-{
- gcry_md_hd_t md;
- int pass, i;
- int used = 0;
- int pwlen = strlen(pw);
-
- assert( s2k->hash_algo );
- dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
- if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) )
- BUG();
-
- if (gcry_md_open (&md, s2k->hash_algo, 1))
- BUG ();
- for(pass=0; used < dek->keylen ; pass++ ) {
- if( pass ) {
- gcry_md_reset (md);
- for(i=0; i < pass; i++ ) /* preset the hash context */
- gcry_md_putc (md, 0 );
- }
-
- if( s2k->mode == 1 || s2k->mode == 3 ) {
- int len2 = pwlen + 8;
- ulong count = len2;
-
- if( create && !pass ) {
- gcry_randomize (s2k->salt, 8, GCRY_STRONG_RANDOM);
- if( s2k->mode == 3 )
- s2k->count = 96; /* 65536 iterations */
- }
-
- if( s2k->mode == 3 ) {
- count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
- if( count < len2 )
- count = len2;
- }
- /* a little bit complicated because we need a ulong for count */
- while( count > len2 ) { /* maybe iterated+salted */
- gcry_md_write ( md, s2k->salt, 8 );
- gcry_md_write ( md, pw, pwlen );
- count -= len2;
- }
- if( count < 8 )
- gcry_md_write ( md, s2k->salt, count );
- else {
- gcry_md_write ( md, s2k->salt, 8 );
- count -= 8;
- gcry_md_write ( md, pw, count );
- }
- }
- else
- gcry_md_write ( md, pw, pwlen );
- gcry_md_final( md );
- i = gcry_md_get_algo_dlen ( s2k->hash_algo );
- if( i > dek->keylen - used )
- i = dek->keylen - used;
- memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i);
- used += i;
- }
- gcry_md_close(md);
+ /* Hash the passphrase and store it in a newly allocated DEK object.
+ Keep a copy of the passphrase in LAST_PW for use by
+ get_last_passphrase(). */
+ dek = xmalloc_secure_clear ( sizeof *dek );
+ dek->algo = cipher_algo;
+ if ( !*pw && mode == 2 )
+ dek->keylen = 0;
+ else
+ hash_passphrase( dek, pw, s2k, mode==2 );
+ xfree(last_pw);
+ last_pw = pw;
+ return dek;
}
-