aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--doc/gpg.texi20
-rw-r--r--g10/call-agent.c265
-rw-r--r--g10/call-agent.h2
-rw-r--r--g10/gpg.c14
-rw-r--r--g10/keydb.h3
-rw-r--r--g10/options.h1
-rw-r--r--g10/passphrase.c70
-rw-r--r--g10/pubkey-enc.c4
-rw-r--r--g10/sign.c1
10 files changed, 301 insertions, 81 deletions
diff --git a/NEWS b/NEWS
index a8352ca53..b81759ceb 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ Noteworthy changes in version 2.1.0beta4 (unreleased)
* The hash algorithm is now printed for sig records in key listings.
+ * New option --pinentry-mode for GPG.
+
Noteworthy changes in version 2.1.0beta3 (2011-12-20)
-----------------------------------------------------
diff --git a/doc/gpg.texi b/doc/gpg.texi
index d67900042..cf647e19b 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2611,6 +2611,26 @@ Note that this passphrase is only used if the option @option{--batch}
has also been given. This is different from @command{gpg}.
@end ifclear
+@ifset gpgtwoone
+@item --pinentry-mode @code{mode}
+@opindex pinentry-mode
+Set the pinentry mode to @code{mode}. Allowed values for @code{mode}
+are:
+@table @asis
+ @item default
+ Use the default of the agent, which is @code{ask}.
+ @item ask
+ Force the use of the Pinentry.
+ @item cancel
+ Emulate use of Pinentry's cancel button.
+ @item error
+ Return a Pinentry error (``No Pinentry'').
+ @item loopback
+ Redirect Pinentry queries to the caller. Note that in contrast to
+ Pinentry the user is not prompted again if he enters a bad password.
+@end table
+@end ifset
+
@item --command-fd @code{n}
@opindex command-fd
This is a replacement for the deprecated shared-memory IPC mode.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index a4d1dbb13..ed141dadc 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -1,6 +1,6 @@
/* call-agent.c - Divert GPG operations to the agent.
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
- * 2010, 2011 Free Software Foundation, Inc.
+ * 2010, 2011, 2013 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -40,47 +40,60 @@
#include "sysutils.h"
#include "call-agent.h"
#include "status.h"
+#include "../common/shareddefs.h"
#ifndef DBG_ASSUAN
# define DBG_ASSUAN 1
#endif
+#define CONTROL_D ('D' - 'A' + 1)
+
+
static assuan_context_t agent_ctx = NULL;
static int did_early_card_test;
-struct cipher_parm_s
+struct default_inq_parm_s
{
ctrl_t ctrl;
assuan_context_t ctx;
+ struct {
+ u32 *keyid;
+ u32 *mainkeyid;
+ int pubkey_algo;
+ } keyinfo;
+};
+
+struct cipher_parm_s
+{
+ struct default_inq_parm_s *dflt;
+ assuan_context_t ctx;
unsigned char *ciphertext;
size_t ciphertextlen;
};
struct writecert_parm_s
{
- assuan_context_t ctx;
+ struct default_inq_parm_s *dflt;
const unsigned char *certdata;
size_t certdatalen;
};
struct writekey_parm_s
{
- assuan_context_t ctx;
+ struct default_inq_parm_s *dflt;
const unsigned char *keydata;
size_t keydatalen;
};
struct genkey_parm_s
{
- ctrl_t ctrl;
- assuan_context_t ctx;
+ struct default_inq_parm_s *dflt;
const char *keyparms;
};
struct import_key_parm_s
{
- ctrl_t ctrl;
- assuan_context_t ctx;
+ struct default_inq_parm_s *dflt;
const void *key;
size_t keylen;
};
@@ -161,6 +174,19 @@ start_agent (ctrl_t ctrl, int for_card)
here used to indirectly enable GPG_ERR_FULLY_CANCELED. */
assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
NULL, NULL, NULL, NULL, NULL, NULL);
+ /* Pass on the pinentry mode. */
+ if (opt.pinentry_mode)
+ {
+ char *tmp = xasprintf ("OPTION pinentry-mode=%s",
+ str_pinentry_mode (opt.pinentry_mode));
+ rc = assuan_transact (agent_ctx, tmp,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ xfree (tmp);
+ if (rc)
+ log_error ("setting pinentry mode '%s' failed: %s\n",
+ str_pinentry_mode (opt.pinentry_mode),
+ gpg_strerror (rc));
+ }
}
}
@@ -307,21 +333,46 @@ get_serialno_cb (void *opaque, const char *line)
static gpg_error_t
default_inq_cb (void *opaque, const char *line)
{
- gpg_error_t err;
- ctrl_t ctrl = opaque;
+ gpg_error_t err = 0;
+ struct default_inq_parm_s *parm = opaque;
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{
- err = gpg_proxy_pinentry_notify (ctrl, line);
+ err = gpg_proxy_pinentry_notify (parm->ctrl, line);
if (err)
log_error (_("failed to proxy %s inquiry to client\n"),
"PINENTRY_LAUNCHED");
/* We do not pass errors to avoid breaking other code. */
}
+ else if (!strncmp (line, "PASSPHRASE", 10) && (line[10]==' '||!line[10])
+ && opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
+ {
+ if (have_static_passphrase ())
+ {
+ const char *s = get_static_passphrase ();
+ err = assuan_send_data (parm->ctx, s, strlen (s));
+ }
+ else
+ {
+ char *pw;
+
+ if (parm->keyinfo.keyid)
+ emit_status_need_passphrase (parm->keyinfo.keyid,
+ parm->keyinfo.mainkeyid,
+ parm->keyinfo.pubkey_algo);
+ pw = cpr_get_hidden ("passphrase.enter", _("Enter passphrase: "));
+ cpr_kill_prompt ();
+ if (*pw == CONTROL_D && !pw[1])
+ err = gpg_error (GPG_ERR_CANCELED);
+ else
+ err = assuan_send_data (parm->ctx, pw, strlen (pw));
+ xfree (pw);
+ }
+ }
else
log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
- return 0;
+ return err;
}
@@ -516,6 +567,9 @@ int
agent_learn (struct agent_card_info_s *info)
{
int rc;
+ struct default_inq_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
rc = start_agent (NULL, 1);
if (rc)
@@ -533,10 +587,10 @@ agent_learn (struct agent_card_info_s *info)
if (rc)
return rc;
-
+ parm.ctx = agent_ctx;
memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, "SCD LEARN --force",
- dummy_data_cb, NULL, default_inq_cb, NULL,
+ dummy_data_cb, NULL, default_inq_cb, &parm,
learn_status_cb, info);
/* Also try to get the key attributes. */
if (!rc)
@@ -553,6 +607,9 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
{
int rc;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
if (!*name)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -566,7 +623,8 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
if (rc)
return rc;
- rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
+ parm.ctx = agent_ctx;
+ rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
learn_status_cb, info);
return rc;
@@ -584,6 +642,9 @@ agent_scd_setattr (const char *name,
int rc;
char line[ASSUAN_LINELENGTH];
char *p;
+ struct default_inq_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
(void)serialno;
@@ -615,8 +676,9 @@ agent_scd_setattr (const char *name,
rc = start_agent (NULL, 1);
if (!rc)
{
+ parm.ctx = agent_ctx;
rc = assuan_transact (agent_ctx, line, NULL, NULL,
- default_inq_cb, NULL, NULL, NULL);
+ default_inq_cb, &parm, NULL, NULL);
}
status_sc_op_failure (rc);
@@ -636,10 +698,11 @@ inq_writecert_parms (void *opaque, const char *line)
if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
{
- rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
+ rc = assuan_send_data (parm->dflt->ctx,
+ parm->certdata, parm->certdatalen);
}
else
- rc = default_inq_cb (opaque, line);
+ rc = default_inq_cb (parm->dflt, line);
return rc;
}
@@ -653,6 +716,9 @@ agent_scd_writecert (const char *certidstr,
int rc;
char line[ASSUAN_LINELENGTH];
struct writecert_parm_s parms;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 1);
if (rc)
@@ -662,7 +728,8 @@ agent_scd_writecert (const char *certidstr,
snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
line[DIM(line)-1] = 0;
- parms.ctx = agent_ctx;
+ dfltparm.ctx = agent_ctx;
+ parms.dflt = &dfltparm;
parms.certdata = certdata;
parms.certdatalen = certdatalen;
@@ -684,10 +751,10 @@ inq_writekey_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
{
- rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
+ rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
}
else
- rc = default_inq_cb (opaque, line);
+ rc = default_inq_cb (parm->dflt, line);
return rc;
}
@@ -701,6 +768,9 @@ agent_scd_writekey (int keyno, const char *serialno,
int rc;
char line[ASSUAN_LINELENGTH];
struct writekey_parm_s parms;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno;
@@ -712,7 +782,8 @@ agent_scd_writekey (int keyno, const char *serialno,
snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
line[DIM(line)-1] = 0;
- parms.ctx = agent_ctx;
+ dfltparm.ctx = agent_ctx;
+ parms.dflt = &dfltparm;
parms.keydata = keydata;
parms.keydatalen = keydatalen;
@@ -837,6 +908,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
char line[ASSUAN_LINELENGTH];
gnupg_isotime_t tbuf;
struct scd_genkey_parm_s parms;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno;
@@ -858,9 +932,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
keyno);
line[DIM(line)-1] = 0;
+ dfltparm.ctx = agent_ctx;
memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, line,
- NULL, NULL, default_inq_cb, NULL,
+ NULL, NULL, default_inq_cb, &dfltparm,
scd_genkey_cb, &parms);
xfree (parms.savedbytes);
@@ -986,19 +1061,25 @@ agent_scd_readcert (const char *certidstr,
char line[ASSUAN_LINELENGTH];
membuf_t data;
size_t len;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
*r_buf = NULL;
rc = start_agent (NULL, 1);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
+
init_membuf (&data, 2048);
snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
- default_inq_cb, NULL, NULL, NULL);
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
if (rc)
{
xfree (get_membuf (&data, &len));
@@ -1029,6 +1110,9 @@ agent_scd_change_pin (int chvno, const char *serialno)
int rc;
char line[ASSUAN_LINELENGTH];
const char *reset = "";
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno;
@@ -1039,11 +1123,14 @@ agent_scd_change_pin (int chvno, const char *serialno)
rc = start_agent (NULL, 1);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
line[DIM(line)-1] = 0;
- rc = assuan_transact (agent_ctx, line, NULL, NULL,
- default_inq_cb, NULL, NULL, NULL);
+ rc = assuan_transact (agent_ctx, line,
+ NULL, NULL,
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
status_sc_op_failure (rc);
return rc;
}
@@ -1057,16 +1144,21 @@ agent_scd_checkpin (const char *serialno)
{
int rc;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 1);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line,
NULL, NULL,
- default_inq_cb, NULL, NULL, NULL);
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
status_sc_op_failure (rc);
return rc;
}
@@ -1102,12 +1194,16 @@ agent_get_passphrase (const char *cache_id,
char *arg3 = NULL;
char *arg4 = NULL;
membuf_t data;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
*r_passphrase = NULL;
rc = start_agent (NULL, 0);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
/* Check that the gpg-agent understands the repeat option. */
if (assuan_transact (agent_ctx,
@@ -1145,7 +1241,8 @@ agent_get_passphrase (const char *cache_id,
init_membuf_secure (&data, 64);
rc = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
- default_inq_cb, NULL, NULL, NULL);
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
if (rc)
xfree (get_membuf (&data, NULL));
@@ -1172,6 +1269,9 @@ agent_clear_passphrase (const char *cache_id)
{
int rc;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
if (!cache_id || !*cache_id)
return 0;
@@ -1179,11 +1279,14 @@ agent_clear_passphrase (const char *cache_id)
rc = start_agent (NULL, 0);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
line[DIM(line)-1] = 0;
- return assuan_transact (agent_ctx, line, NULL, NULL,
- default_inq_cb, NULL, NULL, NULL);
+ return assuan_transact (agent_ctx, line,
+ NULL, NULL,
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
}
@@ -1195,10 +1298,14 @@ gpg_agent_get_confirmation (const char *desc)
int rc;
char *tmp;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 0);
if (rc)
return rc;
+ dfltparm.ctx = agent_ctx;
tmp = percent_plus_escape (desc);
if (!tmp)
@@ -1207,8 +1314,10 @@ gpg_agent_get_confirmation (const char *desc)
line[DIM(line)-1] = 0;
xfree (tmp);
- rc = assuan_transact (agent_ctx, line, NULL, NULL,
- default_inq_cb, NULL, NULL, NULL);
+ rc = assuan_transact (agent_ctx, line,
+ NULL, NULL,
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
return rc;
}
@@ -1439,11 +1548,11 @@ inq_genkey_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
{
- err = assuan_send_data (parm->ctx,
+ err = assuan_send_data (parm->dflt->ctx,
parm->keyparms, strlen (parm->keyparms));
}
else
- err = default_inq_cb (parm->ctrl, line);
+ err = default_inq_cb (parm->dflt, line);
return err;
}
@@ -1460,15 +1569,20 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
gpg_error_t err;
struct genkey_parm_s gk_parm;
struct cache_nonce_parm_s cn_parm;
+ struct default_inq_parm_s dfltparm;
membuf_t data;
size_t len;
unsigned char *buf;
char line[ASSUAN_LINELENGTH];
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
+
*r_pubkey = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
@@ -1476,8 +1590,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
return err;
init_membuf (&data, 1024);
- gk_parm.ctrl = ctrl;
- gk_parm.ctx = agent_ctx;
+ gk_parm.dflt = &dfltparm;
gk_parm.keyparms = keyparms;
snprintf (line, sizeof line, "GENKEY%s%s%s",
no_protection? " --no-protection":"",
@@ -1521,11 +1634,16 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
size_t len;
unsigned char *buf;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
*r_pubkey = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
@@ -1536,7 +1654,8 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
init_membuf (&data, 1024);
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
- default_inq_cb, NULL, NULL, NULL);
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
if (err)
{
xfree (get_membuf (&data, &len));
@@ -1565,17 +1684,26 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
gpg_error_t
agent_pksign (ctrl_t ctrl, const char *cache_nonce,
const char *keygrip, const char *desc,
+ u32 *keyid, u32 *mainkeyid, int pubkey_algo,
unsigned char *digest, size_t digestlen, int digestalgo,
gcry_sexp_t *r_sigval)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
membuf_t data;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
+ dfltparm.keyinfo.keyid = keyid;
+ dfltparm.keyinfo.mainkeyid = mainkeyid;
+ dfltparm.keyinfo.pubkey_algo = pubkey_algo;
*r_sigval = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
if (digestlen*2 + 50 > DIM(line))
return gpg_error (GPG_ERR_GENERAL);
@@ -1613,8 +1741,9 @@ agent_pksign (ctrl_t ctrl, const char *cache_nonce,
cache_nonce? " -- ":"",
cache_nonce? cache_nonce:"");
err = assuan_transact (agent_ctx, line,
- membuf_data_cb, &data, default_inq_cb, ctrl,
- NULL, NULL);
+ membuf_data_cb, &data,
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
if (err)
xfree (get_membuf (&data, NULL));
else
@@ -1647,11 +1776,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
{
assuan_begin_confidential (parm->ctx);
- rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
+ rc = assuan_send_data (parm->dflt->ctx,
+ parm->ciphertext, parm->ciphertextlen);
assuan_end_confidential (parm->ctx);
}
else
- rc = default_inq_cb (parm->ctrl, line);
+ rc = default_inq_cb (parm->dflt, line);
return rc;
}
@@ -1660,9 +1790,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
/* Call the agent to do a decrypt operation using the key identified
by the hex string KEYGRIP and the input data S_CIPHERTEXT. On the
success the decoded value is stored verbatim at R_BUF and its
- length at R_BUF; the callers needs to release it. */
+ length at R_BUF; the callers needs to release it. KEYID, MAINKEYID
+ and PUBKEY_ALGO are used to construct additional promots or status
+ messages. */
gpg_error_t
agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
+ u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext,
unsigned char **r_buf, size_t *r_buflen)
{
@@ -1671,6 +1804,13 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
membuf_t data;
size_t n, len;
char *p, *buf, *endp;
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
+ dfltparm.keyinfo.keyid = keyid;
+ dfltparm.keyinfo.mainkeyid = mainkeyid;
+ dfltparm.keyinfo.pubkey_algo = pubkey_algo;
if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -1679,6 +1819,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
@@ -1704,7 +1845,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
{
struct cipher_parm_s parm;
- parm.ctrl = ctrl;
+ parm.dflt = &dfltparm;
parm.ctx = agent_ctx;
err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
if (err)
@@ -1773,11 +1914,16 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
size_t len;
unsigned char *buf;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
*r_kek = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
forexport? "--export":"--import");
@@ -1785,7 +1931,8 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
init_membuf_secure (&data, 64);
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
- default_inq_cb, ctrl, NULL, NULL);
+ default_inq_cb, &dfltparm,
+ NULL, NULL);
if (err)
{
xfree (get_membuf (&data, &len));
@@ -1810,10 +1957,10 @@ inq_import_key_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
{
- err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
+ err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
}
else
- err = default_inq_cb (parm->ctrl, line);
+ err = default_inq_cb (parm->dflt, line);
return err;
}
@@ -1828,10 +1975,15 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
struct import_key_parm_s parm;
struct cache_nonce_parm_s cn_parm;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
if (desc)
{
@@ -1843,8 +1995,7 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
return err;
}
- parm.ctrl = ctrl;
- parm.ctx = agent_ctx;
+ parm.dflt = &dfltparm;
parm.key = key;
parm.keylen = keylen;
@@ -1854,7 +2005,8 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line,
- NULL, NULL, inq_import_key_parms, &parm,
+ NULL, NULL,
+ inq_import_key_parms, &parm,
cache_nonce_status_cb, &cn_parm);
return err;
}
@@ -1876,12 +2028,17 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
size_t len;
unsigned char *buf;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
*r_result = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
if (desc)
{
@@ -1902,7 +2059,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
- default_inq_cb, ctrl,
+ default_inq_cb, &dfltparm,
cache_nonce_status_cb, &cn_parm);
if (err)
{
@@ -1932,14 +2089,20 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
gpg_error_t err;
struct cache_nonce_parm_s cn_parm;
char line[ASSUAN_LINELENGTH];
+ struct default_inq_parm_s dfltparm;
+
+ memset (&dfltparm, 0, sizeof dfltparm);
+ dfltparm.ctrl = ctrl;
err = start_agent (ctrl, 0);
if (err)
return err;
+ dfltparm.ctx = agent_ctx;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE);
+
if (desc)
{
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
@@ -1958,7 +2121,7 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = passwd_nonce_addr;
err = assuan_transact (agent_ctx, line, NULL, NULL,
- default_inq_cb, ctrl,
+ default_inq_cb, &dfltparm,
cache_nonce_status_cb, &cn_parm);
return err;
}
diff --git a/g10/call-agent.h b/g10/call-agent.h
index 43de14fe3..de05d7afc 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -155,12 +155,14 @@ gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
/* Create a signature. */
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
const char *hexkeygrip, const char *desc,
+ u32 *keyid, u32 *mainkeyid, int pubkey_algo,
unsigned char *digest, size_t digestlen,
int digestalgo,
gcry_sexp_t *r_sigval);
/* Decrypt a ciphertext. */
gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
+ u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext,
unsigned char **r_buf, size_t *r_buflen);
diff --git a/g10/gpg.c b/g10/gpg.c
index b614a94a0..9adc21abc 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -56,6 +56,7 @@
#include "asshelp.h"
#include "call-dirmngr.h"
#include "../common/init.h"
+#include "../common/shareddefs.h"
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
#define MY_O_BINARY O_BINARY
@@ -217,6 +218,7 @@ enum cmd_and_opt_values
oPassphraseFD,
oPassphraseFile,
oPassphraseRepeat,
+ oPinentryMode,
oCommandFD,
oCommandFile,
oQuickRandom,
@@ -611,6 +613,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
+ ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
ARGPARSE_s_s (oCommandFile, "command-file", "@"),
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
@@ -2593,7 +2596,16 @@ main (int argc, char **argv)
case oPassphraseFile:
pwfd = open_info_file (pargs.r.ret_str, 0, 1);
break;
- case oPassphraseRepeat: opt.passphrase_repeat=pargs.r.ret_int; break;
+ case oPassphraseRepeat:
+ opt.passphrase_repeat = pargs.r.ret_int;
+ break;
+
+ case oPinentryMode:
+ opt.pinentry_mode = parse_pinentry_mode (pargs.r.ret_str);
+ if (opt.pinentry_mode == -1)
+ log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
+ break;
+
case oCommandFD:
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
break;
diff --git a/g10/keydb.h b/g10/keydb.h
index 22c2b673e..fd80c2525 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -181,6 +181,7 @@ unsigned char encode_s2k_iterations (int iterations);
assuan_context_t agent_open (int try, const char *orig_codeset);
void agent_close (assuan_context_t ctx);
int have_static_passphrase(void);
+const char *get_static_passphrase (void);
void set_passphrase_from_string(const char *pass);
void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
@@ -196,6 +197,8 @@ void set_next_passphrase( const char *s );
char *get_last_passphrase(void);
void next_to_last_passphrase(void);
+void emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo);
+
char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);
diff --git a/g10/options.h b/g10/options.h
index e67d0ce04..223b11510 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -242,6 +242,7 @@ struct
} *auto_key_locate;
int passphrase_repeat;
+ int pinentry_mode;
} opt;
/* CTRL is used to keep some global variables we currently can't
diff --git a/g10/passphrase.c b/g10/passphrase.c
index cc5655505..d872e36ae 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -43,7 +43,7 @@
#include "i18n.h"
#include "status.h"
#include "call-agent.h"
-
+#include "../common/shareddefs.h"
static char *fd_passwd = NULL;
static char *next_pw = NULL;
@@ -104,9 +104,21 @@ encode_s2k_iterations (int iterations)
int
have_static_passphrase()
{
- return !!fd_passwd && opt.batch;
+ return (!!fd_passwd
+ && (opt.batch || opt.pinentry_mode == PINENTRY_MODE_LOOPBACK));
+}
+
+/* Return a static passphrase. The returned value is only valid as
+ long as no other passphrase related function is called. NULL may
+ be returned if no passphrase has been set; better use
+ have_static_passphrase first. */
+const char *
+get_static_passphrase (void)
+{
+ return fd_passwd;
}
+
/****************
* Set the passphrase to be used for the next query and only for the next
* one.
@@ -156,7 +168,7 @@ read_passphrase_from_fd( int fd )
int i, len;
char *pw;
- if ( !opt.batch )
+ if ( !opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
{ /* 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. */
@@ -187,7 +199,7 @@ read_passphrase_from_fd( int fd )
break;
}
pw[i] = 0;
- if (!opt.batch)
+ if (!opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
tty_printf("\b\b\b \n" );
xfree ( fd_passwd );
@@ -458,30 +470,9 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
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];
- }
-
- 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 );
+ emit_status_need_passphrase (keyid,
+ keyid[2] && keyid[3]? keyid+2:NULL,
+ pubkey_algo);
}
else
{
@@ -614,6 +605,29 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
}
+/* Emit the USERID_HINT and the NEED_PASSPHRASE status messages.
+ MAINKEYID may be NULL. */
+void
+emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo)
+{
+ char buf[50];
+ char *us;
+
+ 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)(mainkeyid? mainkeyid[0]:keyid[0]),
+ (ulong)(mainkeyid? mainkeyid[1]:keyid[1]),
+ pubkey_algo);
+
+ write_status_text (STATUS_NEED_PASSPHRASE, buf);
+}
+
+
/* Return an allocated utf-8 string describing the key PK. If ESCAPED
is true spaces and control characters are percent or plus escaped.
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 254e81091..a98a7238b 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -193,7 +193,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
/* Decrypt. */
desc = gpg_format_keydesc (sk, 0, 1);
- err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
+ err = agent_pkdecrypt (NULL, keygrip,
+ desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
+ s_data, &frame, &nframe);
xfree (desc);
gcry_sexp_release (s_data);
if (err)
diff --git a/g10/sign.c b/g10/sign.c
index 501f1ff25..8944067d7 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -272,6 +272,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
desc = gpg_format_keydesc (pksk, 0, 1);
err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc,
+ pksk->keyid, pksk->main_keyid, pksk->pubkey_algo,
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
&s_sigval);
xfree (desc);