More agent support for gpg.

This commit is contained in:
Werner Koch 2010-10-13 15:57:08 +00:00
parent 5a679857ef
commit 54591341a4
33 changed files with 496 additions and 311 deletions

5
NEWS
View File

@ -43,10 +43,13 @@ Noteworthy changes in version 2.1.x (under development)
* The OpenPGP import command is now able to merge secret keys.
* Removed options:
* Removed GPG options:
--export-options: export-secret-subkey-passwd
--simple-sk-checksum
* New GPG options:
--try-secret-key
Noteworthy changes in version 2.0.13 (2009-09-04)
-------------------------------------------------

View File

@ -1,3 +1,24 @@
2010-10-13 Werner Koch <wk@g10code.com>
* call-pinentry.c (agent_get_passphrase): Support the close_button.
* gpg-agent.c (create_server_socket): Switch back to stderr
logging if we are not starting a agent.
* command.c (cmd_passwd, cmd_export_key): Move mapping of
GPG_ERR_FULLY_CANCELED to ..
(leave_cmd): .. here.
(option_handler): Add option agent-awareness.
* protect-tool.c (get_passphrase): Take care of
GPG_ERR_FULLY_CANCELED.
* findkey.c (try_unprotect_cb): Ditto.
(unprotect): Remove the fully_canceled hack.
* call-pinentry.c (start_pinentry): Ditto.
(agent_askpin): Ditto.
* pkdecrypt.c (agent_pkdecrypt): Ditto
* pksign.c (agent_pksign_do): Ditto.
* genkey.c (agent_ask_new_passphrase): Remove arg CANCEL_ALL.
2010-10-06 Werner Koch <wk@g10code.com>
* cvt-openpgp.c (convert_secret_key): Add missing break.

View File

@ -253,7 +253,7 @@ int pinentry_active_p (ctrl_t ctrl, int waitseconds);
int agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *inital_errtext,
struct pin_entry_info_s *pininfo, int *r_cancelall);
struct pin_entry_info_s *pininfo);
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext, int with_qualitybar);
@ -291,7 +291,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase, int *r_cancelall);
char **r_passphrase);
int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);

View File

@ -467,8 +467,10 @@ start_pinentry (ctrl_t ctrl)
else
{
rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
if (gpg_err_code (rc) == GPG_ERR_CANCELED)
return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
if (gpg_err_code (rc) == GPG_ERR_CANCELED
|| gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
gpg_err_code (rc)));
rc = 0;
}
@ -727,7 +729,7 @@ int
agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *initial_errtext,
struct pin_entry_info_s *pininfo, int *r_cancel_all)
struct pin_entry_info_s *pininfo)
{
int rc;
char line[ASSUAN_LINELENGTH];
@ -737,9 +739,6 @@ agent_askpin (ctrl_t ctrl,
int saveflag;
int close_button;
if (r_cancel_all)
*r_cancel_all = 0;
if (opt.batch)
return 0; /* fixme: we should return BAD PIN */
@ -830,10 +829,10 @@ agent_askpin (ctrl_t ctrl,
&& gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
/* Set a flag in case the window close button was clicked to
cancel the operation. */
if (close_button && r_cancel_all && gpg_err_code (rc) == GPG_ERR_CANCELED)
*r_cancel_all = 1;
/* Change error code in case the window close button was clicked
to cancel the operation. */
if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
errtext = is_pin? _("PIN too long")
@ -890,6 +889,7 @@ agent_get_passphrase (ctrl_t ctrl,
char line[ASSUAN_LINELENGTH];
struct entry_parm_s parm;
int saveflag;
int close_button;
*retpass = NULL;
if (opt.batch)
@ -942,14 +942,21 @@ agent_get_passphrase (ctrl_t ctrl,
saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
assuan_begin_confidential (entry_ctx);
close_button = 0;
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
inq_quality, entry_ctx, NULL, NULL);
inq_quality, entry_ctx,
close_button_status_cb, &close_button);
assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
/* Most pinentries out in the wild return the old Assuan error code
for canceled which gets translated to an assuan Cancel error and
not to the code for a user cancel. Fix this here. */
if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
/* Change error code in case the window close button was clicked
to cancel the operation. */
if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
if (rc)
xfree (parm.buffer);
else

View File

@ -2425,7 +2425,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
pi2->check_cb_arg = pi->pin;
next_try:
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL);
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
initial_errtext = NULL;
if (err)
goto out;
@ -2433,7 +2433,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
/* Unless the passphrase is empty, ask to confirm it. */
if (pi->pin && *pi->pin)
{
err = agent_askpin (ctrl, description2, NULL, NULL, pi2, NULL);
err = agent_askpin (ctrl, description2, NULL, NULL, pi2);
if (err == -1)
{ /* The re-entered one did not match and the user did not
hit cancel. */

View File

@ -71,6 +71,7 @@ struct server_local_s
be done. */
void *import_key; /* Malloced KEK for the import_key command. */
void *export_key; /* Malloced KEK for the export_key command. */
int allow_fully_canceled; /* Client is aware of GPG_ERR_FULLY_CANCELED. */
};
@ -364,6 +365,16 @@ leave_cmd (assuan_context_t ctx, gpg_error_t err)
if (!name)
name = "?";
/* Not all users of gpg-agent know about the fully canceled
error code; map it back if needed. */
if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
if (!ctrl->server_local->allow_fully_canceled)
err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED);
}
/* Most code from common/ does not know the error source, thus
we fix this here. */
if (gpg_err_source (err) == GPG_ERR_SOURCE_UNKNOWN)
@ -1336,12 +1347,7 @@ cmd_passwd (assuan_context_t ctx, char *line)
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey, NULL);
if (rc)
{
/* Not all users of gpg-agent know about fully cancled; thus we
map it back. */
if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
}
;
else if (!s_skey)
{
log_error ("changing a smartcard PIN is not yet supported\n");
@ -1643,7 +1649,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
err = agent_ask_new_passphrase
(ctrl, _("Please enter the passphrase to protect the "
"imported object within the GnuPG system."),
&passphrase, NULL);
&passphrase);
if (err)
goto leave;
}
@ -1751,17 +1757,12 @@ cmd_export_key (assuan_context_t ctx, char *line)
canonical S-expression. */
if (!passphrase)
{
int fully_canceled;
err = agent_ask_new_passphrase
(ctrl, _("This key (or subkey) is not protected with a passphrase."
" Please enter a new passphrase to export it."),
&passphrase, &fully_canceled);
&passphrase);
if (err)
{
if (fully_canceled)
err = gpg_error (GPG_ERR_FULLY_CANCELED);
goto leave;
}
goto leave;
}
err = convert_to_openpgp (ctrl, s_skey, passphrase, &key, &keylen);
}
@ -1814,10 +1815,6 @@ cmd_export_key (assuan_context_t ctx, char *line)
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
/* Not all users of gpg-agent know about fully cancled; thus we map
it back unless we know that it is okay. */
if (!openpgp && gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED);
return leave_cmd (ctx, err);
}
@ -2185,7 +2182,14 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
if (!strcmp (key, "putenv"))
if (!strcmp (key, "agent-awareness"))
{
/* The value is a version string telling us of which agent
version the caller is aware of. */
ctrl->server_local->allow_fully_canceled =
gnupg_compare_version (value, "2.1.0");
}
else if (!strcmp (key, "putenv"))
{
/* Change the session's environment to be used for the
Pinentry. Valid values are:

View File

@ -780,7 +780,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
err = try_do_unprotect_cb (pi);
}
if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
err = agent_askpin (ctrl, prompt, NULL, NULL, pi, NULL);
err = agent_askpin (ctrl, prompt, NULL, NULL, pi);
skeyidx = pi_arg.skeyidx;
if (!err)
{

View File

@ -266,7 +266,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
if (any_flags)
{
rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL);
rc = agent_askpin (ctrl, info, prompt, again_text, pi);
again_text = NULL;
if (!rc && newpin)
{
@ -288,7 +288,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
is_puk?
_("Repeat this PUK"):
_("Repeat this PIN")),
prompt, NULL, pi2, NULL);
prompt, NULL, pi2);
if (!rc && strcmp (pi->pin, pi2->pin))
{
again_text = (resetcode?
@ -312,7 +312,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
info? info:"",
info? "')":"") < 0)
desc = NULL;
rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL);
rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
xfree (desc);
}

View File

@ -169,7 +169,8 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
_("I'll change it later"), 0);
if (!err)
arg->change_required = 1;
else if (gpg_err_code (err) == GPG_ERR_CANCELED)
else if (gpg_err_code (err) == GPG_ERR_CANCELED
|| gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
err = 0;
}
xfree (desc);
@ -290,7 +291,6 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
unsigned char *result;
size_t resultlen;
char hexgrip[40+1];
int fully_canceled;
if (r_passphrase)
*r_passphrase = NULL;
@ -383,9 +383,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
arg.change_required = 0;
pi->check_cb_arg = &arg;
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, &fully_canceled);
if (gpg_err_code (rc) == GPG_ERR_CANCELED && fully_canceled)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
if (!rc)
{
assert (arg.unprotected_key);

View File

@ -290,12 +290,10 @@ reenter_compare_cb (struct pin_entry_info_s *pi)
function returns 0 and store the passphrase at R_PASSPHRASE; if the
user opted not to use a passphrase NULL will be stored there. The
user needs to free the returned string. In case of an error and
error code is returned and NULL stored at R_PASSPHRASE. If
R_CANCEL_ALL is not NULL and the user canceled by directly closing
the window true will be stored at this address. */
error code is returned and NULL stored at R_PASSPHRASE. */
gpg_error_t
agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase, int *r_cancel_all)
char **r_passphrase)
{
gpg_error_t err;
const char *text1 = prompt;
@ -316,7 +314,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
pi2->check_cb_arg = pi->pin;
next_try:
err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi, r_cancel_all);
err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
initial_errtext = NULL;
if (!err)
{
@ -329,7 +327,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
/* Unless the passphrase is empty, ask to confirm it. */
if (pi->pin && *pi->pin)
{
err = agent_askpin (ctrl, text2, NULL, NULL, pi2, NULL);
err = agent_askpin (ctrl, text2, NULL, NULL, pi2);
if (err == -1)
{ /* The re-entered one did not match and the user did not
hit cancel. */
@ -381,7 +379,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the passphrase to%0A"
"to protect your new key"),
&passphrase, NULL);
&passphrase);
if (rc)
return rc;
@ -473,7 +471,7 @@ agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the new passphrase"),
&passphrase, NULL);
&passphrase);
if (!rc)
{
rc = store_key (s_skey, passphrase, 1);

View File

@ -1523,6 +1523,8 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
a hang. */
if (!is_ssh && !check_for_running_agent (1, 1))
{
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
log_set_file (NULL);
log_error (_("a gpg-agent is already running - "
"not starting a new one\n"));
*name = 0; /* Inhibit removal of the socket by cleanup(). */

View File

@ -67,8 +67,6 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
rc = agent_key_from_file (ctrl, NULL, desc_text,
ctrl->keygrip, &shadow_info,
CACHE_MODE_NORMAL, NULL, &s_skey, NULL);
if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
if (rc)
{
if (gpg_err_code (rc) == GPG_ERR_ENOENT)

View File

@ -256,8 +256,6 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
rc = agent_key_from_file (ctrl, cache_nonce, desc_text, ctrl->keygrip,
&shadow_info, cache_mode, lookup_ttl,
&s_skey, NULL);
if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
if (rc)
{
log_error ("failed to read the secret key\n");

View File

@ -704,7 +704,8 @@ get_passphrase (int promptno)
repeat, repeat, 1, &pw);
if (err)
{
if (gpg_err_code (err) == GPG_ERR_CANCELED)
if (gpg_err_code (err) == GPG_ERR_CANCELED
|| gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
log_info (_("cancelled\n"));
else
log_error (_("error while asking for the passphrase: %s\n"),

View File

@ -1,3 +1,8 @@
2010-10-13 Werner Koch <wk@g10code.com>
* miscellaneous.c (parse_version_number, parse_version_string)
(gnupg_compare_version): New.
2010-10-04 Werner Koch <wk@g10code.com>
* gettime.c (asctimestamp) [W32CE]: Do not print the timezone.

View File

@ -236,3 +236,81 @@ match_multistr (const char *multistr,const char *match)
}
/* Parse the first portion of the version number S and store it at
NUMBER. On success, the function returns a pointer into S starting
with the first character, which is not part of the initial number
portion; on failure, NULL is returned. */
static const char*
parse_version_number (const char *s, int *number)
{
int val = 0;
if (*s == '0' && digitp (s+1))
return NULL; /* Leading zeros are not allowed. */
for (; digitp (s); s++ )
{
val *= 10;
val += *s - '0';
}
*number = val;
return val < 0? NULL : s;
}
/* Break up the complete string representation of the version number S,
which is expected to have this format:
<major number>.<minor number>.<micro number><patch level>.
The major, minor and micro number components will be stored at
MAJOR, MINOR and MICRO. On success, a pointer to the last
component, the patch level, will be returned; on failure, NULL will
be returned. */
static const char *
parse_version_string (const char *s, int *major, int *minor, int *micro)
{
s = parse_version_number (s, major);
if (!s || *s != '.')
return NULL;
s++;
s = parse_version_number (s, minor);
if (!s || *s != '.')
return NULL;
s++;
s = parse_version_number (s, micro);
if (!s)
return NULL;
return s; /* Patchlevel. */
}
/* Return true if version string is at least version B. */
int
gnupg_compare_version (const char *a, const char *b)
{
int a_major, a_minor, a_micro;
int b_major, b_minor, b_micro;
const char *a_plvl, *b_plvl;
if (!a || !b)
return 0;
/* Parse version A. */
a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
if (!a_plvl )
return 0; /* Invalid version number. */
/* Parse version B. */
b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
if (!b_plvl )
return 0; /* Invalid version number. */
/* Compare version numbers. */
return (a_major > b_major
|| (a_major == b_major && a_minor > b_minor)
|| (a_major == b_major && a_minor == b_minor
&& a_micro > b_micro)
|| (a_major == b_major && a_minor == b_minor
&& a_micro == b_micro
&& strcmp (a_plvl, b_plvl) >= 0));
}

View File

@ -267,6 +267,8 @@ int is_file_compressed (const char *s, int *ret_rc);
int match_multistr (const char *multistr,const char *match);
int gnupg_compare_version (const char *a, const char *b);
/*-- Simple replacement functions. */
#ifndef HAVE_TTYNAME

View File

@ -1782,13 +1782,27 @@ Remove all entries from the @option{--group} list.
Use @var{name} as the key to sign with. Note that this option overrides
@option{--default-key}.
@ifset gpgtwoone
@item --try-secret-key @var{name}
@opindex try-secret-key
For hidden recipients GPG needs to know the keys to use for trial
decryption. The key set with @option{--default-key} is always tried
first, but this is often not sufficient. This option allows to set more
keys to be used for trial decryption. Although any valid user-id
specification may be used for @var{name} it makes sense to use at least
the long keyid to avoid ambiguities. Note that gpg-agent might pop up a
pinentry for a lot keys to do the trial decryption. If you want to stop
all further trial decryption you may use close-window button instead of
the cancel button.
@end ifset
@item --try-all-secrets
@opindex try-all-secrets
Don't look at the key ID as stored in the message but try all secret
keys in turn to find the right decryption key. This option forces the
behaviour as used by anonymous recipients (created by using
@option{--throw-keyids}) and might come handy in case where an encrypted
message contains a bogus key ID.
@option{--throw-keyids} or @option{--hidden-recipient}) and might come
handy in case where an encrypted message contains a bogus key ID.
@item --skip-hidden-recipients
@itemx --no-skip-hidden-recipients

View File

@ -1,3 +1,33 @@
2010-10-13 Werner Koch <wk@g10code.com>
* call-agent.c (start_agent): Send option agent-awareness.
(status_sc_op_failure): Take care of GPG_ERR_FULLY_CANCELED.
* passphrase.c (passphrase_get): Ditto.
* import.c (transfer_secret_keys): Ditto.
* card-util.c (write_sc_op_status): Ditto.
* getkey.c (enum_secret_keys): Rewrite.
* pubkey-enc.c (get_session_key): Skip keys without an encryption
capability. Handle GPG_ERR_FULLY_CANCELED.
* gpg.c: Add option --try-secret-key.
* options.h (struct opt): Add field secret_keys_to_try.
* passphrase.c (next_to_last_passphrase): Remove.
2010-10-12 Werner Koch <wk@g10code.com>
* keygen.c (generate_subkeypair): Check availibility of secret parts.
* keylist.c (print_card_serialno): Change to take a hexified serialno.
(list_keyblock_print): Print serialno and stub key indicators.
(list_keyblock_colon): Ditto.
* getkey.c (have_any_secret_key): Remove. Replace all calls by
agent_probe_any_secret_key.
* gpgv.c (agent_probe_any_secret_key): New.
(agent_get_keyinfo): New.
2010-10-08 Werner Koch <wk@g10code.com>
* gpg.c: Add option --with-keygrip.

View File

@ -99,6 +99,7 @@ status_sc_op_failure (int rc)
case 0:
break;
case GPG_ERR_CANCELED:
case GPG_ERR_FULLY_CANCELED:
write_status_text (STATUS_SC_OP_FAILURE, "1");
break;
case GPG_ERR_BAD_PIN:
@ -142,6 +143,11 @@ start_agent (ctrl_t ctrl, int for_card)
agents. */
assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
NULL, NULL, NULL, NULL, NULL, NULL);
/* Tell the agent about what version we are aware. This is
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);
}
}

View File

@ -58,6 +58,7 @@ write_sc_op_status (gpg_error_t err)
break;
#if GNUPG_MAJOR_VERSION != 1
case GPG_ERR_CANCELED:
case GPG_ERR_FULLY_CANCELED:
write_status_text (STATUS_SC_OP_FAILURE, "1");
break;
case GPG_ERR_BAD_PIN:

View File

@ -568,8 +568,9 @@ leave:
* first pubkey certificate which has the given name in a user_id. If
* PK has the pubkey algo set, the function will only return a pubkey
* with that algo. If NAMELIST is NULL, the first key is returned.
* The caller should provide storage for the PK. If RET_KB is not
* NULL the function will return the keyblock there. */
* The caller should provide storage for the PK or pass NULL if it is
* not needed. If RET_KB is not NULL the function stores the entire
* keyblock at that address. */
static int
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
PKT_public_key *pk,
@ -1146,12 +1147,13 @@ getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk,
}
/* Get a key by name and store it into PK. If RETCTX is not NULL
* return the search context which needs to be released by the caller
* using getkey_end. If NAME is NULL use the default key (see below).
* On success and if RET_KEYBLOCK is not NULL the found keyblock is
* stored at this address. WANT_SECRET passed as true requires that a
* secret key is available for the selected key.
/* Get a key by name and store it into PK if that is not NULL. If
* RETCTX is not NULL return the search context which needs to be
* released by the caller using getkey_end. If NAME is NULL use the
* default key (see below). On success and if RET_KEYBLOCK is not
* NULL the found keyblock is stored at this address. WANT_SECRET
* passed as true requires that a secret key is available for the
* selected key.
*
* If WANT_SECRET is true and NAME is NULL and a default key has been
* defined that defined key is used. In all other cases the first
@ -2459,7 +2461,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret)
goto skip;
}
if (want_secret && !have_any_secret_key (NULL, ctx->keyblock))
if (want_secret && agent_probe_any_secret_key (NULL, ctx->keyblock))
goto skip; /* No secret key available. */
/* Warning: node flag bits 0 and 1 should be preserved by
@ -2504,57 +2506,42 @@ found:
/****************
* FIXME: Replace by the generic function
* It does not work as it is right now - it is used at
* one place: to get the key for an anonymous recipient.
*
* set with_subkeys true to include subkeys
* set with_spm true to include secret-parts-missing keys
*
* Enumerate all primary secret keys. Caller must use these procedure:
/*
* Enumerate certain secret keys. Caller must use these procedure:
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function
* and provide space for the secret key (pass a buffer for sk)
* 3) call this function as long as it does not return -1
* to indicate EOF.
* 3) call this function as long as it does not return an error.
* The error code GPG_ERR_EOF indicates the end of the listing.
* 4) Always call this function a last time with SK set to NULL,
* so that can free it's context.
*/
int
enum_secret_keys (void **context, PKT_public_key * sk,
int with_subkeys, int with_spm)
gpg_error_t
enum_secret_keys (void **context, PKT_public_key *sk)
{
log_debug ("FIXME: Anonymous recipient does not yet work\n");
return -1;
#if 0
int rc = 0;
gpg_error_t err = 0;
const char *name;
struct
{
int eof;
int first;
KEYDB_HANDLE hd;
KBNODE keyblock;
KBNODE node;
int state;
strlist_t sl;
kbnode_t keyblock;
kbnode_t node;
} *c = *context;
if (!c)
{
/* Make a new context. */
c = xmalloc_clear (sizeof *c);
c = xtrycalloc (1, sizeof *c);
if (!c)
return gpg_error_from_syserror ();
*context = c;
c->hd = keydb_new (1); /*FIXME*/
c->first = 1;
c->keyblock = NULL;
c->node = NULL;
}
if (!sk)
{
/* Free the context. */
keydb_release (c->hd);
release_kbnode (c->keyblock);
xfree (c);
*context = NULL;
@ -2562,48 +2549,79 @@ enum_secret_keys (void **context, PKT_public_key * sk,
}
if (c->eof)
return -1;
return gpg_error (GPG_ERR_EOF);
do
for (;;)
{
/* Get the next secret key from the current keyblock. */
/* Loop until we have a keyblock. */
while (!c->keyblock)
{
/* Loop over the list of secret keys. */
do
{
name = NULL;
switch (c->state)
{
case 0: /* First try to use the --default-key. */
if (opt.def_secret_key && *opt.def_secret_key)
name = opt.def_secret_key;
c->state = 1;
break;
case 1: /* Init list of keys to try. */
c->sl = opt.secret_keys_to_try;
c->state++;
break;
case 2: /* Get next item from list. */
if (c->sl)
{
name = c->sl->d;
c->sl = c->sl->next;
}
else
c->state++;
break;
default: /* No more names to check - stop. */
c->eof = 1;
return gpg_error (GPG_ERR_EOF);
}
}
while (!name || !*name);
err = getkey_byname (NULL, NULL, name, 1, &c->keyblock);
if (err)
{
/* getkey_byname might return a keyblock even in the
error case - I have not checked. Thus better release
it. */
release_kbnode (c->keyblock);
c->keyblock = NULL;
}
else
c->node = c->keyblock;
}
/* Get the next key from the current keyblock. */
for (; c->node; c->node = c->node->next)
{
if ((c->node->pkt->pkttype == PKT_SECRET_KEY
|| (with_subkeys
&& c->node->pkt->pkttype == PKT_SECRET_SUBKEY))
&& !(c->node->pkt->pkt.secret_key->protect.s2k.mode == 1001
&& !with_spm))
if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
|| c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
copy_secret_key (sk, c->node->pkt->pkt.secret_key);
copy_public_key (sk, c->node->pkt->pkt.public_key);
c->node = c->node->next;
return 0; /* Found. */
}
}
}
/* Dispose the keyblock and continue. */
release_kbnode (c->keyblock);
c->keyblock = c->node = NULL;
rc = c->first ? keydb_search_first (c->hd) : keydb_search_next (c->hd);
c->first = 0;
if (rc)
{
keydb_release (c->hd);
c->hd = NULL;
c->eof = 1;
return -1; /* eof */
}
rc = keydb_get_keyblock (c->hd, &c->keyblock);
c->node = c->keyblock;
c->keyblock = NULL;
}
while (!rc);
return rc; /* Error. */
#endif
}
/*********************************************
*********** User ID printing helpers *******
*********************************************/

View File

@ -177,6 +177,7 @@ enum cmd_and_opt_values
oDefRecipient,
oDefRecipientSelf,
oNoDefRecipient,
oTrySecretKey,
oOptions,
oDebug,
oDebugLevel,
@ -460,6 +461,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oLocalUser, "local-user",
N_("|USER-ID|use USER-ID to sign or decrypt")),
ARGPARSE_s_s (oTrySecretKey, "try-secret-key", "@"),
ARGPARSE_s_i (oCompress, NULL,
N_("|N|set compress level to N (0 disables)")),
ARGPARSE_s_i (oCompressLevel, "compress-level", "@"),
@ -1622,6 +1625,7 @@ gpgconf_list (const char *configfile)
es_printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("default-key:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("try-secret-key:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
@ -2526,6 +2530,12 @@ main (int argc, char **argv)
sl->flags = 2;
any_explicit_recipient = 1;
break;
case oTrySecretKey:
add_to_strlist2 (&opt.secret_keys_to_try,
pargs.r.ret_str, utf8_strings);
break;
case oTextmodeShort: opt.textmode = 2; break;
case oTextmode: opt.textmode=1; break;
case oNoTextmode: opt.textmode=0; break;

View File

@ -546,3 +546,21 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
(void)pk;
return gpg_error (GPG_ERR_NO_SECKEY);
}
gpg_error_t
agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
{
(void)ctrl;
(void)keyblock;
return gpg_error (GPG_ERR_NO_SECKEY);
}
gpg_error_t
agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
{
(void)ctrl;
(void)hexkeygrip;
*r_serialno = NULL;
return gpg_error (GPG_ERR_NO_SECKEY);
}

