aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/call-agent.c294
-rw-r--r--g10/call-agent.h6
-rw-r--r--g10/card-util.c242
-rw-r--r--g10/gpg.c14
-rw-r--r--g10/keydb.h3
-rw-r--r--g10/main.h2
-rw-r--r--g10/options.h1
-rw-r--r--g10/passphrase.c70
-rw-r--r--g10/pubkey-enc.c4
-rw-r--r--g10/server.c36
-rw-r--r--g10/sign.c3
11 files changed, 443 insertions, 232 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 55637e463..85a3f2842 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,20 +333,46 @@ get_serialno_cb (void *opaque, const char *line)
static gpg_error_t
default_inq_cb (void *opaque, const char *line)
{
- (void)opaque;
+ gpg_error_t err = 0;
+ struct default_inq_parm_s *parm = opaque;
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{
- /* There is no working server mode yet thus we use
- AllowSetForegroundWindow window right here. We might want to
- do this anyway in case gpg is called on the console. */
- gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
+ 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;
}
@@ -515,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)
@@ -532,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)
@@ -544,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
return rc;
}
+
+int
+agent_keytocard (const char *hexgrip, int keyno, int force,
+ const char *serialno, const char *timestamp)
+{
+ int rc;
+ char line[ASSUAN_LINELENGTH];
+
+ snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
+ force?"--force ": "", hexgrip, serialno, keyno, timestamp);
+ line[DIM(line)-1] = 0;
+
+ rc = start_agent (NULL, 1);
+ if (rc)
+ return rc;
+
+ rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
+ NULL, NULL, NULL);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
/* Call the agent to retrieve a data object. This function returns
the data in the same structure as used by the learn command. It is
allowed to update such a structure using this commmand. */
@@ -552,6 +631,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);
@@ -565,7 +647,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;
@@ -583,6 +666,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;
@@ -614,8 +700,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);
@@ -635,10 +722,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;
}
@@ -652,6 +740,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)
@@ -661,7 +752,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;
@@ -683,10 +775,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;
}
@@ -700,6 +792,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;
@@ -711,7 +806,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;
@@ -836,6 +932,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;
@@ -857,9 +956,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);
@@ -985,19 +1085,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));
@@ -1028,6 +1134,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;
@@ -1038,11 +1147,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;
}
@@ -1056,16 +1168,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;
}
@@ -1101,12 +1218,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,
@@ -1144,7 +1265,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));
@@ -1171,6 +1293,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;
@@ -1178,11 +1303,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);
}
@@ -1194,10 +1322,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)
@@ -1206,8 +1338,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;
}
@@ -1438,11 +1572,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;
}
@@ -1459,15 +1593,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);
@@ -1475,8 +1614,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":"",
@@ -1520,11 +1658,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)
@@ -1535,7 +1678,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));
@@ -1564,17 +1708,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);
@@ -1612,8 +1765,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
@@ -1646,11 +1800,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;
}
@@ -1659,9 +1814,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)
{
@@ -1670,6 +1828,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);
@@ -1678,6 +1843,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);
@@ -1703,7 +1869,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)
@@ -1772,11 +1938,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");
@@ -1784,7 +1955,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));
@@ -1809,10 +1981,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;
}
@@ -1827,10 +1999,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)
{
@@ -1842,8 +2019,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;
@@ -1853,7 +2029,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;
}
@@ -1875,12 +2052,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)
{
@@ -1901,7 +2083,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)
{
@@ -1931,14 +2113,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);
@@ -1957,7 +2145,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..ab1d41a53 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -81,6 +81,10 @@ 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);
+/* Send the KEYTOCARD command. */
+int agent_keytocard (const char *hexgrip, int keyno, int force,
+ const char *serialno, const char *timestamp);
+
/* Send a SETATTR command to the SCdaemon. */
int agent_scd_setattr (const char *name,
const unsigned char *value, size_t valuelen,
@@ -155,12 +159,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/card-util.c b/g10/card-util.c
index 83586858e..75208cc86 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -1264,6 +1264,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
_("Replace existing key? (y/N) ")))
return -1;
+ return 1;
}
return 0;
}
@@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
tty_printf(_("Invalid selection.\n"));
}
- if (replace_existing_key_p (&info, keyno))
+ if (replace_existing_key_p (&info, keyno) < 0)
{
err = gpg_error (GPG_ERR_CANCELED);
goto leave;
@@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
int
card_store_subkey (KBNODE node, int use)
{
- log_info ("FIXME: card_store_subkey has not yet been implemented\n");
-/* struct agent_card_info_s info; */
-/* int okay = 0; */
-/* int rc; */
-/* int keyno, i; */
-/* PKT_secret_key *copied_sk = NULL; */
-/* PKT_secret_key *sk; */
-/* size_t n; */
-/* const char *s; */
-/* int allow_keyno[3]; */
-/* unsigned int nbits; */
-
-
-/* assert (node->pkt->pkttype == PKT_SECRET_KEY */
-/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
-/* sk = node->pkt->pkt.secret_key; */
-
-/* if (get_info_for_key_operation (&info)) */
-/* return 0; */
-
-/* if (!info.extcap.ki) */
-/* { */
-/* tty_printf ("The card does not support the import of keys\n"); */
-/* tty_printf ("\n"); */
-/* goto leave; */
-/* } */
-
-/* show_card_key_info (&info); */
-
-/* nbits = nbits_from_sk (sk); */
-
-/* if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
-/* { */
-/* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
-/* tty_printf ("\n"); */
-/* goto leave; */
-/* } */
-
-/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
-/* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
-/* allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
-
-/* tty_printf (_("Please select where to store the key:\n")); */
-
-/* if (allow_keyno[0]) */
-/* tty_printf (_(" (1) Signature key\n")); */
-/* if (allow_keyno[1]) */
-/* tty_printf (_(" (2) Encryption key\n")); */
-/* if (allow_keyno[2]) */
-/* tty_printf (_(" (3) Authentication key\n")); */
-
-/* for (;;) */
-/* { */
-/* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
-/* _("Your selection? ")); */
-/* cpr_kill_prompt(); */
-/* if (*answer == CONTROL_D || !*answer) */
-/* { */
-/* xfree (answer); */
-/* goto leave; */
-/* } */
-/* keyno = *answer? atoi(answer): 0; */
-/* xfree(answer); */
-/* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
-/* { */
-/* if (info.is_v2 && !info.extcap.aac */
-/* && info.key_attr[keyno-1].nbits != nbits) */
-/* { */
-/* tty_printf ("Key does not match the card's capability.\n"); */
-/* } */
-/* else */
-/* break; /\* Okay. *\/ */
-/* } */
-/* else */
-/* tty_printf(_("Invalid selection.\n")); */
-/* } */
-
-/* if (replace_existing_key_p (&info, keyno)) */
-/* goto leave; */
-
-/* /\* Unprotect key. *\/ */
-/* switch (is_secret_key_protected (sk) ) */
-/* { */
-/* case 0: /\* Not protected. *\/ */
-/* break; */
-/* case -1: */
-/* log_error (_("unknown key protection algorithm\n")); */
-/* goto leave; */
-/* default: */
-/* if (sk->protect.s2k.mode == 1001) */
-/* { */
-/* log_error (_("secret parts of key are not available\n")); */
-/* goto leave; */
-/* } */
-/* if (sk->protect.s2k.mode == 1002) */
-/* { */
-/* log_error (_("secret key already stored on a card\n")); */
-/* goto leave; */
-/* } */
-/* /\* We better copy the key before we unprotect it. *\/ */
-/* copied_sk = sk = copy_secret_key (NULL, sk); */
-/* rc = 0/\*check_secret_key (sk, 0)*\/; */
-/* if (rc) */
-/* goto leave; */
-/* } */
-
-/* #warning code save_unprotected_key_to_card */
-/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
-/* /\* if (rc) *\/ */
-/* /\* { *\/ */
-/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
-/* /\* goto leave; *\/ */
-/* /\* } *\/ */
-
-/* /\* Get back to the maybe protected original secret key. *\/ */
-/* if (copied_sk) */
-/* { */
-/* free_secret_key (copied_sk); */
-/* copied_sk = NULL; */
-/* } */
-/* sk = node->pkt->pkt.secret_key; */
-
-/* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
-/* n = pubkey_get_nskey (sk->pubkey_algo); */
-/* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
-/* { */
-/* gcry_mpi_release (sk->skey[i]); */
-/* sk->skey[i] = NULL; */
-/* } */
-/* i = pubkey_get_npkey (sk->pubkey_algo); */
-/* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
-/* sk->is_protected = 1; */
-/* sk->protect.s2k.mode = 1002; */
-/* s = info.serialno; */
-/* for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
-/* sk->protect.ivlen++, s += 2) */
-/* sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
-
-/* okay = 1; */
-
-/* leave: */
-/* if (copied_sk) */
-/* free_secret_key (copied_sk); */
-/* agent_release_card_info (&info); */
-/* return okay; */
- return -1;
+ struct agent_card_info_s info;
+ int okay = 0;
+ unsigned int nbits;
+ int allow_keyno[3];
+ int keyno;
+ PKT_public_key *pk;
+ gpg_error_t err;
+ char *hexgrip;
+ int rc;
+ gnupg_isotime_t timebuf;
+
+ assert (node->pkt->pkttype == PKT_PUBLIC_KEY
+ || node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+
+ pk = node->pkt->pkt.public_key;
+
+ if (get_info_for_key_operation (&info))
+ return 0;
+
+ if (!info.extcap.ki)
+ {
+ tty_printf ("The card does not support the import of keys\n");
+ tty_printf ("\n");
+ goto leave;
+ }
+
+ nbits = nbits_from_pk (pk);
+
+ if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
+ {
+ tty_printf ("You may only store a 1024 bit RSA key on the card\n");
+ tty_printf ("\n");
+ goto leave;
+ }
+
+ allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
+ allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
+ allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
+
+ tty_printf (_("Please select where to store the key:\n"));
+
+ if (allow_keyno[0])
+ tty_printf (_(" (1) Signature key\n"));
+ if (allow_keyno[1])
+ tty_printf (_(" (2) Encryption key\n"));
+ if (allow_keyno[2])
+ tty_printf (_(" (3) Authentication key\n"));
+
+ for (;;)
+ {
+ char *answer = cpr_get ("cardedit.genkeys.storekeytype",
+ _("Your selection? "));
+ cpr_kill_prompt();
+ if (*answer == CONTROL_D || !*answer)
+ {
+ xfree (answer);
+ goto leave;
+ }
+ keyno = *answer? atoi(answer): 0;
+ xfree(answer);
+ if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
+ {
+ if (info.is_v2 && !info.extcap.aac
+ && info.key_attr[keyno-1].nbits != nbits)
+ {
+ tty_printf ("Key does not match the card's capability.\n");
+ }
+ else
+ break; /* Okay. */
+ }
+ else
+ tty_printf(_("Invalid selection.\n"));
+ }
+
+ if ((rc = replace_existing_key_p (&info, keyno)) < 0)
+ goto leave;
+
+ err = hexkeygrip_from_pk (pk, &hexgrip);
+ if (err)
+ goto leave;
+
+ epoch2isotime (timebuf, (time_t)pk->timestamp);
+ agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
+
+ if (rc)
+ log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
+ else
+ okay = 1;
+ xfree (hexgrip);
+
+ leave:
+ agent_release_card_info (&info);
+ return okay;
}
diff --git a/g10/gpg.c b/g10/gpg.c
index 7e4339b57..a19c9a76a 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", "@"),
@@ -2594,7 +2597,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 fb36c81eb..39e7826a9 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/main.h b/g10/main.h
index d25265aa7..15d3b7627 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -353,6 +353,8 @@ void unblock_all_signals(void);
/*-- server.c --*/
int gpg_server (ctrl_t);
+gpg_error_t gpg_proxy_pinentry_notify (ctrl_t ctrl,
+ const unsigned char *line);
#ifdef ENABLE_CARD_SUPPORT
/*-- card-util.c --*/
diff --git a/g10/options.h b/g10/options.h
index d4824bcf1..d44d7a14b 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 a69536e1d..a328e1adc 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -201,7 +201,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/server.c b/g10/server.c
index d8871d059..da9c28df4 100644
--- a/g10/server.c
+++ b/g10/server.c
@@ -50,6 +50,9 @@ struct server_local_s
/* List of prepared recipients. */
pk_list_t recplist;
+ /* Set if pinentry notifications should be passed back to the
+ client. */
+ int allow_pinentry_notify;
};
@@ -105,9 +108,8 @@ has_option (const char *line, const char *name)
static gpg_error_t
option_handler (assuan_context_t ctx, const char *key, const char *value)
{
-/* ctrl_t ctrl = assuan_get_pointer (ctx); */
+ ctrl_t ctrl = assuan_get_pointer (ctx);
- (void)ctx;
(void)value;
/* Fixme: Implement the tty and locale args. */
@@ -136,6 +138,10 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
{
/* This is for now a dummy option. */
}
+ else if (!strcmp (key, "allow-pinentry-notify"))
+ {
+ ctrl->server_local->allow_pinentry_notify = 1;
+ }
else
return gpg_error (GPG_ERR_UNKNOWN_OPTION);
@@ -768,3 +774,29 @@ gpg_server (ctrl_t ctrl)
assuan_release (ctx);
return rc;
}
+
+
+/* Helper to notify the client about Pinentry events. Because that
+ might disturb some older clients, this is only done when enabled
+ via an option. If it is not enabled we tell Windows to allow
+ setting the foreground window right here. Returns an gpg error
+ code. */
+gpg_error_t
+gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
+{
+ if (!ctrl || !ctrl->server_local
+ || !ctrl->server_local->allow_pinentry_notify)
+ {
+ gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
+ /* Client might be interested in that event - send as status line. */
+ if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
+ && (line[17]==' '||!line[17]))
+ {
+ for (line += 17; *line && spacep (line); line++)
+ ;
+ write_status_text (STATUS_PINENTRY_LAUNCHED, line);
+ }
+ return 0;
+ }
+ return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
+}
diff --git a/g10/sign.c b/g10/sign.c
index 6ff7df6a9..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);
@@ -1604,6 +1605,8 @@ update_keysig_packet( PKT_signature **ret_sig,
/* create a new signature packet */
sig = copy_signature (NULL, orig_sig);
+ sig->digest_algo=digest_algo;
+
/* We need to create a new timestamp so that new sig expiration
calculations are done correctly... */
sig->timestamp=make_timestamp();