aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog18
-rw-r--r--g10/call-agent.c208
-rw-r--r--g10/call-agent.h15
-rw-r--r--g10/gpg.c88
-rw-r--r--g10/options.h2
-rw-r--r--g10/passphrase.c1048
-rw-r--r--g10/seckey-cert.c2
7 files changed, 476 insertions, 905 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 21dedf1d9..fc632a9b1 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,8 +1,26 @@
2006-10-04 Werner Koch <[email protected]>
+ * call-agent.c (agent_havekey): Removed.
+ (percent_plus_escape): New.
+ (agent_get_passphrase): New.
+ (agent_clear_passphrase): New.
+
+ * passphrase.c: Changed so that we always require the agent.
+ (agent_send_option, agent_send_all_options, agent_open): Removed.
+ (agent_get_passphrase): Cleaned up. Does now use the call-agent
+ functions. Renamed to
+ (passphrase_get): .. this. Changed all callers.
+ (passphrase_clear_cache): Rewritten.
+ (passphrase_to_dek, hash_passphrase): Re-indented.
+
+ * gpg.c (main): Made --use-agent a dummy option.
+ * seckey-cert.c (check_secret_key): We require the agent, so always
+ allow for 3 tries.
+
* gpg.c (main): Print a warning if -sat has been used.
(main): Removed the special treatment of the -k option. -k is now
an alias for --list-keys.
+ (main): Removed --list-ownertrust.
2006-10-02 Werner Koch <[email protected]>
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 202865f70..30b46fa99 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -218,6 +218,30 @@ unescape_status_string (const unsigned char *s)
return buffer;
}
+/* 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. */
+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;
+}
+
/* Take a 20 byte hexencoded string and put it into the the provided
20 byte buffer FPR in binary format. */
static int
@@ -258,93 +282,6 @@ store_serialno (const char *line)
-#if 0
-/* Handle a KEYPARMS inquiry. Note, we only send the data,
- assuan_transact takes care of flushing and writing the end */
-static int
-inq_genkey_parms (void *opaque, const char *keyword)
-{
- struct genkey_parm_s *parm = opaque;
- int rc;
-
- rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
- return rc;
-}
-
-
-
-/* Call the agent to generate a new key */
-int
-agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
-{
- int rc;
- struct genkey_parm_s gk_parm;
- membuf_t data;
- size_t len;
- char *buf;
-
- *r_pubkey = NULL;
- rc = start_agent ();
- if (rc)
- return rc;
-
- rc = assuan_transact (agent_ctx, "RESET", NULL, NULL,
- NULL, NULL, NULL, NULL);
- if (rc)
- return rc;
-
- init_membuf (&data, 1024);
- gk_parm.ctx = agent_ctx;
- gk_parm.sexp = keyparms;
- gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
- if (!gk_parm.sexplen)
- return gpg_error (GPG_ERR_INV_VALUE);
- rc = assuan_transact (agent_ctx, "GENKEY",
- membuf_data_cb, &data,
- inq_genkey_parms, &gk_parm, NULL, NULL);
- if (rc)
- {
- xfree (get_membuf (&data, &len));
- return rc;
- }
- buf = get_membuf (&data, &len);
- if (!buf)
- return gpg_error (GPG_ERR_ENOMEM);
- if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
- {
- xfree (buf);
- return gpg_error (GPG_ERR_INV_SEXP);
- }
- *r_pubkey = buf;
- return 0;
-}
-#endif /*0*/
-
-
-
-/* Ask the agent whether the corresponding secret key is available for
- the given keygrip. */
-int
-agent_havekey (const char *hexkeygrip)
-{
- int rc;
- char line[ASSUAN_LINELENGTH];
-
- rc = start_agent ();
- if (rc)
- return rc;
-
- if (!hexkeygrip || strlen (hexkeygrip) != 40)
- return gpg_error (GPG_ERR_INV_VALUE);
-
- snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
- line[DIM(line)-1] = 0;
-
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
- return rc;
-}
-
-
/* Release the card info structure INFO. */
void
agent_release_card_info (struct agent_card_info_s *info)
@@ -856,3 +793,100 @@ agent_clear_pin_cache (const char *sn)
{
}
+
+
+
+
+/* Note: All strings shall be UTF-8. On success the caler needs to
+ free the string stored at R_PASSPHRASE. On error NULL will be
+ stored at R_PASSPHRASE and an appropriate fpf error code
+ returned. */
+gpg_error_t
+agent_get_passphrase (const char *cache_id,
+ const char *err_msg,
+ const char *prompt,
+ const char *desc_msg,
+ char **r_passphrase)
+{
+ int rc;
+ char *line, *p;
+ char cmd[] = "GET_PASSPHRASE --data -- ";
+ membuf_t data;
+
+ *r_passphrase = NULL;
+
+ rc = start_agent ();
+ if (rc)
+ return rc;
+
+ /* We allocate 3 times the needed space for the texts so that
+ there is enough space for escaping. */
+ line = xtrymalloc ( strlen (cmd) + 1
+ + (cache_id? 3*strlen (cache_id): 1) + 1
+ + (err_msg? 3*strlen (err_msg): 1) + 1
+ + (prompt? 3*strlen (prompt): 1) + 1
+ + (desc_msg? 3*strlen (desc_msg): 1) + 1
+ + 1);
+ if (!line)
+ return gpg_error_from_syserror ();
+
+ p = stpcpy (line, cmd);
+ if (cache_id && *cache_id)
+ p = percent_plus_escape (p, cache_id);
+ else
+ *p++ = 'X';
+ *p++ = ' ';
+
+ if (err_msg && *err_msg)
+ p = percent_plus_escape (p, err_msg);
+ else
+ *p++ = 'X';
+ *p++ = ' ';
+
+ if (prompt && *prompt)
+ p = percent_plus_escape (p, prompt);
+ else
+ *p++ = 'X';
+ *p++ = ' ';
+
+ if (desc_msg && *desc_msg)
+ p = percent_plus_escape (p, desc_msg);
+ else
+ *p++ = 'X';
+ *p = 0;
+
+ init_membuf_secure (&data, 64);
+ rc = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &data, NULL, NULL, NULL, NULL);
+
+ if (rc)
+ xfree (get_membuf (&data, NULL));
+ else
+ {
+ put_membuf (&data, "", 1);
+ *r_passphrase = get_membuf (&data, NULL);
+ if (!*r_passphrase)
+ rc = gpg_error_from_syserror ();
+ }
+ xfree (line);
+ return rc;
+}
+
+
+gpg_error_t
+agent_clear_passphrase (const char *cache_id)
+{
+ int rc;
+ char line[ASSUAN_LINELENGTH];
+
+ if (!cache_id || !*cache_id)
+ return 0;
+
+ rc = start_agent ();
+ if (rc)
+ return rc;
+
+ snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
+ line[DIM(line)-1] = 0;
+ return assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+}
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 08e22e382..6b27c7693 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -73,10 +73,6 @@ int agent_learn (struct agent_card_info_s *info);
/* Update INFO with the attribute NAME. */
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
-/* Check whether the secret key for the key identified by HEXKEYGRIP
- is available. Return 0 for yes or an error code. */
-int agent_havekey (const char *hexkeygrip);
-
/* Send a SETATTR command to the SCdaemon. */
int agent_scd_setattr (const char *name,
const unsigned char *value, size_t valuelen,
@@ -110,5 +106,16 @@ int agent_scd_checkpin (const char *serialno);
void agent_clear_pin_cache (const char *sn);
+/* Send the GET_PASSPHRASE command to the agent. */
+gpg_error_t agent_get_passphrase (const char *cache_id,
+ const char *err_msg,
+ const char *prompt,
+ const char *desc_msg,
+ char **r_passphrase);
+
+/* Send the CLEAR_PASSPHRASE command to the agent. */
+gpg_error_t agent_clear_passphrase (const char *cache_id);
+
+
#endif /*GNUPG_G10_CALL_AGENT_H*/
diff --git a/g10/gpg.c b/g10/gpg.c
index aa70fc808..b541ab7a6 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -78,7 +78,7 @@ enum cmd_and_opt_values
aDecrypt = 'd',
aEncr = 'e',
oInteractive = 'i',
- oListKeys = 'k',
+ aListKeys = 'k',
oDryRun = 'n',
oOutput = 'o',
oQuiet = 'q',
@@ -140,7 +140,6 @@ enum cmd_and_opt_values
aListTrustDB,
aListTrustPath,
aExportOwnerTrust,
- aListOwnerTrust,
aImportOwnerTrust,
aDeArmor,
aEnArmor,
@@ -554,7 +553,6 @@ static ARGPARSE_OPTS opts[] = {
" --fingerprint [names] show fingerprints\n" ) },
/* hidden options */
- { aListOwnerTrust, "list-ownertrust", 256, "@"}, /* deprecated */
{ aPrintMDs, "print-mds" , 256, "@"}, /* old */
{ aListTrustDB, "list-trustdb",0 , "@"},
/* Not yet used */
@@ -1896,7 +1894,7 @@ main (int argc, char **argv )
/* malloc hooks go here ... */
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
-
+
set_native_charset (NULL); /* Try to auto set the character set */
@@ -2014,25 +2012,45 @@ main (int argc, char **argv )
case aCardEdit:
case aChangePIN:
#endif /* ENABLE_CARD_SUPPORT*/
+ case aListKeys:
+ case aListSigs:
+ case aExportSecret:
+ case aExportSecretSub:
+ case aSym:
+ case aClearsign:
+ case aGenRevoke:
+ case aDesigRevoke:
+ case aPrimegen:
+ case aGenRandom:
+ case aPrintMD:
+ case aPrintMDs:
+ case aListTrustDB:
+ case aCheckTrustDB:
+ case aUpdateTrustDB:
+ case aFixTrustDB:
+ case aListTrustPath:
+ case aDeArmor:
+ case aEnArmor:
+ case aSign:
+ case aSignKey:
+ case aLSignKey:
+ case aStore:
+ case aExportOwnerTrust:
+ case aImportOwnerTrust:
+ case aRebuildKeydbCaches:
set_cmd (&cmd, pargs.r_opt);
break;
- case aListKeys: set_cmd( &cmd, aListKeys); break;
- case aListSigs: set_cmd( &cmd, aListSigs); break;
- case aExportSecret: set_cmd( &cmd, aExportSecret); break;
- case aExportSecretSub: set_cmd( &cmd, aExportSecretSub); break;
+ case aKeygen:
+ case aEditKey:
case aDeleteSecretKeys:
- set_cmd( &cmd, aDeleteSecretKeys);
- greeting=1;
- break;
case aDeleteSecretAndPublicKeys:
- set_cmd( &cmd, aDeleteSecretAndPublicKeys);
- greeting=1;
+ case aDeleteKeys:
+ set_cmd (&cmd, pargs.r_opt);
+ greeting=1;
break;
- case aDeleteKeys: set_cmd( &cmd, aDeleteKeys); greeting=1; break;
case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
- case aSym: set_cmd( &cmd, aSym); break;
case aDecryptFiles: multifile=1; /* fall through */
case aDecrypt: set_cmd( &cmd, aDecrypt); break;
@@ -2043,32 +2061,6 @@ main (int argc, char **argv )
case aVerifyFiles: multifile=1; /* fall through */
case aVerify: set_cmd( &cmd, aVerify); break;
- case aSign: set_cmd( &cmd, aSign ); break;
- case aKeygen: set_cmd( &cmd, aKeygen); greeting=1; break;
- case aSignKey: set_cmd( &cmd, aSignKey); break;
- case aLSignKey: set_cmd( &cmd, aLSignKey); break;
- case aStore: set_cmd( &cmd, aStore); break;
- case aEditKey: set_cmd( &cmd, aEditKey); greeting=1; break;
- case aClearsign: set_cmd( &cmd, aClearsign); break;
- case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
- case aDesigRevoke: set_cmd( &cmd, aDesigRevoke); break;
- case aPrimegen: set_cmd( &cmd, aPrimegen); break;
- case aGenRandom: set_cmd( &cmd, aGenRandom); break;
- case aPrintMD: set_cmd( &cmd, aPrintMD); break;
- case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
- case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
- case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
- case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
- case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
- case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
- case aDeArmor: set_cmd( &cmd, aDeArmor); break;
- case aEnArmor: set_cmd( &cmd, aEnArmor); break;
- case aListOwnerTrust:
- deprecated_warning(configname,configlineno,
- "--list-ownertrust","--export-ownertrust","");
- case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
- case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
- case aRebuildKeydbCaches: set_cmd( &cmd, aRebuildKeydbCaches); break;
case oArmor: opt.armor = 1; opt.no_armor=0; break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
@@ -2085,15 +2077,8 @@ main (int argc, char **argv )
break;
case oBatch: opt.batch = 1; nogreeting = 1; break;
- case oUseAgent:
-#ifndef __riscos__
- opt.use_agent = 1;
-#else /* __riscos__ */
- opt.use_agent = 0;
- riscos_not_implemented("use-agent");
-#endif /* __riscos__ */
- break;
- case oNoUseAgent: opt.use_agent = 0; break;
+ case oUseAgent: /* Dummy. */
+ case oNoUseAgent: /* Dummy. */ break;
case oGpgAgentInfo: opt.gpg_agent_info = pargs.r.ret_str; break;
case oAnswerYes: opt.answer_yes = 1; break;
case oAnswerNo: opt.answer_no = 1; break;
@@ -2397,7 +2382,6 @@ main (int argc, char **argv )
break;
case oPasswdFD:
pwfd = iobuf_translate_file_handle (pargs.r.ret_int, 0);
- opt.use_agent = 0;
break;
case oPasswdFile:
pwfd = open_info_file (pargs.r.ret_str, 0);
@@ -2809,8 +2793,6 @@ main (int argc, char **argv )
}
#endif
- log_info ("WARNING: This version of gpg is not ready for use, use gpg 1.4.x\n");
-
/* FIXME: We should use logging to a file only in server mode;
however we have not yet implemetyed that. Thus we try to get
away with --batch as indication for logging to file
diff --git a/g10/options.h b/g10/options.h
index 282130085..d36db1a79 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -184,7 +184,7 @@ struct
int command_fd;
const char *override_session_key;
int show_session_key;
- int use_agent;
+
const char *gpg_agent_info;
int try_all_secrets;
int no_expensive_trust_checks;
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;
}
-
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index ad5b75603..a059aa00f 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -284,7 +284,7 @@ check_secret_key( PKT_secret_key *sk, int n )
mode=0;
if( n < 1 )
- n = (opt.batch && !opt.use_agent)? 1 : 3; /* use the default value */
+ n = 3; /* Use the default value */
for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) {
int canceled = 0;