View File

@ -362,7 +362,7 @@ import_print_stats (void *hd)
* Read the next keyblock from stream A.
* PENDING_PKT should be initialzed to NULL
* and not chnaged form the caller.
* Retunr: 0 = okay, -1 no more blocks or another errorcode.
* Return: 0 = okay, -1 no more blocks or another errorcode.
*/
static int
read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
@ -1142,8 +1142,15 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
stats->count++;
stats->secret_read++;
/* For now we ignore the stub keys becuase we don't have real
support for them in gpg-agent. */
/* We ignore stub keys. The way we handle them in other parts
of the code is by asking the agent whether any secret key is
available for a given keyblock and then concluding that we
have a secret key; all secret (sub)keys of the keyblock the
agent does not know of are then stub keys. This works also
for card stub keys. The learn command or the card-status
command may be used to check with the agent whether a card
has been inserted and a stub key is in turn generated by the
agent. */
if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002)
continue;
@ -1288,7 +1295,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
write_status (STATUS_RSA_OR_IDEA);
idea_cipher_warn (0);
}
if (gpg_err_code (err) == GPG_ERR_CANCELED)
if (gpg_err_code (err) == GPG_ERR_CANCELED
|| gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
break; /* Don't try the other subkeys. */
}
}

View File

@ -241,11 +241,8 @@ gpg_error_t getkey_next (getkey_ctx_t ctx, PKT_public_key *pk,
kbnode_t *ret_keyblock);
void getkey_end (getkey_ctx_t ctx);
int have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock);
gpg_error_t enum_secret_keys (void **context, PKT_public_key *pk);
//int enum_secret_keys( void **context, PKT_secret_key *sk,
// int with_subkeys, int with_spm );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_user_id_string_native( u32 *keyid );

