mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
More agent support for gpg.
This commit is contained in:
parent
5a679857ef
commit
54591341a4
33 changed files with 496 additions and 311 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(). */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue