mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
More agent support for gpg.
This commit is contained in:
parent
5a679857ef
commit
54591341a4
5
NEWS
5
NEWS
@ -43,10 +43,13 @@ Noteworthy changes in version 2.1.x (under development)
|
|||||||
|
|
||||||
* The OpenPGP import command is now able to merge secret keys.
|
* The OpenPGP import command is now able to merge secret keys.
|
||||||
|
|
||||||
* Removed options:
|
* Removed GPG options:
|
||||||
--export-options: export-secret-subkey-passwd
|
--export-options: export-secret-subkey-passwd
|
||||||
--simple-sk-checksum
|
--simple-sk-checksum
|
||||||
|
|
||||||
|
* New GPG options:
|
||||||
|
--try-secret-key
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.13 (2009-09-04)
|
Noteworthy changes in version 2.0.13 (2009-09-04)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
@ -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>
|
2010-10-06 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* cvt-openpgp.c (convert_secret_key): Add missing break.
|
* cvt-openpgp.c (convert_secret_key): Add missing break.
|
||||||
|
@ -253,7 +253,7 @@ int pinentry_active_p (ctrl_t ctrl, int waitseconds);
|
|||||||
int agent_askpin (ctrl_t ctrl,
|
int agent_askpin (ctrl_t ctrl,
|
||||||
const char *desc_text, const char *prompt_text,
|
const char *desc_text, const char *prompt_text,
|
||||||
const char *inital_errtext,
|
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,
|
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
|
||||||
const char *desc, const char *prompt,
|
const char *desc, const char *prompt,
|
||||||
const char *errtext, int with_qualitybar);
|
const char *errtext, int with_qualitybar);
|
||||||
@ -291,7 +291,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
/*-- genkey.c --*/
|
/*-- genkey.c --*/
|
||||||
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
|
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,
|
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,
|
int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
||||||
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
|
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
|
||||||
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
|
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
|
||||||
|
@ -467,8 +467,10 @@ start_pinentry (ctrl_t ctrl)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
|
rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_CANCELED)
|
if (gpg_err_code (rc) == GPG_ERR_CANCELED
|
||||||
return unlock_pinentry (gpg_error (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;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,7 +729,7 @@ int
|
|||||||
agent_askpin (ctrl_t ctrl,
|
agent_askpin (ctrl_t ctrl,
|
||||||
const char *desc_text, const char *prompt_text,
|
const char *desc_text, const char *prompt_text,
|
||||||
const char *initial_errtext,
|
const char *initial_errtext,
|
||||||
struct pin_entry_info_s *pininfo, int *r_cancel_all)
|
struct pin_entry_info_s *pininfo)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
@ -737,9 +739,6 @@ agent_askpin (ctrl_t ctrl,
|
|||||||
int saveflag;
|
int saveflag;
|
||||||
int close_button;
|
int close_button;
|
||||||
|
|
||||||
if (r_cancel_all)
|
|
||||||
*r_cancel_all = 0;
|
|
||||||
|
|
||||||
if (opt.batch)
|
if (opt.batch)
|
||||||
return 0; /* fixme: we should return BAD PIN */
|
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)
|
&& gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
|
||||||
|
|
||||||
/* Set a flag in case the window close button was clicked to
|
/* Change error code in case the window close button was clicked
|
||||||
cancel the operation. */
|
to cancel the operation. */
|
||||||
if (close_button && r_cancel_all && gpg_err_code (rc) == GPG_ERR_CANCELED)
|
if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
|
||||||
*r_cancel_all = 1;
|
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
|
||||||
|
|
||||||
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
|
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
|
||||||
errtext = is_pin? _("PIN too long")
|
errtext = is_pin? _("PIN too long")
|
||||||
@ -890,6 +889,7 @@ agent_get_passphrase (ctrl_t ctrl,
|
|||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
struct entry_parm_s parm;
|
struct entry_parm_s parm;
|
||||||
int saveflag;
|
int saveflag;
|
||||||
|
int close_button;
|
||||||
|
|
||||||
*retpass = NULL;
|
*retpass = NULL;
|
||||||
if (opt.batch)
|
if (opt.batch)
|
||||||
@ -942,14 +942,21 @@ agent_get_passphrase (ctrl_t ctrl,
|
|||||||
|
|
||||||
saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
|
saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
|
||||||
assuan_begin_confidential (entry_ctx);
|
assuan_begin_confidential (entry_ctx);
|
||||||
|
close_button = 0;
|
||||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
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);
|
assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
|
||||||
/* Most pinentries out in the wild return the old Assuan error code
|
/* Most pinentries out in the wild return the old Assuan error code
|
||||||
for canceled which gets translated to an assuan Cancel error and
|
for canceled which gets translated to an assuan Cancel error and
|
||||||
not to the code for a user cancel. Fix this here. */
|
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)
|
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);
|
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)
|
if (rc)
|
||||||
xfree (parm.buffer);
|
xfree (parm.buffer);
|
||||||
else
|
else
|
||||||
|
@ -2425,7 +2425,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
|
|||||||
pi2->check_cb_arg = pi->pin;
|
pi2->check_cb_arg = pi->pin;
|
||||||
|
|
||||||
next_try:
|
next_try:
|
||||||
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL);
|
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
|
||||||
initial_errtext = NULL;
|
initial_errtext = NULL;
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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. */
|
/* Unless the passphrase is empty, ask to confirm it. */
|
||||||
if (pi->pin && *pi->pin)
|
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)
|
if (err == -1)
|
||||||
{ /* The re-entered one did not match and the user did not
|
{ /* The re-entered one did not match and the user did not
|
||||||
hit cancel. */
|
hit cancel. */
|
||||||
|
@ -71,6 +71,7 @@ struct server_local_s
|
|||||||
be done. */
|
be done. */
|
||||||
void *import_key; /* Malloced KEK for the import_key command. */
|
void *import_key; /* Malloced KEK for the import_key command. */
|
||||||
void *export_key; /* Malloced KEK for the export_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)
|
if (!name)
|
||||||
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
|
/* Most code from common/ does not know the error source, thus
|
||||||
we fix this here. */
|
we fix this here. */
|
||||||
if (gpg_err_source (err) == GPG_ERR_SOURCE_UNKNOWN)
|
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,
|
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
|
||||||
&s_skey, NULL);
|
&s_skey, NULL);
|
||||||
if (rc)
|
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)
|
else if (!s_skey)
|
||||||
{
|
{
|
||||||
log_error ("changing a smartcard PIN is not yet supported\n");
|
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
|
err = agent_ask_new_passphrase
|
||||||
(ctrl, _("Please enter the passphrase to protect the "
|
(ctrl, _("Please enter the passphrase to protect the "
|
||||||
"imported object within the GnuPG system."),
|
"imported object within the GnuPG system."),
|
||||||
&passphrase, NULL);
|
&passphrase);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1751,17 +1757,12 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
|||||||
canonical S-expression. */
|
canonical S-expression. */
|
||||||
if (!passphrase)
|
if (!passphrase)
|
||||||
{
|
{
|
||||||
int fully_canceled;
|
|
||||||
err = agent_ask_new_passphrase
|
err = agent_ask_new_passphrase
|
||||||
(ctrl, _("This key (or subkey) is not protected with a passphrase."
|
(ctrl, _("This key (or subkey) is not protected with a passphrase."
|
||||||
" Please enter a new passphrase to export it."),
|
" Please enter a new passphrase to export it."),
|
||||||
&passphrase, &fully_canceled);
|
&passphrase);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
goto leave;
|
||||||
if (fully_canceled)
|
|
||||||
err = gpg_error (GPG_ERR_FULLY_CANCELED);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
err = convert_to_openpgp (ctrl, s_skey, passphrase, &key, &keylen);
|
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);
|
xfree (ctrl->server_local->keydesc);
|
||||||
ctrl->server_local->keydesc = NULL;
|
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);
|
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);
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
gpg_error_t err = 0;
|
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
|
/* Change the session's environment to be used for the
|
||||||
Pinentry. Valid values are:
|
Pinentry. Valid values are:
|
||||||
|
@ -780,7 +780,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
|
|||||||
err = try_do_unprotect_cb (pi);
|
err = try_do_unprotect_cb (pi);
|
||||||
}
|
}
|
||||||
if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
|
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;
|
skeyidx = pi_arg.skeyidx;
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +266,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
|||||||
|
|
||||||
if (any_flags)
|
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;
|
again_text = NULL;
|
||||||
if (!rc && newpin)
|
if (!rc && newpin)
|
||||||
{
|
{
|
||||||
@ -288,7 +288,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
|||||||
is_puk?
|
is_puk?
|
||||||
_("Repeat this PUK"):
|
_("Repeat this PUK"):
|
||||||
_("Repeat this PIN")),
|
_("Repeat this PIN")),
|
||||||
prompt, NULL, pi2, NULL);
|
prompt, NULL, pi2);
|
||||||
if (!rc && strcmp (pi->pin, pi2->pin))
|
if (!rc && strcmp (pi->pin, pi2->pin))
|
||||||
{
|
{
|
||||||
again_text = (resetcode?
|
again_text = (resetcode?
|
||||||
@ -312,7 +312,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
|||||||
info? info:"",
|
info? info:"",
|
||||||
info? "')":"") < 0)
|
info? "')":"") < 0)
|
||||||
desc = NULL;
|
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);
|
xfree (desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,8 @@ try_unprotect_cb (struct pin_entry_info_s *pi)
|
|||||||
_("I'll change it later"), 0);
|
_("I'll change it later"), 0);
|
||||||
if (!err)
|
if (!err)
|
||||||
arg->change_required = 1;
|
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;
|
err = 0;
|
||||||
}
|
}
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
@ -290,7 +291,6 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
unsigned char *result;
|
unsigned char *result;
|
||||||
size_t resultlen;
|
size_t resultlen;
|
||||||
char hexgrip[40+1];
|
char hexgrip[40+1];
|
||||||
int fully_canceled;
|
|
||||||
|
|
||||||
if (r_passphrase)
|
if (r_passphrase)
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
@ -383,9 +383,7 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
|
|||||||
arg.change_required = 0;
|
arg.change_required = 0;
|
||||||
pi->check_cb_arg = &arg;
|
pi->check_cb_arg = &arg;
|
||||||
|
|
||||||
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi, &fully_canceled);
|
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_CANCELED && fully_canceled)
|
|
||||||
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
assert (arg.unprotected_key);
|
assert (arg.unprotected_key);
|
||||||
|
@ -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
|
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 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
|
user needs to free the returned string. In case of an error and
|
||||||
error code is returned and NULL stored at R_PASSPHRASE. If
|
error code is returned and NULL stored at R_PASSPHRASE. */
|
||||||
R_CANCEL_ALL is not NULL and the user canceled by directly closing
|
|
||||||
the window true will be stored at this address. */
|
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
|
agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
|
||||||
char **r_passphrase, int *r_cancel_all)
|
char **r_passphrase)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
const char *text1 = prompt;
|
const char *text1 = prompt;
|
||||||
@ -316,7 +314,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
|
|||||||
pi2->check_cb_arg = pi->pin;
|
pi2->check_cb_arg = pi->pin;
|
||||||
|
|
||||||
next_try:
|
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;
|
initial_errtext = NULL;
|
||||||
if (!err)
|
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. */
|
/* Unless the passphrase is empty, ask to confirm it. */
|
||||||
if (pi->pin && *pi->pin)
|
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)
|
if (err == -1)
|
||||||
{ /* The re-entered one did not match and the user did not
|
{ /* The re-entered one did not match and the user did not
|
||||||
hit cancel. */
|
hit cancel. */
|
||||||
@ -381,7 +379,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
rc = agent_ask_new_passphrase (ctrl,
|
rc = agent_ask_new_passphrase (ctrl,
|
||||||
_("Please enter the passphrase to%0A"
|
_("Please enter the passphrase to%0A"
|
||||||
"to protect your new key"),
|
"to protect your new key"),
|
||||||
&passphrase, NULL);
|
&passphrase);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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,
|
rc = agent_ask_new_passphrase (ctrl,
|
||||||
_("Please enter the new passphrase"),
|
_("Please enter the new passphrase"),
|
||||||
&passphrase, NULL);
|
&passphrase);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = store_key (s_skey, passphrase, 1);
|
rc = store_key (s_skey, passphrase, 1);
|
||||||
|
@ -1523,6 +1523,8 @@ create_server_socket (char *name, int is_ssh, assuan_sock_nonce_t *nonce)
|
|||||||
a hang. */
|
a hang. */
|
||||||
if (!is_ssh && !check_for_running_agent (1, 1))
|
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 - "
|
log_error (_("a gpg-agent is already running - "
|
||||||
"not starting a new one\n"));
|
"not starting a new one\n"));
|
||||||
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
||||||
|
@ -67,8 +67,6 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
rc = agent_key_from_file (ctrl, NULL, desc_text,
|
rc = agent_key_from_file (ctrl, NULL, desc_text,
|
||||||
ctrl->keygrip, &shadow_info,
|
ctrl->keygrip, &shadow_info,
|
||||||
CACHE_MODE_NORMAL, NULL, &s_skey, NULL);
|
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 (rc)
|
||||||
{
|
{
|
||||||
if (gpg_err_code (rc) == GPG_ERR_ENOENT)
|
if (gpg_err_code (rc) == GPG_ERR_ENOENT)
|
||||||
|
@ -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,
|
rc = agent_key_from_file (ctrl, cache_nonce, desc_text, ctrl->keygrip,
|
||||||
&shadow_info, cache_mode, lookup_ttl,
|
&shadow_info, cache_mode, lookup_ttl,
|
||||||
&s_skey, 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 (rc)
|
||||||
{
|
{
|
||||||
log_error ("failed to read the secret key\n");
|
log_error ("failed to read the secret key\n");
|
||||||
|
@ -704,7 +704,8 @@ get_passphrase (int promptno)
|
|||||||
repeat, repeat, 1, &pw);
|
repeat, repeat, 1, &pw);
|
||||||
if (err)
|
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"));
|
log_info (_("cancelled\n"));
|
||||||
else
|
else
|
||||||
log_error (_("error while asking for the passphrase: %s\n"),
|
log_error (_("error while asking for the passphrase: %s\n"),
|
||||||
|
@ -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>
|
2010-10-04 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gettime.c (asctimestamp) [W32CE]: Do not print the timezone.
|
* gettime.c (asctimestamp) [W32CE]: Do not print the timezone.
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -267,6 +267,8 @@ int is_file_compressed (const char *s, int *ret_rc);
|
|||||||
|
|
||||||
int match_multistr (const char *multistr,const char *match);
|
int match_multistr (const char *multistr,const char *match);
|
||||||
|
|
||||||
|
int gnupg_compare_version (const char *a, const char *b);
|
||||||
|
|
||||||
|
|
||||||
/*-- Simple replacement functions. */
|
/*-- Simple replacement functions. */
|
||||||
#ifndef HAVE_TTYNAME
|
#ifndef HAVE_TTYNAME
|
||||||
|
18
doc/gpg.texi
18
doc/gpg.texi
@ -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
|
Use @var{name} as the key to sign with. Note that this option overrides
|
||||||
@option{--default-key}.
|
@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
|
@item --try-all-secrets
|
||||||
@opindex try-all-secrets
|
@opindex try-all-secrets
|
||||||
Don't look at the key ID as stored in the message but try all secret
|
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
|
keys in turn to find the right decryption key. This option forces the
|
||||||
behaviour as used by anonymous recipients (created by using
|
behaviour as used by anonymous recipients (created by using
|
||||||
@option{--throw-keyids}) and might come handy in case where an encrypted
|
@option{--throw-keyids} or @option{--hidden-recipient}) and might come
|
||||||
message contains a bogus key ID.
|
handy in case where an encrypted message contains a bogus key ID.
|
||||||
|
|
||||||
@item --skip-hidden-recipients
|
@item --skip-hidden-recipients
|
||||||
@itemx --no-skip-hidden-recipients
|
@itemx --no-skip-hidden-recipients
|
||||||
|
@ -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>
|
2010-10-08 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* gpg.c: Add option --with-keygrip.
|
* gpg.c: Add option --with-keygrip.
|
||||||
|
@ -99,6 +99,7 @@ status_sc_op_failure (int rc)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case GPG_ERR_CANCELED:
|
case GPG_ERR_CANCELED:
|
||||||
|
case GPG_ERR_FULLY_CANCELED:
|
||||||
write_status_text (STATUS_SC_OP_FAILURE, "1");
|
write_status_text (STATUS_SC_OP_FAILURE, "1");
|
||||||
break;
|
break;
|
||||||
case GPG_ERR_BAD_PIN:
|
case GPG_ERR_BAD_PIN:
|
||||||
@ -142,6 +143,11 @@ start_agent (ctrl_t ctrl, int for_card)
|
|||||||
agents. */
|
agents. */
|
||||||
assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
|
assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ write_sc_op_status (gpg_error_t err)
|
|||||||
break;
|
break;
|
||||||
#if GNUPG_MAJOR_VERSION != 1
|
#if GNUPG_MAJOR_VERSION != 1
|
||||||
case GPG_ERR_CANCELED:
|
case GPG_ERR_CANCELED:
|
||||||
|
case GPG_ERR_FULLY_CANCELED:
|
||||||
write_status_text (STATUS_SC_OP_FAILURE, "1");
|
write_status_text (STATUS_SC_OP_FAILURE, "1");
|
||||||
break;
|
break;
|
||||||
case GPG_ERR_BAD_PIN:
|
case GPG_ERR_BAD_PIN:
|
||||||
|
156
g10/getkey.c
156
g10/getkey.c
@ -568,8 +568,9 @@ leave:
|
|||||||
* first pubkey certificate which has the given name in a user_id. If
|
* 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
|
* 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.
|
* 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
|
* The caller should provide storage for the PK or pass NULL if it is
|
||||||
* NULL the function will return the keyblock there. */
|
* not needed. If RET_KB is not NULL the function stores the entire
|
||||||
|
* keyblock at that address. */
|
||||||
static int
|
static int
|
||||||
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
|
key_byname (GETKEY_CTX *retctx, strlist_t namelist,
|
||||||
PKT_public_key *pk,
|
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
|
/* Get a key by name and store it into PK if that is not NULL. If
|
||||||
* return the search context which needs to be released by the caller
|
* RETCTX is not NULL return the search context which needs to be
|
||||||
* using getkey_end. If NAME is NULL use the default key (see below).
|
* released by the caller using getkey_end. If NAME is NULL use the
|
||||||
* On success and if RET_KEYBLOCK is not NULL the found keyblock is
|
* default key (see below). On success and if RET_KEYBLOCK is not
|
||||||
* stored at this address. WANT_SECRET passed as true requires that a
|
* NULL the found keyblock is stored at this address. WANT_SECRET
|
||||||
* secret key is available for the selected key.
|
* 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
|
* 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
|
* 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;
|
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. */
|
goto skip; /* No secret key available. */
|
||||||
|
|
||||||
/* Warning: node flag bits 0 and 1 should be preserved by
|
/* Warning: node flag bits 0 and 1 should be preserved by
|
||||||
@ -2504,57 +2506,42 @@ found:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
/*
|
||||||
* FIXME: Replace by the generic function
|
* Enumerate certain secret keys. Caller must use these procedure:
|
||||||
* 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:
|
|
||||||
* 1) create a void pointer and initialize it to NULL
|
* 1) create a void pointer and initialize it to NULL
|
||||||
* 2) pass this void pointer by reference to this function
|
* 2) pass this void pointer by reference to this function
|
||||||
* and provide space for the secret key (pass a buffer for sk)
|
* and provide space for the secret key (pass a buffer for sk)
|
||||||
* 3) call this function as long as it does not return -1
|
* 3) call this function as long as it does not return an error.
|
||||||
* to indicate EOF.
|
* 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,
|
* 4) Always call this function a last time with SK set to NULL,
|
||||||
* so that can free it's context.
|
* so that can free it's context.
|
||||||
*/
|
*/
|
||||||
int
|
gpg_error_t
|
||||||
enum_secret_keys (void **context, PKT_public_key * sk,
|
enum_secret_keys (void **context, PKT_public_key *sk)
|
||||||
int with_subkeys, int with_spm)
|
|
||||||
{
|
{
|
||||||
log_debug ("FIXME: Anonymous recipient does not yet work\n");
|
gpg_error_t err = 0;
|
||||||
return -1;
|
const char *name;
|
||||||
#if 0
|
|
||||||
|
|
||||||
int rc = 0;
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int eof;
|
int eof;
|
||||||
int first;
|
int state;
|
||||||
KEYDB_HANDLE hd;
|
strlist_t sl;
|
||||||
KBNODE keyblock;
|
kbnode_t keyblock;
|
||||||
KBNODE node;
|
kbnode_t node;
|
||||||
} *c = *context;
|
} *c = *context;
|
||||||
|
|
||||||
|
|
||||||
if (!c)
|
if (!c)
|
||||||
{
|
{
|
||||||
/* Make a new context. */
|
/* Make a new context. */
|
||||||
c = xmalloc_clear (sizeof *c);
|
c = xtrycalloc (1, sizeof *c);
|
||||||
|
if (!c)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
*context = c;
|
*context = c;
|
||||||
c->hd = keydb_new (1); /*FIXME*/
|
|
||||||
c->first = 1;
|
|
||||||
c->keyblock = NULL;
|
|
||||||
c->node = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sk)
|
if (!sk)
|
||||||
{
|
{
|
||||||
/* Free the context. */
|
/* Free the context. */
|
||||||
keydb_release (c->hd);
|
|
||||||
release_kbnode (c->keyblock);
|
release_kbnode (c->keyblock);
|
||||||
xfree (c);
|
xfree (c);
|
||||||
*context = NULL;
|
*context = NULL;
|
||||||
@ -2562,48 +2549,79 @@ enum_secret_keys (void **context, PKT_public_key * sk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (c->eof)
|
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)
|
for (; c->node; c->node = c->node->next)
|
||||||
{
|
{
|
||||||
if ((c->node->pkt->pkttype == PKT_SECRET_KEY
|
if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||||
|| (with_subkeys
|
|| c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||||
&& c->node->pkt->pkttype == PKT_SECRET_SUBKEY))
|
|
||||||
&& !(c->node->pkt->pkt.secret_key->protect.s2k.mode == 1001
|
|
||||||
&& !with_spm))
|
|
||||||
{
|
{
|
||||||
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;
|
c->node = c->node->next;
|
||||||
return 0; /* Found. */
|
return 0; /* Found. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dispose the keyblock and continue. */
|
||||||
release_kbnode (c->keyblock);
|
release_kbnode (c->keyblock);
|
||||||
c->keyblock = c->node = NULL;
|
c->keyblock = 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;
|
|
||||||
}
|
}
|
||||||
while (!rc);
|
|
||||||
|
|
||||||
return rc; /* Error. */
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
*********** User ID printing helpers *******
|
*********** User ID printing helpers *******
|
||||||
*********************************************/
|
*********************************************/
|
||||||
|
10
g10/gpg.c
10
g10/gpg.c
@ -177,6 +177,7 @@ enum cmd_and_opt_values
|
|||||||
oDefRecipient,
|
oDefRecipient,
|
||||||
oDefRecipientSelf,
|
oDefRecipientSelf,
|
||||||
oNoDefRecipient,
|
oNoDefRecipient,
|
||||||
|
oTrySecretKey,
|
||||||
oOptions,
|
oOptions,
|
||||||
oDebug,
|
oDebug,
|
||||||
oDebugLevel,
|
oDebugLevel,
|
||||||
@ -460,6 +461,8 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_s (oLocalUser, "local-user",
|
ARGPARSE_s_s (oLocalUser, "local-user",
|
||||||
N_("|USER-ID|use USER-ID to sign or decrypt")),
|
N_("|USER-ID|use USER-ID to sign or decrypt")),
|
||||||
|
|
||||||
|
ARGPARSE_s_s (oTrySecretKey, "try-secret-key", "@"),
|
||||||
|
|
||||||
ARGPARSE_s_i (oCompress, NULL,
|
ARGPARSE_s_i (oCompress, NULL,
|
||||||
N_("|N|set compress level to N (0 disables)")),
|
N_("|N|set compress level to N (0 disables)")),
|
||||||
ARGPARSE_s_i (oCompressLevel, "compress-level", "@"),
|
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 ("reader-port:%lu:\n", GC_OPT_FLAG_NONE);
|
||||||
es_printf ("default-key:%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 ("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 ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
|
||||||
es_printf ("log-file:%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);
|
es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
|
||||||
@ -2526,6 +2530,12 @@ main (int argc, char **argv)
|
|||||||
sl->flags = 2;
|
sl->flags = 2;
|
||||||
any_explicit_recipient = 1;
|
any_explicit_recipient = 1;
|
||||||
break;
|
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 oTextmodeShort: opt.textmode = 2; break;
|
||||||
case oTextmode: opt.textmode=1; break;
|
case oTextmode: opt.textmode=1; break;
|
||||||
case oNoTextmode: opt.textmode=0; break;
|
case oNoTextmode: opt.textmode=0; break;
|
||||||
|
18
g10/gpgv.c
18
g10/gpgv.c
@ -546,3 +546,21 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
|
|||||||
(void)pk;
|
(void)pk;
|
||||||
return gpg_error (GPG_ERR_NO_SECKEY);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
16
g10/import.c
16
g10/import.c
@ -362,7 +362,7 @@ import_print_stats (void *hd)
|
|||||||
* Read the next keyblock from stream A.
|
* Read the next keyblock from stream A.
|
||||||
* PENDING_PKT should be initialzed to NULL
|
* PENDING_PKT should be initialzed to NULL
|
||||||
* and not chnaged form the caller.
|
* 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
|
static int
|
||||||
read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root )
|
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->count++;
|
||||||
stats->secret_read++;
|
stats->secret_read++;
|
||||||
|
|
||||||
/* For now we ignore the stub keys becuase we don't have real
|
/* We ignore stub keys. The way we handle them in other parts
|
||||||
support for them in gpg-agent. */
|
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)
|
if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002)
|
||||||
continue;
|
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);
|
write_status (STATUS_RSA_OR_IDEA);
|
||||||
idea_cipher_warn (0);
|
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. */
|
break; /* Don't try the other subkeys. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,11 +241,8 @@ gpg_error_t getkey_next (getkey_ctx_t ctx, PKT_public_key *pk,
|
|||||||
kbnode_t *ret_keyblock);
|
kbnode_t *ret_keyblock);
|
||||||
void getkey_end (getkey_ctx_t ctx);
|
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 );
|
void merge_keys_and_selfsig( KBNODE keyblock );
|
||||||
char*get_user_id_string( u32 *keyid );
|
char*get_user_id_string( u32 *keyid );
|
||||||
char*get_user_id_string_native( u32 *keyid );
|
char*get_user_id_string_native( u32 *keyid );
|
||||||
|
@ -1638,7 +1638,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
/* See whether we have a matching secret key. */
|
/* See whether we have a matching secret key. */
|
||||||
if (seckey_check)
|
if (seckey_check)
|
||||||
{
|
{
|
||||||
have_seckey = have_any_secret_key (ctrl, keyblock);
|
have_seckey = !agent_probe_any_secret_key (ctrl, keyblock);
|
||||||
if (have_seckey && !quiet)
|
if (have_seckey && !quiet)
|
||||||
tty_printf (_("Secret key is available.\n"));
|
tty_printf (_("Secret key is available.\n"));
|
||||||
}
|
}
|
||||||
|
45
g10/keygen.c
45
g10/keygen.c
@ -3441,6 +3441,8 @@ generate_subkeypair (KBNODE keyblock)
|
|||||||
u32 expire;
|
u32 expire;
|
||||||
unsigned int nbits;
|
unsigned int nbits;
|
||||||
u32 cur_time;
|
u32 cur_time;
|
||||||
|
char *hexgrip = NULL;
|
||||||
|
char *serialno = NULL;
|
||||||
|
|
||||||
/* Break out the primary key. */
|
/* Break out the primary key. */
|
||||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
||||||
@ -3476,37 +3478,16 @@ generate_subkeypair (KBNODE keyblock)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning ask gpg-agent on the availibility of the secret key
|
err = hexkeygrip_from_pk (pri_psk, &hexgrip);
|
||||||
/* if (pri_sk->is_protected && pri_sk->protect.s2k.mode == 1001) */
|
if (err)
|
||||||
/* { */
|
goto leave;
|
||||||
/* tty_printf (_("Secret parts of primary key are not available.\n")); */
|
if (agent_get_keyinfo (NULL, hexgrip, &serialno))
|
||||||
/* err = G10ERR_NO_SECKEY; */
|
{
|
||||||
/* goto leave; */
|
tty_printf (_("Secret parts of primary key are not available.\n"));
|
||||||
/* } */
|
goto leave;
|
||||||
|
}
|
||||||
|
if (serialno)
|
||||||
/* /\* Unprotect to get the passphrase. *\/ */
|
tty_printf (_("Secret parts of primary key are stored on-card.\n"));
|
||||||
/* 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; */
|
|
||||||
|
|
||||||
algo = ask_algo (1, NULL, &use);
|
algo = ask_algo (1, NULL, &use);
|
||||||
assert (algo);
|
assert (algo);
|
||||||
@ -3536,6 +3517,8 @@ generate_subkeypair (KBNODE keyblock)
|
|||||||
write_status_text (STATUS_KEY_CREATED, "S");
|
write_status_text (STATUS_KEY_CREATED, "S");
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
xfree (hexgrip);
|
||||||
|
xfree (serialno);
|
||||||
if (err)
|
if (err)
|
||||||
log_error (_("Key generation failed: %s\n"), g10_errstr (err) );
|
log_error (_("Key generation failed: %s\n"), g10_errstr (err) );
|
||||||
return err;
|
return err;
|
||||||
|
213
g10/keylist.c
213
g10/keylist.c
@ -40,11 +40,12 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
|
#include "call-agent.h"
|
||||||
|
|
||||||
static void list_all (int);
|
static void list_all (int);
|
||||||
static void list_one (strlist_t names, int secret);
|
static void list_one (strlist_t names, int secret);
|
||||||
static void locate_one (ctrl_t ctrl, strlist_t names);
|
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
|
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
|
/* Print basic information of a secret key including the card serial
|
||||||
number information. */
|
number information. */
|
||||||
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
void
|
void
|
||||||
print_card_key_info (estream_t fp, kbnode_t keyblock)
|
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. */
|
/* Flags = 0x01 hashed 0x02 critical. */
|
||||||
@ -444,7 +446,7 @@ list_all (int secret)
|
|||||||
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
|
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
|
||||||
goto leave;
|
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. */
|
; /* Secret key listing requested but this isn't one. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -757,13 +759,15 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
|
|||||||
static void
|
static void
|
||||||
list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc;
|
||||||
KBNODE kbctx;
|
KBNODE kbctx;
|
||||||
KBNODE node;
|
KBNODE node;
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
struct sig_stats *stats = opaque;
|
struct sig_stats *stats = opaque;
|
||||||
int skip_sigs = 0;
|
int skip_sigs = 0;
|
||||||
int s2k_char;
|
int s2k_char;
|
||||||
|
char *hexgrip = NULL;
|
||||||
|
char *serialno = NULL;
|
||||||
|
|
||||||
/* Get the keyid from the keyblock. */
|
/* Get the keyid from the keyblock. */
|
||||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
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;
|
pk = node->pkt->pkt.public_key;
|
||||||
|
|
||||||
/* Fixme: Get s2k mode from the agent. */
|
if (secret || opt.with_keygrip)
|
||||||
s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
|
{
|
||||||
(sk->protect.s2k.mode == 1002)? '>' : */' ');
|
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 ();
|
check_trustdb_stale ();
|
||||||
|
|
||||||
@ -822,19 +839,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
|||||||
if (fpr)
|
if (fpr)
|
||||||
print_fingerprint (pk, 0);
|
print_fingerprint (pk, 0);
|
||||||
|
|
||||||
if (opt.with_keygrip)
|
if (opt.with_keygrip && hexgrip)
|
||||||
{
|
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!hexkeygrip_from_pk (pk, &p))
|
if (serialno)
|
||||||
{
|
print_card_serialno (serialno);
|
||||||
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 (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
print_key_data (pk);
|
print_key_data (pk);
|
||||||
@ -895,10 +904,25 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
|||||||
else
|
else
|
||||||
skip_sigs = 0;
|
skip_sigs = 0;
|
||||||
|
|
||||||
/* Fixme: Get s2k mode from the agent. */
|
xfree (serialno); serialno = NULL;
|
||||||
s2k_char = (/*(sk->protect.s2k.mode == 1001)? '#' :
|
xfree (hexgrip); hexgrip = NULL;
|
||||||
(sk->protect.s2k.mode == 1002)? '>' : */' ');
|
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",
|
es_fprintf (es_stdout, "%s%c %4u%c/%s %s",
|
||||||
secret? "ssb":"sub",
|
secret? "ssb":"sub",
|
||||||
s2k_char,
|
s2k_char,
|
||||||
@ -926,20 +950,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
|||||||
if (fpr > 1)
|
if (fpr > 1)
|
||||||
{
|
{
|
||||||
print_fingerprint (pk2, 0);
|
print_fingerprint (pk2, 0);
|
||||||
/* FIXME: (see above) */
|
if (serialno)
|
||||||
/* if (secret) */
|
print_card_serialno (serialno);
|
||||||
/* 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 (opt.with_keygrip && hexgrip)
|
||||||
|
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
|
||||||
if (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
print_key_data (pk2);
|
print_key_data (pk2);
|
||||||
}
|
}
|
||||||
@ -1050,6 +1065,8 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
es_putc ('\n', es_stdout);
|
es_putc ('\n', es_stdout);
|
||||||
|
xfree (serialno);
|
||||||
|
xfree (hexgrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1079,7 +1096,7 @@ print_revokers (PKT_public_key * pk)
|
|||||||
static void
|
static void
|
||||||
list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc;
|
||||||
KBNODE kbctx;
|
KBNODE kbctx;
|
||||||
KBNODE node;
|
KBNODE node;
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
@ -1088,6 +1105,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
int ulti_hack = 0;
|
int ulti_hack = 0;
|
||||||
int i;
|
int i;
|
||||||
char *p;
|
char *p;
|
||||||
|
char *hexgrip = NULL;
|
||||||
|
char *serialno = NULL;
|
||||||
|
int stubkey;
|
||||||
|
|
||||||
/* Get the keyid from the keyblock. */
|
/* Get the keyid from the keyblock. */
|
||||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
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;
|
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);
|
keyid_from_pk (pk, keyid);
|
||||||
es_fputs (secret? "sec:":"pub:", es_stdout);
|
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 13. */
|
||||||
es_putc (':', es_stdout); /* End of field 14. */
|
es_putc (':', es_stdout); /* End of field 14. */
|
||||||
if (/*FIXME sk->protect.s2k.mode*/1 == 1001)
|
if (stubkey)
|
||||||
es_putc ('#', es_stdout); /* Key is just a stub. */
|
es_putc ('#', es_stdout);
|
||||||
else if (/*FIXME sk->protect.s2k.mode*/1 == 1002)
|
else if (serialno)
|
||||||
{
|
es_fputs(serialno, es_stdout);
|
||||||
/* 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]); */
|
|
||||||
}
|
|
||||||
es_putc (':', es_stdout); /* End of field 15. */
|
es_putc (':', es_stdout); /* End of field 15. */
|
||||||
}
|
}
|
||||||
es_putc ('\n', es_stdout);
|
es_putc ('\n', es_stdout);
|
||||||
@ -1154,11 +1177,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
print_fingerprint (pk, 0);
|
print_fingerprint (pk, 0);
|
||||||
if (opt.with_key_data || opt.with_keygrip)
|
if (opt.with_key_data || opt.with_keygrip)
|
||||||
{
|
{
|
||||||
if (!hexkeygrip_from_pk (pk, &p))
|
if (hexgrip)
|
||||||
{
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
|
||||||
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
|
||||||
xfree (p);
|
|
||||||
}
|
|
||||||
if (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
print_key_data (pk);
|
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)
|
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||||
{
|
{
|
||||||
u32 keyid2[2];
|
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);
|
keyid_from_pk (pk2, keyid2);
|
||||||
es_fputs (secret? "ssb:":"sub:", es_stdout);
|
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 13. */
|
||||||
es_putc (':', es_stdout); /* End of field 14. */
|
es_putc (':', es_stdout); /* End of field 14. */
|
||||||
if (/*FIXME:sk2->protect.s2k.mode*/1 == 1001)
|
if (stubkey)
|
||||||
es_putc ('#', es_stdout); /* Key is just a stub. */
|
es_putc ('#', es_stdout);
|
||||||
else if (/*FIXME: sk2->protect.s2k.mode*/1 == 1002)
|
else if (serialno)
|
||||||
{
|
es_fputs (serialno, es_stdout);
|
||||||
/* 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]); */
|
|
||||||
}
|
|
||||||
es_putc (':', es_stdout); /* End of field 15. */
|
es_putc (':', es_stdout); /* End of field 15. */
|
||||||
}
|
}
|
||||||
es_putc ('\n', es_stdout);
|
es_putc ('\n', es_stdout);
|
||||||
@ -1260,11 +1288,8 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
print_fingerprint (pk2, 0);
|
print_fingerprint (pk2, 0);
|
||||||
if (opt.with_key_data || opt.with_keygrip)
|
if (opt.with_key_data || opt.with_keygrip)
|
||||||
{
|
{
|
||||||
if (!hexkeygrip_from_pk (pk2, &p))
|
if (hexgrip)
|
||||||
{
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
|
||||||
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
|
||||||
xfree (p);
|
|
||||||
}
|
|
||||||
if (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
print_key_data (pk2);
|
print_key_data (pk2);
|
||||||
}
|
}
|
||||||
@ -1385,6 +1410,9 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
/* fixme: check or list other sigs here */
|
/* 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. */
|
/* Print the serial number of an OpenPGP card if available. */
|
||||||
static void
|
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");
|
if (!serialno)
|
||||||
/* int i; */
|
return;
|
||||||
|
if (opt.with_colons)
|
||||||
|
return; /* Handled elsewhere. */
|
||||||
|
|
||||||
/* if (!sk) */
|
es_fputs (_(" Card serial no. ="), es_stdout);
|
||||||
/* return; */
|
es_putc (' ', es_stdout);
|
||||||
/* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
|
if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
|
||||||
/* return; /\* Not a card. *\/ */
|
{
|
||||||
/* if (opt.with_colons) */
|
/* This is an OpenPGP card. Print the relevant part. */
|
||||||
/* return; /\* Handled elsewhere. *\/ */
|
/* Example: D2760001240101010001000003470000 */
|
||||||
|
/* xxxxyyyyyyyy */
|
||||||
/* es_fputs (_(" Card serial no. ="), es_stdout); */
|
es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
|
||||||
/* es_putc (' ', es_stdout); */
|
}
|
||||||
/* if (sk->protect.ivlen == 16 */
|
else
|
||||||
/* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
|
es_fputs (serialno, es_stdout);
|
||||||
/* { */
|
es_putc ('\n', es_stdout);
|
||||||
/* /\* 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); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -555,11 +555,10 @@ get_signature_count (PKT_public_key *pk)
|
|||||||
/* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
|
/* if(agent_scd_getattr("SIG-COUNTER",&info)==0) */
|
||||||
/* return info.sig_counter; */
|
/* return info.sig_counter; */
|
||||||
/* } */
|
/* } */
|
||||||
#endif
|
#else
|
||||||
|
(void)pk;
|
||||||
/* How to do this without a card? */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand %-strings. Returns a string which must be xfreed. Returns
|
/* Expand %-strings. Returns a string which must be xfreed. Returns
|
||||||
|
@ -79,6 +79,8 @@ struct
|
|||||||
const char *def_secret_key;
|
const char *def_secret_key;
|
||||||
char *def_recipient;
|
char *def_recipient;
|
||||||
int def_recipient_self;
|
int def_recipient_self;
|
||||||
|
strlist_t secret_keys_to_try;
|
||||||
|
|
||||||
int def_cert_level;
|
int def_cert_level;
|
||||||
int min_cert_level;
|
int min_cert_level;
|
||||||
int ask_cert_level;
|
int ask_cert_level;
|
||||||
|
@ -211,17 +211,6 @@ get_last_passphrase()
|
|||||||
return p;
|
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
|
/* Here's an interesting question: since this passphrase was passed in
|
||||||
on the command line, is there really any point in using secure
|
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
|
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)
|
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") );
|
log_info (_("cancelled by user\n") );
|
||||||
if (canceled)
|
if (canceled)
|
||||||
|
@ -94,14 +94,13 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
|
|||||||
{
|
{
|
||||||
void *enum_context = NULL;
|
void *enum_context = NULL;
|
||||||
u32 keyid[2];
|
u32 keyid[2];
|
||||||
char *p;
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (sk)
|
if (sk)
|
||||||
free_public_key (sk);
|
free_public_key (sk);
|
||||||
sk = xmalloc_clear (sizeof *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)
|
if (rc)
|
||||||
{
|
{
|
||||||
rc = G10ERR_NO_SECKEY;
|
rc = G10ERR_NO_SECKEY;
|
||||||
@ -109,42 +108,22 @@ get_session_key (PKT_pubkey_enc * k, DEK * dek)
|
|||||||
}
|
}
|
||||||
if (sk->pubkey_algo != k->pubkey_algo)
|
if (sk->pubkey_algo != k->pubkey_algo)
|
||||||
continue;
|
continue;
|
||||||
|
if (!(sk->pubkey_usage & PUBKEY_USAGE_ENC))
|
||||||
|
continue;
|
||||||
keyid_from_pk (sk, keyid);
|
keyid_from_pk (sk, keyid);
|
||||||
log_info (_("anonymous recipient; trying secret key %s ...\n"),
|
log_info (_("anonymous recipient; trying secret key %s ...\n"),
|
||||||
keystr (keyid));
|
keystr (keyid));
|
||||||
|
|
||||||
if (!opt.try_all_secrets && !is_status_enabled ())
|
rc = get_it (k, dek, sk, keyid);
|
||||||
{
|
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
log_info (_("okay, we are the anonymous recipient.\n"));
|
log_info (_("okay, we are the anonymous recipient.\n"));
|
||||||
break;
|
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:
|
leave:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user