View File

@ -1638,7 +1638,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
/* See whether we have a matching secret key. */
if (seckey_check)
{
have_seckey = have_any_secret_key (ctrl, keyblock);
have_seckey = !agent_probe_any_secret_key (ctrl, keyblock);
if (have_seckey && !quiet)
tty_printf (_("Secret key is available.\n"));
}

View File

@ -3441,6 +3441,8 @@ generate_subkeypair (KBNODE keyblock)
u32 expire;
unsigned int nbits;
u32 cur_time;
char *hexgrip = NULL;
char *serialno = NULL;
/* Break out the primary key. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@ -3476,37 +3478,16 @@ generate_subkeypair (KBNODE keyblock)
goto leave;
}
#warning ask gpg-agent on the availibility of the secret key
/* if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) */
/* { */
/* tty_printf (_("Secret parts of primary key are not available.\n")); */
/* err = G10ERR_NO_SECKEY; */
/* goto leave; */
/* } */
/* /\* Unprotect to get the passphrase. *\/ */
/* switch (is_secret_key_protected (pri_sk) ) */
/* { */
/* case -1: */
/* err = G10ERR_PUBKEY_ALGO; */
/* break; */
/* case 0: */
/* tty_printf (_("This key is not protected.\n")); */
/* break; */
/* case -2: */
/* tty_printf (_("Secret parts of primary key are stored on-card.\n")); */
/* ask_pass = 1; */
/* break; */
/* default: */
/* tty_printf (_("Key is protected.\n")); */
/* err = check_secret_key ( pri_sk, 0 ); */
/* if (!err) */
/* passphrase = get_last_passphrase(); */
/* break; */
/* } */
/* if (err) */
/* goto leave; */
err = hexkeygrip_from_pk (pri_psk, &hexgrip);
if (err)
goto leave;
if (agent_get_keyinfo (NULL, hexgrip, &serialno))
{
tty_printf (_("Secret parts of primary key are not available.\n"));
goto leave;
}
if (serialno)
tty_printf (_("Secret parts of primary key are stored on-card.\n"));
algo = ask_algo (1, NULL, &use);
assert (algo);
@ -3536,6 +3517,8 @@ generate_subkeypair (KBNODE keyblock)
write_status_text (STATUS_KEY_CREATED, "S");
leave:
xfree (hexgrip);
xfree (serialno);
if (err)
log_error (_("Key generation failed: %s\n"), g10_errstr (err) );
return err;

View File

@ -40,11 +40,12 @@
#include "main.h"
#include "i18n.h"
#include "status.h"
#include "call-agent.h"
static void list_all (int);
static void list_one (strlist_t names, int secret);
static void locate_one (ctrl_t ctrl, strlist_t names);
static void print_card_serialno (PKT_public_key *sk);
static void print_card_serialno (const char *serialno);
struct sig_stats
{
@ -175,6 +176,7 @@ print_pubkey_info (estream_t fp, PKT_public_key * pk)
/* Print basic information of a secret key including the card serial
number information. */
#ifdef ENABLE_CARD_SUPPORT
void
print_card_key_info (estream_t fp, kbnode_t keyblock)
{
@ -224,7 +226,7 @@ print_card_key_info (estream_t fp, kbnode_t keyblock)
/* } */
/* } */
}
#endif /*ENABLE_CARD_SUPPORT*/
/* Flags = 0x01 hashed 0x02 critical. */
@ -444,7 +446,7 @@ list_all (int secret)
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
goto leave;
}
if (secret && !have_any_secret_key (NULL, keyblock))
if (secret && agent_probe_any_secret_key (NULL, keyblock))
; /* Secret key listing requested but this isn't one. */
else
{
@ -757,13 +759,15 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
static void
list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
{
int rc = 0;
int rc;
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
struct sig_stats *stats = opaque;
int skip_sigs = 0;
int s2k_char;
char *hexgrip = NULL;
char *serialno = NULL;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@ -775,10 +779,23 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
}
pk = node->pkt->pkt.public_key;
/* Fixme: Get s2k mode from the agent. */
s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
(sk->protect.s2k.mode == 1002)? '>' : */' ');
if (secret || opt.with_keygrip)
{
rc = hexkeygrip_from_pk (pk, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
}
if (secret)
{
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
}
else
s2k_char = ' ';
check_trustdb_stale ();
@ -822,19 +839,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
if (fpr)
print_fingerprint (pk, 0);
if (opt.with_keygrip)
{
char *p;
if (opt.with_keygrip && hexgrip)
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
if (!hexkeygrip_from_pk (pk, &p))
{
es_fprintf (es_stdout, " Keygrip = %s\n", p);
xfree (p);
}
}
/* FIXME: Change this function to take a PK and ask the agent: */
/* if (secret) print_card_serialno (sk); */
if (serialno)
print_card_serialno (serialno);
if (opt.with_key_data)
print_key_data (pk);
@ -895,10 +904,25 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
else
skip_sigs = 0;
/* Fixme: Get s2k mode from the agent. */
s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
(sk->protect.s2k.mode == 1002)? '>' : */' ');
xfree (serialno); serialno = NULL;
xfree (hexgrip); hexgrip = NULL;
if (secret || opt.with_keygrip)
{
rc = hexkeygrip_from_pk (pk2, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n",
gpg_strerror (rc));
}
if (secret)
{
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
}
else
s2k_char = ' ';
es_fprintf (es_stdout, "%s%c %4u%c/%s %s",
secret? "ssb":"sub",
s2k_char,
@ -926,20 +950,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
if (fpr > 1)
{
print_fingerprint (pk2, 0);
/* FIXME: (see above) */
/* if (secret) */
/* print_card_serialno (sk2); */
}
if (opt.with_keygrip)
{
char *p;
if (!hexkeygrip_from_pk (pk2, &p))
{
es_fprintf (es_stdout, " Keygrip = %s\n", p);
xfree (p);
}
if (serialno)
print_card_serialno (serialno);
}
if (opt.with_keygrip && hexgrip)
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk2);
}
@ -1050,6 +1065,8 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
}
}
es_putc ('\n', es_stdout);
xfree (serialno);
xfree (hexgrip);
}
void
@ -1079,7 +1096,7 @@ print_revokers (PKT_public_key * pk)
static void
list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
int rc = 0;
int rc;
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
@ -1088,6 +1105,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
int ulti_hack = 0;
int i;
char *p;
char *hexgrip = NULL;
char *serialno = NULL;
int stubkey;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@ -1099,6 +1119,15 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
}
pk = node->pkt->pkt.public_key;
if (secret || opt.with_keygrip || opt.with_key_data)
{
rc = hexkeygrip_from_pk (pk, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
}
stubkey = 0;
if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
stubkey = 1; /* Key not found. */
keyid_from_pk (pk, keyid);
es_fputs (secret? "sec:":"pub:", es_stdout);
@ -1135,16 +1164,10 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
if (/*FIXME sk->protect.s2k.mode*/1 == 1001)
es_putc ('#', es_stdout); /* Key is just a stub. */
else if (/*FIXME sk->protect.s2k.mode*/1 == 1002)
{
/* Key is stored on an external token (card) or handled by
the gpg-agent. Print the serial number of that token
here. */
/* FIXME: for (i = 0; i < sk->protect.ivlen; i++) */
/* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
}
if (stubkey)
es_putc ('#', es_stdout);
else if (serialno)
es_fputs(serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
}
es_putc ('\n', es_stdout);
@ -1154,11 +1177,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
print_fingerprint (pk, 0);
if (opt.with_key_data || opt.with_keygrip)
{
if (!hexkeygrip_from_pk (pk, &p))
{
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
xfree (p);
}
if (hexgrip)
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk);
}
@ -1213,7 +1233,21 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
u32 keyid2[2];
PKT_public_key *pk2 = node->pkt->pkt.public_key;
PKT_public_key *pk2;
pk2 = node->pkt->pkt.public_key;
xfree (hexgrip); hexgrip = NULL;
xfree (serialno); serialno = NULL;
if (secret || opt.with_keygrip || opt.with_key_data)
{
rc = hexkeygrip_from_pk (pk2, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n",
gpg_strerror (rc));
}
stubkey = 0;
if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
stubkey = 1; /* Key not found. */
keyid_from_pk (pk2, keyid2);
es_fputs (secret? "ssb:":"sub:", es_stdout);
@ -1243,16 +1277,10 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
if (/*FIXME:sk2->protect.s2k.mode*/1 == 1001)
es_putc ('#', es_stdout); /* Key is just a stub. */
else if (/*FIXME: sk2->protect.s2k.mode*/1 == 1002)
{
/* Key is stored on an external token (card) or
handled by the gpg-agent. Print the serial
number of that token here. */
/* FIXME: for (i = 0; i < sk2->protect.ivlen; i++)
es_fprintf (es_stdout, "%02X", sk2->protect.iv[i]); */
}
if (stubkey)
es_putc ('#', es_stdout);
else if (serialno)
es_fputs (serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
}
es_putc ('\n', es_stdout);
@ -1260,11 +1288,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
print_fingerprint (pk2, 0);
if (opt.with_key_data || opt.with_keygrip)
{
if (!hexkeygrip_from_pk (pk2, &p))
{
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
xfree (p);
}
if (hexgrip)
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
if (opt.with_key_data)
print_key_data (pk2);
}
@ -1385,6 +1410,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
/* fixme: check or list other sigs here */
}
}
xfree (hexgrip);
xfree (serialno);
}
/*
@ -1550,38 +1578,25 @@ print_fingerprint (PKT_public_key *pk, int mode)
/* Print the serial number of an OpenPGP card if available. */
static void
print_card_serialno (PKT_public_key *pk)
print_card_serialno (const char *serialno)
{
log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
/* int i; */
if (!serialno)
return;
if (opt.with_colons)
return; /* Handled elsewhere. */
/* if (!sk) */
/* return; */
/* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
/* return; /\* Not a card. *\/ */
/* if (opt.with_colons) */
/* return; /\* Handled elsewhere. *\/ */
/* es_fputs (_(" Card serial no. ="), es_stdout); */
/* es_putc (' ', es_stdout); */
/* if (sk->protect.ivlen == 16 */
/* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
/* { */
/* /\* This is an OpenPGP card. Just print the relevant part. *\/ */
/* for (i = 8; i < 14; i++) */
/* { */
/* if (i == 10) */
/* es_putc (' ', es_stdout); */
/* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
/* } */
/* } */
/* else */
/* { */
/* /\* Something is wrong: Print all. *\/ */
/* for (i = 0; i < sk->protect.ivlen; i++) */
/* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
/* } */
/* es_putc ('\n', es_stdout); */
es_fputs (_(" Card serial no. ="), es_stdout);
es_putc (' ', es_stdout);
if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
{
/* This is an OpenPGP card. Print the relevant part. */
/* Example: D2760001240101010001000003470000 */
/* xxxxyyyyyyyy */
es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
}
else
es_fputs (serialno, es_stdout);
es_putc ('\n', es_stdout);
}

View File

@ -555,11 +555,10 @@ get_signature_count (PKT_public_key *pk)
/* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
/* return info.sig_counter; */
/* } */
#endif
/* How to do this without a card? */
#else
(void)pk;
return 0;
#endif
}
/* Expand %-strings. Returns a string which must be xfreed. Returns

View File

@ -79,6 +79,8 @@ struct
const char *def_secret_key;
char *def_recipient;
int def_recipient_self;
strlist_t secret_keys_to_try;
int def_cert_level;
int min_cert_level;
int ask_cert_level;

View File

@ -211,17 +211,6 @@ get_last_passphrase()
return p;
}
/* As if we had used the passphrase - make it the last_pw. */
void
next_to_last_passphrase(void)
{
if (next_pw)
{
last_pw=next_pw;
next_pw=NULL;
}
}
/* Here's an interesting question: since this passphrase was passed in
on the command line, is there really any point in using secure
memory for it? I'm going with 'yes', since it doesn't hurt, and
@ -407,7 +396,8 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
if (!rc)
;
else if ( gpg_err_code (rc) == GPG_ERR_CANCELED )
else if (gpg_err_code (rc) == GPG_ERR_CANCELED
|| gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
{
log_info (_("cancelled by user\n") );
if (canceled)

View File

@ -94,14 +94,13 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
{
void *enum_context = NULL;
u32 keyid[2];
char *p;
for (;;)
{
if (sk)
free_public_key (sk);
sk = xmalloc_clear (sizeof *sk);
rc = -1; /* FIXME:enum_secret_keys (&enum_context, sk, 1, 0);*/
rc = enum_secret_keys (&enum_context, sk);
if (rc)
{
rc = G10ERR_NO_SECKEY;
@ -109,42 +108,22 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
}
if (sk->pubkey_algo != k->pubkey_algo)
continue;
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
continue;
keyid_from_pk (sk, keyid);
log_info (_("anonymous recipient; trying secret key %s ...\n"),
keystr (keyid));
if (!opt.try_all_secrets && !is_status_enabled ())
{
p = get_last_passphrase ();
set_next_passphrase (p);
xfree (p);
}
/* rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /\* ask */
/* only */
/* once *\/ */
/* if( !rc ) */
{
rc = get_it (k, dek, sk, keyid);
/* Successfully checked the secret key (either it was a
card, had no passphrase, or had the right passphrase)
but couldn't decrypt the session key, so thus that key
is not the anonymous recipient. Move the next
passphrase into last for the next round. We only do
this if the secret key was successfully checked as in
the normal case, check_secret_key handles this for us
via passphrase_to_dek. */
if (rc)
next_to_last_passphrase ();
}
rc = get_it (k, dek, sk, keyid);
if (!rc)
{
log_info (_("okay, we are the anonymous recipient.\n"));
break;
}
else if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
break; /* Don't try any more secret keys. */
}
enum_secret_keys (&enum_context, NULL, 0, 0); /* free context */
enum_secret_keys (&enum_context, NULL); /* free context */
}
leave: