Exporting secret keys via gpg-agent is now basically supported.

A couple of forward ported changes.
Doc updates.
This commit is contained in:
Werner Koch 2010-10-01 20:33:53 +00:00
parent aeb31977ec
commit bfbd80feb9
72 changed files with 1930 additions and 546 deletions

8
NEWS
View File

@ -30,8 +30,8 @@ Noteworthy changes in version 2.1.x (under development)
by default. by default.
* Dirmngr is now a part of this package. Dirmngr is now also * Dirmngr is now a part of this package. Dirmngr is now also
expected to run as a system service and the configuraion expected to run as a system service and the configuration
directories are changed to the gnupg name space. directories are changed to the GnuPG name space.
* Given sufficient permissions Dirmngr is started automagically. * Given sufficient permissions Dirmngr is started automagically.
@ -43,6 +43,10 @@ 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:
--export-options: export-secret-subkey-passwd
--simple-sk-checksum
Noteworthy changes in version 2.0.13 (2009-09-04) Noteworthy changes in version 2.0.13 (2009-09-04)
------------------------------------------------- -------------------------------------------------

View File

@ -23,6 +23,7 @@ Release process:
(Mainly config.guess and config.sub). (Mainly config.guess and config.sub).
* [1.4 only] Update gpg.texi and gpgv.texi from the trunk: * [1.4 only] Update gpg.texi and gpgv.texi from the trunk:
make -C doc update-source-from-gnupg-2 make -C doc update-source-from-gnupg-2
* [1.4 and 2.0] Copy needed texinfo files from trunk.
* Run "make -C po update-po". * Run "make -C po update-po".
* Write NEWS entries and set the release date in NEWS. * Write NEWS entries and set the release date in NEWS.
* In configure.ac set "my_issvn" to "no". * In configure.ac set "my_issvn" to "no".

View File

@ -1,3 +1,47 @@
2010-09-30 Werner Koch <wk@g10code.com>
* gpg-agent.c (agent_exit): Run cleanup.
(cleanup): Run only once.
* call-pinentry.c (close_button_status_cb): New.
(agent_askpin): Add arg R_CANCEL_ALL. Change all callers.
* genkey.c (agent_ask_new_passphrase): Ditto.
* findkey.c (unprotect): Return GPG_ERR_FULLY_CANCELED if needed.
* command.c (cmd_export_key): Add support for OpenPGP keys.
* findkey.c (unprotect): Add optional arg R_PASSPHRASE.
(agent_key_from_file): Ditto. Change all callers.
* findkey.c (unprotect): Do not put the passphrase into the cache
if it has been changed.
* cvt-openpgp.c (convert_to_openpgp, apply_protection)
(key_from_sexp): New.
2010-09-29 Werner Koch <wk@g10code.com>
* cvt-openpgp.c (convert_openpgp): Rename to convert_from_openpgp.
* command.c (has_option): Stop at "--".
(has_option_name, option_value): Ditto.
(skip_options): Skip initial spaces.
2010-09-24 Werner Koch <wk@g10code.com>
* gpg-agent.c (main, reread_configuration): Always test whether
the default configuration file has been created in the meantime.
Fixes bug#1285.
2010-09-17 Werner Koch <wk@g10code.com>
* command.c (cmd_havekey): Allow testing of several keygrips.
2010-09-15 Werner Koch <wk@g10code.com>
* protect.c (calculate_mic): Take care of shared secret format.
* agent.h (PROTECTED_SHARED_SECRET): New.
2010-09-02 Werner Koch <wk@g10code.com> 2010-09-02 Werner Koch <wk@g10code.com>
* cache.c (new_data): Change arg and callers to use a string and * cache.c (new_data): Change arg and callers to use a string and

View File

@ -182,7 +182,8 @@ enum
PRIVATE_KEY_UNKNOWN = 0, PRIVATE_KEY_UNKNOWN = 0,
PRIVATE_KEY_CLEAR = 1, PRIVATE_KEY_CLEAR = 1,
PRIVATE_KEY_PROTECTED = 2, PRIVATE_KEY_PROTECTED = 2,
PRIVATE_KEY_SHADOWED = 3 PRIVATE_KEY_SHADOWED = 3,
PROTECTED_SHARED_SECRET = 4
}; };
@ -233,7 +234,8 @@ gpg_error_t agent_key_from_file (ctrl_t ctrl,
unsigned char **shadow_info, unsigned char **shadow_info,
cache_mode_t cache_mode, cache_mode_t cache_mode,
lookup_ttl_t lookup_ttl, lookup_ttl_t lookup_ttl,
gcry_sexp_t *result); gcry_sexp_t *result,
char **r_passphrase);
gpg_error_t agent_public_key_from_file (ctrl_t ctrl, gpg_error_t agent_public_key_from_file (ctrl_t ctrl,
const unsigned char *grip, const unsigned char *grip,
gcry_sexp_t *result); gcry_sexp_t *result);
@ -251,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); struct pin_entry_info_s *pininfo, int *r_cancelall);
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);
@ -289,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); char **r_passphrase, int *r_cancelall);
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);

View File

@ -696,6 +696,29 @@ setup_qualitybar (void)
} }
/* Check the button_info line for a close action. */
static gpg_error_t
close_button_status_cb (void *opaque, const char *line)
{
int *flag = opaque;
const char *keyword = line;
int keywordlen;
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
;
while (spacep (line))
line++;
if (keywordlen == 11 && !memcmp (keyword, "BUTTON_INFO", keywordlen))
{
if ( !strcmp (line, "close") )
*flag = 1;
}
return 0;
}
/* Call the Entry and ask for the PIN. We do check for a valid PIN /* Call the Entry and ask for the PIN. We do check for a valid PIN
number here and repeat it as long as we have invalid formed number here and repeat it as long as we have invalid formed
@ -704,7 +727,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) struct pin_entry_info_s *pininfo, int *r_cancel_all)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
@ -712,6 +735,10 @@ agent_askpin (ctrl_t ctrl,
const char *errtext = NULL; const char *errtext = NULL;
int is_pin = 0; int is_pin = 0;
int saveflag; int saveflag;
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 */
@ -791,8 +818,10 @@ agent_askpin (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
@ -801,6 +830,11 @@ 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
cancel the operation. */
if (close_button && r_cancel_all && gpg_err_code (rc) == GPG_ERR_CANCELED)
*r_cancel_all = 1;
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")
: _("Passphrase too long"); : _("Passphrase too long");

View File

@ -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); err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL);
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); err = agent_askpin (ctrl, description2, NULL, NULL, pi2, NULL);
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. */

View File

@ -169,6 +169,23 @@ reset_notify (assuan_context_t ctx, char *line)
} }
/* Skip over options.
Blanks after the options are also removed. */
static char *
skip_options (const char *line)
{
while (spacep (line))
line++;
while ( *line == '-' && line[1] == '-' )
{
while (*line && !spacep (line))
line++;
while (spacep (line))
line++;
}
return (char*)line;
}
/* Check whether the option NAME appears in LINE */ /* Check whether the option NAME appears in LINE */
static int static int
has_option (const char *line, const char *name) has_option (const char *line, const char *name)
@ -177,6 +194,8 @@ has_option (const char *line, const char *name)
int n = strlen (name); int n = strlen (name);
s = strstr (line, name); s = strstr (line, name);
if (s && s >= skip_options (line))
return 0;
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
} }
@ -190,6 +209,8 @@ has_option_name (const char *line, const char *name)
int n = strlen (name); int n = strlen (name);
s = strstr (line, name); s = strstr (line, name);
if (s && s >= skip_options (line))
return 0;
return (s && (s == line || spacep (s-1)) return (s && (s == line || spacep (s-1))
&& (!s[n] || spacep (s+n) || s[n] == '=')); && (!s[n] || spacep (s+n) || s[n] == '='));
} }
@ -203,6 +224,8 @@ option_value (const char *line, const char *name)
int n = strlen (name); int n = strlen (name);
s = strstr (line, name); s = strstr (line, name);
if (s && s >= skip_options (line))
return NULL;
if (s && (s == line || spacep (s-1)) if (s && (s == line || spacep (s-1))
&& s[n] && (spacep (s+n) || s[n] == '=')) && s[n] && (spacep (s+n) || s[n] == '='))
{ {
@ -215,23 +238,6 @@ option_value (const char *line, const char *name)
} }
/* Skip over options. It is assumed that leading spaces have been
removed (this is the case for lines passed to a handler from
assuan). Blanks after the options are also removed. */
static char *
skip_options (char *line)
{
while ( *line == '-' && line[1] == '-' )
{
while (*line && !spacep (line))
line++;
while (spacep (line))
line++;
}
return line;
}
/* Replace all '+' by a blank. */ /* Replace all '+' by a blank. */
static void static void
plus_to_blank (char *s) plus_to_blank (char *s)
@ -530,23 +536,35 @@ cmd_marktrusted (assuan_context_t ctx, char *line)
static const char hlp_havekey[] = static const char hlp_havekey[] =
"HAVEKEY <hexstring_with_keygrip>\n" "HAVEKEY <hexstrings_with_keygrips>\n"
"\n" "\n"
"Return success when the secret key is available."; "Return success if at least one of the secret keys with the given\n"
"keygrips is available.";
static gpg_error_t static gpg_error_t
cmd_havekey (assuan_context_t ctx, char *line) cmd_havekey (assuan_context_t ctx, char *line)
{ {
int rc; gpg_error_t err;
unsigned char buf[20]; unsigned char buf[20];
rc = parse_keygrip (ctx, line, buf); do
if (rc) {
return rc; err = parse_keygrip (ctx, line, buf);
if (err)
return err;
if (!agent_key_available (buf))
return 0; /* Found. */
if (agent_key_available (buf)) while (*line && *line != ' ' && *line != '\t')
return gpg_error (GPG_ERR_NO_SECKEY); line++;
while (*line == ' ' || *line == '\t')
return 0; line++;
}
while (*line);
/* No leave_cmd() here because errors are expected and would clutter
the log. */
return gpg_error (GPG_ERR_NO_SECKEY);
} }
@ -1316,9 +1334,14 @@ cmd_passwd (assuan_context_t ctx, char *line)
ctrl->in_passwd++; ctrl->in_passwd++;
rc = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, rc = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL, grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey); &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");
@ -1590,9 +1613,9 @@ cmd_import_key (assuan_context_t ctx, char *line)
used to protect the key using the same code as for regular used to protect the key using the same code as for regular
key import. */ key import. */
err = convert_openpgp (ctrl, openpgp_sexp, grip, err = convert_from_openpgp (ctrl, openpgp_sexp, grip,
ctrl->server_local->keydesc, cache_nonce, ctrl->server_local->keydesc, cache_nonce,
&key, &passphrase); &key, &passphrase);
if (err) if (err)
goto leave; goto leave;
realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err); realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
@ -1620,7 +1643,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); &passphrase, NULL);
if (err) if (err)
goto leave; goto leave;
} }
@ -1650,7 +1673,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
static const char hlp_export_key[] = static const char hlp_export_key[] =
"EXPORT_KEY <hexstring_with_keygrip>\n" "EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp] <hexstring_with_keygrip>\n"
"\n" "\n"
"Export a secret key from the key store. The key will be encrypted\n" "Export a secret key from the key store. The key will be encrypted\n"
"using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n" "using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
@ -1668,6 +1691,26 @@ cmd_export_key (assuan_context_t ctx, char *line)
gcry_cipher_hd_t cipherhd = NULL; gcry_cipher_hd_t cipherhd = NULL;
unsigned char *wrappedkey = NULL; unsigned char *wrappedkey = NULL;
size_t wrappedkeylen; size_t wrappedkeylen;
int openpgp;
char *cache_nonce;
char *passphrase = NULL;
openpgp = has_option (line, "--openpgp");
cache_nonce = option_value (line, "--cache-nonce");
if (cache_nonce)
{
for (; *line && !spacep (line); line++)
;
if (*line)
*line++ = '\0';
cache_nonce = xtrystrdup (cache_nonce);
if (!cache_nonce)
{
err = gpg_error_from_syserror ();
goto leave;
}
}
line = skip_options (line);
if (!ctrl->server_local->export_key) if (!ctrl->server_local->export_key)
{ {
@ -1685,8 +1728,11 @@ cmd_export_key (assuan_context_t ctx, char *line)
goto leave; goto leave;
} }
/* Get the key from the file. With the openpgp flag we also ask for
the passphrase so that we can use it to re-encrypt it. */
err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip, err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
NULL, CACHE_MODE_IGNORE, NULL, &s_skey); NULL, CACHE_MODE_IGNORE, NULL, &s_skey,
openpgp ? &passphrase : NULL);
if (err) if (err)
goto leave; goto leave;
if (!s_skey) if (!s_skey)
@ -1697,8 +1743,33 @@ cmd_export_key (assuan_context_t ctx, char *line)
err = gpg_error (GPG_ERR_UNUSABLE_SECKEY); err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
goto leave; goto leave;
} }
err = make_canon_sexp_pad (s_skey, 1, &key, &keylen); if (openpgp)
{
/* The openpgp option changes the key format into the OpenPGP
key transfer format. The result is already a padded
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);
if (err)
{
if (fully_canceled)
err = gpg_error (GPG_ERR_FULLY_CANCELED);
goto leave;
}
}
err = convert_to_openpgp (ctrl, s_skey, passphrase, &key, &keylen);
}
else
{
/* Convert into a canonical S-expression and wrap that. */
err = make_canon_sexp_pad (s_skey, 1, &key, &keylen);
}
if (err) if (err)
goto leave; goto leave;
gcry_sexp_release (s_skey); gcry_sexp_release (s_skey);
@ -1735,12 +1806,18 @@ cmd_export_key (assuan_context_t ctx, char *line)
leave: leave:
xfree (passphrase);
xfree (wrappedkey); xfree (wrappedkey);
gcry_cipher_close (cipherhd); gcry_cipher_close (cipherhd);
xfree (key); xfree (key);
gcry_sexp_release (s_skey); gcry_sexp_release (s_skey);
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);
} }

View File

@ -525,10 +525,10 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
pointed to by GRIP. On error NULL is stored at all return pointed to by GRIP. On error NULL is stored at all return
arguments. */ arguments. */
gpg_error_t gpg_error_t
convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt, unsigned char *grip, const char *prompt,
const char *cache_nonce, const char *cache_nonce,
unsigned char **r_key, char **r_passphrase) unsigned char **r_key, char **r_passphrase)
{ {
gpg_error_t err; gpg_error_t err;
gcry_sexp_t top_list; gcry_sexp_t top_list;
@ -779,7 +779,7 @@ convert_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); err = agent_askpin (ctrl, prompt, NULL, NULL, pi, NULL);
skeyidx = pi_arg.skeyidx; skeyidx = pi_arg.skeyidx;
if (!err) if (!err)
{ {
@ -824,4 +824,267 @@ convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
} }
static gpg_error_t
key_from_sexp (gcry_sexp_t sexp, const char *elems, gcry_mpi_t *array)
{
gpg_error_t err = 0;
gcry_sexp_t l2;
int idx;
for (idx=0; *elems; elems++, idx++)
{
l2 = gcry_sexp_find_token (sexp, elems, 1);
if (!l2)
{
err = gpg_error (GPG_ERR_NO_OBJ); /* Required parameter not found. */
goto leave;
}
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
if (!array[idx])
{
err = gpg_error (GPG_ERR_INV_OBJ); /* Required parameter invalid. */
goto leave;
}
}
leave:
if (err)
{
int i;
for (i=0; i < idx; i++)
{
gcry_mpi_release (array[i]);
array[i] = NULL;
}
}
return err;
}
/* Given an ARRAY of mpis with the key parameters, protect the secret
parameters in that array and replace them by one opaque encoded
mpi. NPKEY is the number of public key parameters and NSKEY is
the number of secret key parameters (including the public ones).
On success the array will have NPKEY+1 elements. */
static gpg_error_t
apply_protection (gcry_mpi_t *array, int npkey, int nskey,
const char *passphrase,
int protect_algo, void *protect_iv, size_t protect_ivlen,
int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count)
{
gpg_error_t err;
int i, j;
gcry_cipher_hd_t cipherhd;
unsigned char *bufarr[10];
size_t narr[10];
unsigned int nbits[10];
int ndata;
unsigned char *p, *data;
assert (npkey < nskey);
assert (nskey < DIM (bufarr));
/* Collect only the secret key parameters into BUFARR et al and
compute the required size of the data buffer. */
ndata = 20; /* Space for the SHA-1 checksum. */
for (i = npkey, j = 0; i < nskey; i++, j++ )
{
err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]);
if (err)
{
err = gpg_error_from_syserror ();
for (i = 0; i < j; i++)
xfree (bufarr[i]);
return err;
}
nbits[j] = gcry_mpi_get_nbits (array[i]);
ndata += 2 + narr[j];
}
/* Allocate data buffer and stuff it with the secret key parameters. */
data = xtrymalloc_secure (ndata);
if (!data)
{
err = gpg_error_from_syserror ();
for (i = 0; i < (nskey-npkey); i++ )
xfree (bufarr[i]);
return err;
}
p = data;
for (i = 0; i < (nskey-npkey); i++ )
{
*p++ = nbits[i] >> 8 ;
*p++ = nbits[i];
memcpy (p, bufarr[i], narr[i]);
p += narr[i];
xfree (bufarr[i]);
bufarr[i] = NULL;
}
assert (p == data + ndata - 20);
/* Append a hash of the secret key parameters. */
gcry_md_hash_buffer (GCRY_MD_SHA1, p, data, ndata - 20);
/* Encrypt it. */
err = gcry_cipher_open (&cipherhd, protect_algo,
GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
if (!err)
err = hash_passphrase_and_set_key (passphrase, cipherhd, protect_algo,
s2k_mode, s2k_algo, s2k_salt, s2k_count);
if (!err)
err = gcry_cipher_setiv (cipherhd, protect_iv, protect_ivlen);
if (!err)
err = gcry_cipher_encrypt (cipherhd, data, ndata, NULL, 0);
gcry_cipher_close (cipherhd);
if (err)
{
xfree (data);
return err;
}
/* Replace the secret key parameters in the array by one opaque value. */
for (i = npkey; i < nskey; i++ )
{
gcry_mpi_release (array[i]);
array[i] = NULL;
}
array[npkey] = gcry_mpi_set_opaque (NULL, data, ndata*8);
return 0;
}
/* Convert our key S_KEY into an OpenPGP key transfer format. On
success a canonical encoded S-expression is stored at R_TRANSFERKEY
and its length at R_TRANSFERKEYLEN; this S-expression is also
padded to a multiple of 64 bits. */
gpg_error_t
convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
unsigned char **r_transferkey, size_t *r_transferkeylen)
{
gpg_error_t err;
gcry_sexp_t list, l2;
char *name;
int algo;
const char *algoname;
const char *elems;
int npkey, nskey;
gcry_mpi_t array[10];
char protect_iv[16];
char salt[8];
unsigned long s2k_count;
int i, j;
(void)ctrl;
*r_transferkey = NULL;
for (i=0; i < DIM (array); i++)
array[i] = NULL;
list = gcry_sexp_find_token (s_key, "private-key", 0);
if (!list)
return gpg_error (GPG_ERR_NO_OBJ); /* Does not contain a key object. */
l2 = gcry_sexp_cadr (list);
gcry_sexp_release (list);
list = l2;
name = gcry_sexp_nth_string (list, 0);
if (!name)
{
gcry_sexp_release (list);
return gpg_error (GPG_ERR_INV_OBJ); /* Invalid structure of object. */
}
algo = gcry_pk_map_name (name);
xfree (name);
switch (algo)
{
case GCRY_PK_RSA: algoname = "rsa"; npkey = 2; elems = "nedpqu"; break;
case GCRY_PK_ELG: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_ELG_E: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_DSA: algoname = "dsa"; npkey = 4; elems = "pqgyx"; break;
case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break;
default: algoname = ""; npkey = 0; elems = NULL; break;
}
assert (!elems || strlen (elems) < DIM (array) );
nskey = elems? strlen (elems) : 0;
if (!elems)
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
else
err = key_from_sexp (list, elems, array);
gcry_sexp_release (list);
if (err)
return err;
gcry_create_nonce (protect_iv, sizeof protect_iv);
gcry_create_nonce (salt, sizeof salt);
s2k_count = get_standard_s2k_count ();
err = apply_protection (array, npkey, nskey, passphrase,
GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
3, GCRY_MD_SHA1, salt, s2k_count);
/* Turn it into the transfer key S-expression. Note that we always
return a protected key. */
if (!err)
{
char countbuf[35];
membuf_t mbuf;
void *format_args_buf_ptr[1];
int format_args_buf_int[1];
void *format_args[10+2];
size_t n;
gcry_sexp_t tmpkey, tmpsexp;
snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
init_membuf (&mbuf, 50);
put_membuf_str (&mbuf, "(skey");
for (i=j=0; i < npkey; i++)
{
put_membuf_str (&mbuf, " _ %m");
format_args[j++] = array + i;
}
put_membuf_str (&mbuf, " e %b");
format_args_buf_ptr[0] = gcry_mpi_get_opaque (array[npkey], &n);
format_args_buf_int[0] = (n+7)/8;
format_args[j++] = format_args_buf_int;
format_args[j++] = format_args_buf_ptr;
put_membuf_str (&mbuf, ")\n");
put_membuf (&mbuf, "", 1);
tmpkey = NULL;
{
char *format = get_membuf (&mbuf, NULL);
if (!format)
err = gpg_error_from_syserror ();
else
err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args);
xfree (format);
}
if (!err)
err = gcry_sexp_build (&tmpsexp, NULL,
"(openpgp-private-key\n"
" (version 1:4)\n"
" (algo %s)\n"
" %S\n"
" (protection sha1 aes %b 1:3 sha1 %b %s))\n",
algoname,
tmpkey,
(int)sizeof protect_iv, protect_iv,
(int)sizeof salt, salt,
countbuf);
gcry_sexp_release (tmpkey);
if (!err)
err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen);
gcry_sexp_release (tmpsexp);
}
for (i=0; i < DIM (array); i++)
gcry_mpi_release (array[i]);
return err;
}

View File

@ -19,10 +19,14 @@
#ifndef GNUPG_AGENT_CVT_OPENPGP_H #ifndef GNUPG_AGENT_CVT_OPENPGP_H
#define GNUPG_AGENT_CVT_OPENPGP_H #define GNUPG_AGENT_CVT_OPENPGP_H
gpg_error_t convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, gpg_error_t convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt, unsigned char *grip, const char *prompt,
const char *cache_nonce, const char *cache_nonce,
unsigned char **r_key, char **r_passphrase); unsigned char **r_key, char **r_passphrase);
gpg_error_t convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key,
const char *passphrase,
unsigned char **r_transferkey,
size_t *r_transferkeylen);
#endif /*GNUPG_AGENT_CVT_OPENPGP_H*/ #endif /*GNUPG_AGENT_CVT_OPENPGP_H*/

View File

@ -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); rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL);
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); prompt, NULL, pi2, NULL);
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); rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL);
xfree (desc); xfree (desc);
} }

View File

@ -104,7 +104,7 @@ agent_write_private_key (const unsigned char *grip,
} }
/* Callback function to try the unprotection from the passpharse query /* Callback function to try the unprotection from the passphrase query
code. */ code. */
static int static int
try_unprotect_cb (struct pin_entry_info_s *pi) try_unprotect_cb (struct pin_entry_info_s *pi)
@ -273,11 +273,16 @@ modify_description (const char *in, const char *comment, char **result)
should be the hex encoded keygrip of that key to be used with the should be the hex encoded keygrip of that key to be used with the
caching mechanism. DESC_TEXT may be set to override the default caching mechanism. DESC_TEXT may be set to override the default
description used for the pinentry. If LOOKUP_TTL is given this description used for the pinentry. If LOOKUP_TTL is given this
function is used to lookup the default ttl. */ function is used to lookup the default ttl. If R_PASSPHRASE is not
NULL, the function succeeded and the key was protected the used
passphrase (entered or from the cache) is stored there; if not NULL
will be stored. The caller needs to free the returned
passphrase. */
static int static int
unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text, unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
unsigned char **keybuf, const unsigned char *grip, unsigned char **keybuf, const unsigned char *grip,
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl) cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
char **r_passphrase)
{ {
struct pin_entry_info_s *pi; struct pin_entry_info_s *pi;
struct try_unprotect_arg_s arg; struct try_unprotect_arg_s arg;
@ -285,6 +290,10 @@ 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)
*r_passphrase = NULL;
bin2hex (grip, 20, hexgrip); bin2hex (grip, 20, hexgrip);
@ -297,13 +306,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
if (pw) if (pw)
{ {
rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen); rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
xfree (pw);
if (!rc) if (!rc)
{ {
if (r_passphrase)
*r_passphrase = pw;
else
xfree (pw);
xfree (*keybuf); xfree (*keybuf);
*keybuf = result; *keybuf = result;
return 0; return 0;
} }
xfree (pw);
} }
} }
@ -318,13 +331,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
if (pw) if (pw)
{ {
rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen); rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
xfree (pw);
if (!rc) if (!rc)
{ {
if (r_passphrase)
*r_passphrase = pw;
else
xfree (pw);
xfree (*keybuf); xfree (*keybuf);
*keybuf = result; *keybuf = result;
return 0; return 0;
} }
xfree (pw);
rc = 0; rc = 0;
} }
@ -366,7 +383,9 @@ 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); 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);
if (!rc) if (!rc)
{ {
assert (arg.unprotected_key); assert (arg.unprotected_key);
@ -400,8 +419,13 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
return rc; return rc;
} }
} }
agent_put_cache (hexgrip, cache_mode, pi->pin, else
lookup_ttl? lookup_ttl (hexgrip) : 0); {
agent_put_cache (hexgrip, cache_mode, pi->pin,
lookup_ttl? lookup_ttl (hexgrip) : 0);
if (r_passphrase && *pi->pin)
*r_passphrase = xtrystrdup (pi->pin);
}
xfree (*keybuf); xfree (*keybuf);
*keybuf = arg.unprotected_key; *keybuf = arg.unprotected_key;
} }
@ -501,13 +525,17 @@ read_key_file (const unsigned char *grip, gcry_sexp_t *result)
not simply pass the TTL value because the value is only needed if not simply pass the TTL value because the value is only needed if
an unprotect action was needed and looking up the TTL may have some an unprotect action was needed and looking up the TTL may have some
overhead (e.g. scanning the sshcontrol file). If a CACHE_NONCE is overhead (e.g. scanning the sshcontrol file). If a CACHE_NONCE is
given that cache item is first tried to get a passphrase. */ given that cache item is first tried to get a passphrase. If
R_PASSPHRASE is not NULL, the function succeeded and the key was
protected the used passphrase (entered or from the cache) is stored
there; if not NULL will be stored. The caller needs to free the
returned passphrase. */
gpg_error_t gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *cache_nonce, agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
const char *desc_text, const char *desc_text,
const unsigned char *grip, unsigned char **shadow_info, const unsigned char *grip, unsigned char **shadow_info,
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl, cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
gcry_sexp_t *result) gcry_sexp_t *result, char **r_passphrase)
{ {
int rc; int rc;
unsigned char *buf; unsigned char *buf;
@ -518,6 +546,8 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
*result = NULL; *result = NULL;
if (shadow_info) if (shadow_info)
*shadow_info = NULL; *shadow_info = NULL;
if (r_passphrase)
*r_passphrase = NULL;
rc = read_key_file (grip, &s_skey); rc = read_key_file (grip, &s_skey);
if (rc) if (rc)
@ -579,7 +609,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (!rc) if (!rc)
{ {
rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip, rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
cache_mode, lookup_ttl); cache_mode, lookup_ttl, r_passphrase);
if (rc) if (rc)
log_error ("failed to unprotect the secret key: %s\n", log_error ("failed to unprotect the secret key: %s\n",
gpg_strerror (rc)); gpg_strerror (rc));
@ -626,6 +656,11 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (rc || got_shadow_info) if (rc || got_shadow_info)
{ {
xfree (buf); xfree (buf);
if (r_passphrase)
{
xfree (*r_passphrase);
*r_passphrase = NULL;
}
return rc; return rc;
} }
@ -637,6 +672,11 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
{ {
log_error ("failed to build S-Exp (off=%u): %s\n", log_error ("failed to build S-Exp (off=%u): %s\n",
(unsigned int)erroff, gpg_strerror (rc)); (unsigned int)erroff, gpg_strerror (rc));
if (r_passphrase)
{
xfree (*r_passphrase);
*r_passphrase = NULL;
}
return rc; return rc;
} }

View File

@ -290,10 +290,12 @@ 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. */ 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. */
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) char **r_passphrase, int *r_cancel_all)
{ {
gpg_error_t err; gpg_error_t err;
const char *text1 = prompt; const char *text1 = prompt;
@ -314,7 +316,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); err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi, r_cancel_all);
initial_errtext = NULL; initial_errtext = NULL;
if (!err) if (!err)
{ {
@ -327,7 +329,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); err = agent_askpin (ctrl, text2, NULL, NULL, pi2, NULL);
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. */
@ -379,7 +381,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); &passphrase, NULL);
if (rc) if (rc)
return rc; return rc;
@ -471,7 +473,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); &passphrase, NULL);
if (!rc) if (!rc)
{ {
rc = store_key (s_skey, passphrase, 1); rc = store_key (s_skey, passphrase, 1);

View File

@ -440,6 +440,11 @@ remove_socket (char *name)
static void static void
cleanup (void) cleanup (void)
{ {
static int done;
if (done)
return;
done = 1;
deinitialize_module_cache (); deinitialize_module_cache ();
remove_socket (socket_name); remove_socket (socket_name);
remove_socket (socket_name_ssh); remove_socket (socket_name_ssh);
@ -724,6 +729,12 @@ main (int argc, char **argv )
if( parse_debug ) if( parse_debug )
log_info (_("NOTE: no default option file `%s'\n"), log_info (_("NOTE: no default option file `%s'\n"),
configname ); configname );
/* Save the default conf file name so that
reread_configuration is able to test whether the
config file has been created in the meantime. */
xfree (config_filename);
config_filename = configname;
configname = NULL;
} }
else else
{ {
@ -811,10 +822,15 @@ main (int argc, char **argv )
fclose( configfp ); fclose( configfp );
configfp = NULL; configfp = NULL;
/* Keep a copy of the name so that it can be read on SIGHUP. */ /* Keep a copy of the name so that it can be read on SIGHUP. */
config_filename = configname; if (config_filename != configname)
{
xfree (config_filename);
config_filename = configname;
}
configname = NULL; configname = NULL;
goto next_pass; goto next_pass;
} }
xfree (configname); xfree (configname);
configname = NULL; configname = NULL;
if (log_get_errorcount(0)) if (log_get_errorcount(0))
@ -1262,6 +1278,12 @@ void
agent_exit (int rc) agent_exit (int rc)
{ {
/*FIXME: update_random_seed_file();*/ /*FIXME: update_random_seed_file();*/
/* We run our cleanup handler because that may close cipher contexts
stored in secure memory and thus this needs to be done before we
explicitly terminate secure memory. */
cleanup ();
#if 1 #if 1
/* at this time a bit annoying */ /* at this time a bit annoying */
if (opt.debug & DBG_MEMSTAT_VALUE) if (opt.debug & DBG_MEMSTAT_VALUE)
@ -1337,8 +1359,8 @@ reread_configuration (void)
fp = fopen (config_filename, "r"); fp = fopen (config_filename, "r");
if (!fp) if (!fp)
{ {
log_error (_("option file `%s': %s\n"), log_info (_("option file `%s': %s\n"),
config_filename, strerror(errno) ); config_filename, strerror(errno) );
return; return;
} }

View File

@ -14,7 +14,8 @@ the ~/.gnupg home directory. This directory is named
and should have permissions 700. and should have permissions 700.
The secret keys are stored in files with a name matching the The secret keys are stored in files with a name matching the
hexadecimal representation of the keygrip[2]. hexadecimal representation of the keygrip[2] and suffixed with ".key".
Unprotected Private Key Format Unprotected Private Key Format
============================== ==============================
@ -166,21 +167,23 @@ This format is used to transfer keys between gpg and gpg-agent.
(openpgp-private-key (openpgp-private-key
(version V) (version V)
(protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)
(algo PUBKEYALGO) (algo PUBKEYALGO)
(skey CSUM c P1 c P2 c P3 ... e PN)) (skey _ P1 _ P2 _ P3 ... e PN)
(csum n)
(protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT))
* V is the packet version number (3 or 4). * V is the packet version number (3 or 4).
* PUBKEYALGO is a Libgcrypt algo name * PUBKEYALGO is a Libgcrypt algo name
* CSUM is the 16 bit checksum as defined by OpenPGP.
* P1 .. PN are the parameters; the public parameters are never encrypted * P1 .. PN are the parameters; the public parameters are never encrypted
the secrect key parameters are encrypted if the "protection" list is the secrect key parameters are encrypted if the "protection" list is
given. To make this more explicit each parameter is preceded by a given. To make this more explicit each parameter is preceded by a
flag "_" for cleartext or "e" for encrypted text. flag "_" for cleartext or "e" for encrypted text.
* CSUM is the depreciated 16 bit checksum as defined by OpenPGP. This
is an optional element.
* If PROTTYPE is "sha1" the new style SHA1 checksum is used if it is "sum" * If PROTTYPE is "sha1" the new style SHA1 checksum is used if it is "sum"
the old 16 bit checksum is used and if it is "none" no protection at the old 16 bit checksum (above) is used and if it is "none" no
all is used. protection at all is used.
* PROTALGO is a Libgcrypt style cipher algorithm name * PROTALGO is a Libgcrypt style cipher algorithm name
* IV is the initialization verctor. * IV is the initialization verctor.
* S2KMODE is the value from RFC-4880. * S2KMODE is the value from RFC-4880.
@ -189,6 +192,105 @@ This format is used to transfer keys between gpg and gpg-agent.
* S2KCOUNT is the count value from RFC-4880. * S2KCOUNT is the count value from RFC-4880.
Persistent Passphrase Format
============================
To allow persistent storage of cached passphrases we use a scheme
similar to the private-key storage format. This is a master
passphrase format where each file may protect several secrets under
one master passphrase. It is possible to have several of those files
each protected by a dedicated master passphrase. Clear text keywords
allow to list the available protected passphrases.
The name of the files with these protected secrets have this form:
pw-<string>.dat. STRING may be an arbitrary string, as a default name
for the passphrase storage the name "pw-default.dat" is suggested.
(protected-shared-secret
((desc descriptive_text)
(key [key_1] (keyword_1 keyword_2 keyword_n))
(key [key_2] (keyword_21 keyword_22 keyword_2n))
(key [key_n] (keyword_n1 keyword_n2 keyword_nn))
(protected mode (parms) encrypted_octet_string)
(protected-at <isotimestamp>)
)
)
After decryption the encrypted_octet_string yields this S-expression:
(
(
(value key_1 value_1)
(value key_2 value_2)
(value key_n value_n)
)
(hash sha1 #...[hashvalue]...#)
)
The "descriptive_text" is displayed with the prompt to enter the
unprotection passphrase.
KEY_1 to KEY_N are unique identifiers for the shared secret, for
example an URI. In case this information should be kept confidential
as well, they may not appear in the unprotected part; however they are
mandatory in the encrypted_octet_string. The list of keywords is
optional. The oder of the "key" lists and the order of the "value"
lists mut match, that is the first "key"-list is associated with the
first "value" list in the encrypted_octet_string.
The protection mode etc. is indentical to the protection mode as
decribed for the private key format.
list of the secret key parameters. The protected-at expression is
optional; the isotimestamp is 15 bytes long (e.g. "19610711T172000").
The "hash" in the encrypted_octet_string is calculated on the
concatenation of the key list and value lists: i.e it is required to
hash the concatenation of all these lists, including the
parenthesis and (if used) the protected-at list.
Example:
(protected-shared-secret
((desc "List of system passphrases")
(key "uid-1002" ("Knuth" "Donald Ervin Knuth"))
(key "uid-1001" ("Dijkstra" "Edsgar Wybe Dijkstra"))
(key)
(protected mode (parms) encrypted_octet_string)
(protected-at "20100915T111722")
)
)
with "encrypted_octet_string" decoding to:
(
(
(value 4:1002 "signal flags at the lock")
(value 4:1001 "taocp")
(value 1:0 "premature optimization is the root of all evil")
)
(hash sha1 #0102030405060708091011121314151617181920#)
)
To compute the hash this S-expression (in canoncical format) was
hashed:
((desc "List of system passphrases")
(key "uid-1002" ("Knuth" "Donald Ervin Knuth"))
(key "uid-1001" ("Dijkstra" "Edsgar Wybe Dijkstra"))
(key)
(value 4:1002 "signal flags at the lock")
(value 4:1001 "taocp")
(value 1:0 "premature optimization is the root of all evil")
(protected-at "20100915T111722")
)
Notes: Notes:
====== ======

View File

@ -66,7 +66,9 @@ 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); 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)

View File

@ -255,7 +255,9 @@ 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); &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");

View File

@ -191,14 +191,16 @@ get_standard_s2k_count (void)
/* Calculate the MIC for a private key S-Exp. SHA1HASH should point to /* Calculate the MIC for a private key or shared secret S-expression.
a 20 byte buffer. This function is suitable for any algorithms. */ SHA1HASH should point to a 20 byte buffer. This function is
suitable for all algorithms. */
static int static int
calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash) calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
{ {
const unsigned char *hash_begin, *hash_end; const unsigned char *hash_begin, *hash_end;
const unsigned char *s; const unsigned char *s;
size_t n; size_t n;
int is_shared_secret;
s = plainkey; s = plainkey;
if (*s != '(') if (*s != '(')
@ -207,16 +209,23 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
n = snext (&s); n = snext (&s);
if (!n) if (!n)
return gpg_error (GPG_ERR_INV_SEXP); return gpg_error (GPG_ERR_INV_SEXP);
if (!smatch (&s, n, "private-key")) if (smatch (&s, n, "private-key"))
is_shared_secret = 0;
else if (smatch (&s, n, "shared-secret"))
is_shared_secret = 1;
else
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
if (*s != '(') if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP); return gpg_error (GPG_ERR_UNKNOWN_SEXP);
hash_begin = s; hash_begin = s;
s++; if (!is_shared_secret)
n = snext (&s); {
if (!n) s++;
return gpg_error (GPG_ERR_INV_SEXP); n = snext (&s);
s += n; /* skip over the algorithm name */ if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* Skip the algorithm name. */
}
while (*s == '(') while (*s == '(')
{ {
@ -955,7 +964,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
xfree (final); xfree (final);
return rc; return rc;
} }
/* Now remove tha part which is included in the MIC but should not /* Now remove the part which is included in the MIC but should not
go into the final thing. */ go into the final thing. */
if (cutlen) if (cutlen)
{ {

View File

@ -289,6 +289,13 @@ test_agent_get_shadow_info (void)
} }
static void
test_agent_protect_shared_secret (void)
{
}
int int
@ -305,6 +312,7 @@ main (int argc, char **argv)
test_make_shadow_info (); test_make_shadow_info ();
test_agent_shadow_key (); test_agent_shadow_key ();
test_agent_get_shadow_info (); test_agent_get_shadow_info ();
test_agent_protect_shared_secret ();
return 0; return 0;
} }

View File

@ -1,3 +1,17 @@
2010-09-30 Werner Koch <wk@g10code.com>
* util.h (GPG_ERR_FULLY_CANCELED): Add replacement.
2010-09-17 Werner Koch <wk@g10code.com>
* http.c (INADDR_NONE): Provide fallback.
* logging.c (INADDR_NONE): Ditto.
2010-09-16 Werner Koch <wk@g10code.com>
* util.h: Add GPG_ERR_MISSING_ISSUER_CERT.
* status.c (get_inv_recpsgnr_code): Ditto.
2010-09-13 Werner Koch <wk@g10code.com> 2010-09-13 Werner Koch <wk@g10code.com>
* homedir.c (gnupg_bindir) [W32CE]: Change to bin/. * homedir.c (gnupg_bindir) [W32CE]: Change to bin/.

View File

@ -114,6 +114,9 @@ struct srventry
#ifndef EAGAIN #ifndef EAGAIN
#define EAGAIN EWOULDBLOCK #define EAGAIN EWOULDBLOCK
#endif #endif
#ifndef INADDR_NONE /* Slowaris is missing that. */
#define INADDR_NONE ((unsigned long)(-1))
#endif /*INADDR_NONE*/
#define HTTP_PROXY_ENV "http_proxy" #define HTTP_PROXY_ENV "http_proxy"
#define MAX_LINELEN 20000 /* Max. length of a HTTP header line. */ #define MAX_LINELEN 20000 /* Max. length of a HTTP header line. */

View File

@ -68,6 +68,9 @@
#ifndef EAFNOSUPPORT #ifndef EAFNOSUPPORT
# define EAFNOSUPPORT EINVAL # define EAFNOSUPPORT EINVAL
#endif #endif
#ifndef INADDR_NONE /* Slowaris is missing that. */
#define INADDR_NONE ((unsigned long)(-1))
#endif /*INADDR_NONE*/
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
#define sock_close(a) closesocket(a) #define sock_close(a) closesocket(a)

View File

@ -82,7 +82,7 @@ sskip (unsigned char const **buf, int *depth)
/* Check whether the the string at the address BUF points to matches /* Check whether the the string at the address BUF points to matches
the token. Return true on match and update BUF to point behind the the token. Return true on match and update BUF to point behind the
token. Return false and dont update tha buffer if it does not token. Return false and do not update the buffer if it does not
match. */ match. */
static inline int static inline int
smatch (unsigned char const **buf, size_t buflen, const char *token) smatch (unsigned char const **buf, size_t buflen, const char *token)

View File

@ -58,6 +58,7 @@ get_inv_recpsgnr_code (gpg_error_t err)
case GPG_ERR_NOT_TRUSTED: errstr = "10"; break; case GPG_ERR_NOT_TRUSTED: errstr = "10"; break;
case GPG_ERR_MISSING_CERT: errstr = "11"; break; case GPG_ERR_MISSING_CERT: errstr = "11"; break;
case GPG_ERR_MISSING_ISSUER_CERT: errstr = "12"; break;
default: errstr = "0"; break; default: errstr = "0"; break;
} }

View File

@ -33,6 +33,12 @@
#ifndef GPG_ERR_NOT_INITIALIZED #ifndef GPG_ERR_NOT_INITIALIZED
#define GPG_ERR_NOT_INITIALIZED 184 #define GPG_ERR_NOT_INITIALIZED 184
#endif #endif
#ifndef GPG_ERR_MISSING_ISSUER_CERT
#define GPG_ERR_MISSING_ISSUER_CERT 185
#endif
#ifndef GPG_ERR_FULLY_CANCELED
#define GPG_ERR_FULLY_CANCELED 198
#endif
/* Hash function used with libksba. */ /* Hash function used with libksba. */

View File

@ -396,7 +396,7 @@ AH_BOTTOM([
# define GNUPG_DEFAULT_HOMEDIR "/gnupg" # define GNUPG_DEFAULT_HOMEDIR "/gnupg"
# endif # endif
#elif defined(__VMS) #elif defined(__VMS)
#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg" #define GNUPG_DEFAULT_HOMEDIR "/SYS$LOGIN/gnupg"
#else #else
#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
#endif #endif

View File

@ -1,3 +1,7 @@
2010-09-16 Werner Koch <wk@g10code.com>
* validate.c (validate_cert_chain): Use GPG_ERR_MISSING_ISSUER_CERT.
2010-08-13 Werner Koch <wk@g10code.com> 2010-08-13 Werner Koch <wk@g10code.com>
* Makefile.am (dirmngr_SOURCES): Add w32-ldap-help.h. * Makefile.am (dirmngr_SOURCES): Add w32-ldap-help.h.

View File

@ -623,7 +623,7 @@ validate_cert_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
log_error (_("issuer certificate not found: %s\n"), log_error (_("issuer certificate not found: %s\n"),
gpg_strerror (err)); gpg_strerror (err));
/* Use a better understandable error code. */ /* Use a better understandable error code. */
err = gpg_error (GPG_ERR_MISSING_CERT); err = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
goto leave; goto leave;
} }

View File

@ -1,3 +1,7 @@
2010-09-28 Werner Koch <wk@g10code.com>
* Makefile.am (AM_MAKEINFOFLAGS): Add define gpgtwoone.
2010-09-28 David Shaw <dshaw@jabberwocky.com> 2010-09-28 David Shaw <dshaw@jabberwocky.com>
* gpg.texi (OpenPGP Options): Clarify that --force-v3-sigs * gpg.texi (OpenPGP Options): Clarify that --force-v3-sigs

View File

@ -586,7 +586,8 @@ more arguments in future versions.
8 := "Policy mismatch" 8 := "Policy mismatch"
9 := "Not a secret key" 9 := "Not a secret key"
10 := "Key not trusted" 10 := "Key not trusted"
11 := "Missing certificate" (e.g. intermediate or root cert.) 11 := "Missing certificate"
12 := "Missing issuer certificate"
Note that for historical reasons the INV_RECP status is also Note that for historical reasons the INV_RECP status is also
used for gpgsm's SIGNER command where it relates to signer's used for gpgsm's SIGNER command where it relates to signer's

View File

@ -57,9 +57,9 @@ gnupg_TEXINFOS = \
DVIPS = TEXINPUTS="$(srcdir)$(PATH_SEPARATOR)$$TEXINPUTS" dvips DVIPS = TEXINPUTS="$(srcdir)$(PATH_SEPARATOR)$$TEXINPUTS" dvips
AM_MAKEINFOFLAGS = -I $(srcdir) --css-include=$(srcdir)/texi.css AM_MAKEINFOFLAGS = -I $(srcdir) --css-include=$(srcdir)/texi.css -D gpgtwoone
YAT2M_OPTIONS = -I $(srcdir) \ YAT2M_OPTIONS = -I $(srcdir) -D gpgtwoone \
--release "GnuPG @PACKAGE_VERSION@" --source "GNU Privacy Guard" --release "GnuPG @PACKAGE_VERSION@" --source "GNU Privacy Guard"
myman_sources = gnupg7.texi gpg.texi gpgsm.texi gpg-agent.texi \ myman_sources = gnupg7.texi gpg.texi gpgsm.texi gpg-agent.texi \

View File

@ -194,7 +194,7 @@ or other purposes and don't have a corresponding certificate.
@item A root certificate does not verify @item A root certificate does not verify
A common problem is that the root certificate misses the required A common problem is that the root certificate misses the required
basicConstrains attribute and thus @command{gpgsm} rejects this basicConstraints attribute and thus @command{gpgsm} rejects this
certificate. An error message indicating ``no value'' is a sign for certificate. An error message indicating ``no value'' is a sign for
such a certificate. You may use the @code{relax} flag in such a certificate. You may use the @code{relax} flag in
@file{trustlist.txt} to accept the certificate anyway. Note that the @file{trustlist.txt} to accept the certificate anyway. Note that the

View File

@ -317,8 +317,12 @@ should in general not be used to avoid X-sniffing attacks.
@item --log-file @var{file} @item --log-file @var{file}
@opindex log-file @opindex log-file
Append all logging output to @var{file}. This is very helpful in Append all logging output to @var{file}. This is very helpful in seeing
seeing what the agent actually does. what the agent actually does. If neither a log file nor a log file
descriptor has been set on a Windows platform, the Registry entry
@var{HKCU\Software\GNU\GnuPG:DefaultLogFile}, if set, is used to specify
the logging output.
@anchor{option --allow-mark-trusted} @anchor{option --allow-mark-trusted}
@item --allow-mark-trusted @item --allow-mark-trusted
@ -1148,11 +1152,13 @@ This can be used to see whether a secret key is available. It does
not return any information on whether the key is somehow protected. not return any information on whether the key is somehow protected.
@example @example
HAVEKEY @var{keygrip} HAVEKEY @var{keygrips}
@end example @end example
The Agent answers either with OK or @code{No_Secret_Key} (208). The The agent answers either with OK or @code{No_Secret_Key} (208). The
caller may want to check for other error codes as well. caller may want to check for other error codes as well. More than one
keygrip may be given. In this case the command returns success if at
least one of the keygrips corresponds to an available secret key.
@node Agent LEARN @node Agent LEARN

View File

@ -3,6 +3,11 @@
@c This is part of the GnuPG manual. @c This is part of the GnuPG manual.
@c For copying conditions, see the file gnupg.texi. @c For copying conditions, see the file gnupg.texi.
@c Note that we use this texinfo file for all versions of GnuPG: 1.4.x,
@c 2.0 and 2.1. The macro "gpgone" controls parts which are only valid
@c for GnuPG 1.4, the macro "gpgtwoone" controls parts which are only
@c valid for GnupG 2.1 and later.
@node Invoking GPG @node Invoking GPG
@chapter Invoking GPG @chapter Invoking GPG
@cindex GPG command options @cindex GPG command options
@ -68,18 +73,19 @@ implementation.
@ifset gpgone @ifset gpgone
This is the standalone version of @command{gpg}. For desktop use you This is the standalone version of @command{gpg}. For desktop use you
should consider using @command{gpg2}. should consider using @command{gpg2} @footnote{On some platforms gpg2 is
installed under the name @command{gpg}}.
@end ifset @end ifset
@ifclear gpgone @ifclear gpgone
In contrast to the standalone version @command{gpg}, which is more In contrast to the standalone version @command{gpg}, which is more
suited for server and embedded platforms, this version is installed suited for server and embedded platforms, this version is commonly
under the name @command{gpg2} and more targeted to the desktop as it installed under the name @command{gpg2} and more targeted to the desktop
requires several other modules to be installed. The standalone version as it requires several other modules to be installed. The standalone
will be kept maintained and it is possible to install both versions on version will be kept maintained and it is possible to install both
the same system. If you need to use different configuration files, you versions on the same system. If you need to use different configuration
should make use of something like @file{gpg.conf-2} instead of just files, you should make use of something like @file{gpg.conf-2} instead
@file{gpg.conf}. of just @file{gpg.conf}.
@end ifclear @end ifclear
@manpause @manpause
@ -415,8 +421,10 @@ normally not very useful and a security risk. The second form of the
command has the special property to render the secret part of the command has the special property to render the secret part of the
primary key useless; this is a GNU extension to OpenPGP and other primary key useless; this is a GNU extension to OpenPGP and other
implementations can not be expected to successfully import such a key. implementations can not be expected to successfully import such a key.
@ifclear gpgtwoone
See the option @option{--simple-sk-checksum} if you want to import such See the option @option{--simple-sk-checksum} if you want to import such
an exported key with an older OpenPGP implementation. an exported key with an older OpenPGP implementation.
@end ifclear
@item --import @item --import
@itemx --fast-import @itemx --fast-import
@ -1550,6 +1558,7 @@ key signer (defaults to 3)
@item --max-cert-depth @code{n} @item --max-cert-depth @code{n}
Maximum depth of a certification chain (default is 5). Maximum depth of a certification chain (default is 5).
@ifclear gpgtwoone
@item --simple-sk-checksum @item --simple-sk-checksum
Secret keys are integrity protected by using a SHA-1 checksum. This Secret keys are integrity protected by using a SHA-1 checksum. This
method is part of the upcoming enhanced OpenPGP specification but method is part of the upcoming enhanced OpenPGP specification but
@ -1560,6 +1569,7 @@ a security risk. Note that using this option only takes effect when
the secret key is encrypted - the simplest way to make this happen is the secret key is encrypted - the simplest way to make this happen is
to change the passphrase on the key (even changing it to the same to change the passphrase on the key (even changing it to the same
value is acceptable). value is acceptable).
@end ifclear
@item --no-sig-cache @item --no-sig-cache
Do not cache the verification status of key signatures. Do not cache the verification status of key signatures.
@ -1884,11 +1894,17 @@ program that does not accept attribute user IDs. Defaults to yes.
Include designated revoker information that was marked as Include designated revoker information that was marked as
"sensitive". Defaults to no. "sensitive". Defaults to no.
@c Since GnuPG 2.1 gpg-agent manages the secret key and thus the
@c export-reset-subkey-passwd hack is not anymore justified. Such use
@c cases need to be implemented using a specialized secret key export
@c tool.
@ifclear gpgtwoone
@item export-reset-subkey-passwd @item export-reset-subkey-passwd
When using the @option{--export-secret-subkeys} command, this option resets When using the @option{--export-secret-subkeys} command, this option resets
the passphrases for all exported subkeys to empty. This is useful the passphrases for all exported subkeys to empty. This is useful
when the exported subkey is to be used on an unattended machine where when the exported subkey is to be used on an unattended machine where
a passphrase doesn't necessarily make sense. Defaults to no. a passphrase doesn't necessarily make sense. Defaults to no.
@end ifclear
@item export-clean @item export-clean
Compact (remove all signatures from) user IDs on the key being Compact (remove all signatures from) user IDs on the key being

View File

@ -31,7 +31,7 @@
@command{gpgsm} is a tool similar to @command{gpg} to provide digital @command{gpgsm} is a tool similar to @command{gpg} to provide digital
encryption and signing services on X.509 certificates and the CMS encryption and signing services on X.509 certificates and the CMS
protocol. It is mainly used as a backend for S/MIME mail processing. protocol. It is mainly used as a backend for S/MIME mail processing.
@command{gpgsm} includes a full features certificate management and @command{gpgsm} includes a full featured certificate management and
complies with all rules defined for the German Sphinx project. complies with all rules defined for the German Sphinx project.
@manpause @manpause
@ -286,7 +286,7 @@ smartcard is not yet supported.
@node GPGSM Options @node GPGSM Options
@section Option Summary @section Option Summary
@command{GPGSM} comes features a bunch of options to control the exact behaviour @command{GPGSM} features a bunch of options to control the exact behaviour
and to change the default configuration. and to change the default configuration.
@menu @menu
@ -566,10 +566,9 @@ certificate.
@item --include-certs @var{n} @item --include-certs @var{n}
@opindex include-certs @opindex include-certs
Using @var{n} of -2 includes all certificate except for the root cert, Using @var{n} of -2 includes all certificate except for the root cert,
-1 includes all certs, 0 does not include any certs, 1 includes only -1 includes all certs, 0 does not include any certs, 1 includes only the
the signers cert (this is the default) and all other positive signers cert and all other positive values include up to @var{n}
values include up to @var{n} certificates starting with the signer cert. certificates starting with the signer cert. The default is -2.
The default is -2.
@item --cipher-algo @var{oid} @item --cipher-algo @var{oid}
@opindex cipher-algo @opindex cipher-algo

View File

@ -1,3 +1,67 @@
2010-10-01 Werner Koch <wk@g10code.com>
* export.c (do_export_stream): Rewrite to take the secret keys
from the agent.
(canon_pubkey_algo, transfer_format_to_openpgp): New.
2010-09-29 Werner Koch <wk@g10code.com>
* keygen.c (key_from_sexp): Fix memory leak in the error case.
* call-agent.c (agent_export_key): New.
2010-09-29 Werner Koch <wk@g10code.com>
* build-packet.c (build_packet): Fix up the pkttype.
* keyid.c (keystr_with_sub): Make SUB_KID optional.
(keystr_from_pk_with_sub): Ditto.
* call-agent.c (agent_scd_pksign): Add missing space.
* mainproc.c (struct mainproc_context): Add field CTRL.
(proc_packets): Add arg CTRL. Change all callers.
(proc_signature_packets, proc_signature_packets_by_fd)
(proc_encryption_packets): Add arg CTRL. Change all callers.
* compress.c (handle_compressed): Ditto.
* getkey.c (get_pubkey_byname): Ditto.
* keyserver.c (keyserver_spawn, keyserver_work): Ditto.
(show_prompt, keyserver_export, keyserver_import)
(keyserver_import_fprint, keyserver_import_keyid)
(keyserver_refresh, keyserver_search, keyserver_fetch)
(keyserver_import_name, keyserver_search_prompt)
(keyserver_import_pka, keyserver_import_cert): Ditto.
callers.
* verify.c (verify_signatures, verify_files): Ditto.
* sign.c (sign_file): Ditto.
* encrypt.c (encrypt_crypt, encrypt_crypt_files): Ditto.
* pkclist.c (find_and_check_key, build_pk_list): Ditto.
* keylist.c (locate_one, public_key_list, secret_key_list): Ditto.
* card-util.c (fetch_url, card_edit): Ditto.
* import.c (check_prefs, import_one, revocation_present): Ditto.
* keyedit.c (menu_addrevoker, keyedit_menu): Ditto.
* decrypt-data.c (decrypt_data): Ditto.
* decrypt.c (decrypt_message, decrypt_messages)
(decrypt_message_fd): Ditto.
* gpgv.c (main): Add CTRL structure.
2010-09-28 Werner Koch <wk@g10code.com>
* options.h (struct opt): Remove SIMPLE_SK_CHECKSUM.
* export.c (parse_export_options): Remove option
export-resert-subkey-passwd.
(do_export_stream, do_export, export_pubkeys)
(export_pubkeys_stream, export_seckeys, export_secsubkeys): Add
arg CTRL. Change all callers.
* call-agent.c (hash_algo_option): New.
(agent_scd_pksign): Use it.
2010-09-17 Werner Koch <wk@g10code.com>
* call-agent.c (agent_probe_any_secret_key): New.
2010-09-28 David Shaw <dshaw@jabberwocky.com> 2010-09-28 David Shaw <dshaw@jabberwocky.com>
* options.skel: Make the example for force-v3-sigs match * options.skel: Make the example for force-v3-sigs match

View File

@ -26,10 +26,10 @@
#include <ctype.h> #include <ctype.h>
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "status.h" #include "status.h"
#include "iobuf.h" #include "iobuf.h"
#include "util.h"
#include "cipher.h" #include "cipher.h"
#include "i18n.h" #include "i18n.h"
#include "options.h" #include "options.h"
@ -71,8 +71,16 @@ build_packet( IOBUF out, PACKET *pkt )
log_debug("build_packet() type=%d\n", pkt->pkttype ); log_debug("build_packet() type=%d\n", pkt->pkttype );
assert( pkt->pkt.generic ); assert( pkt->pkt.generic );
switch( (pkttype = pkt->pkttype) ) switch ((pkttype = pkt->pkttype))
{ {
case PKT_PUBLIC_KEY:
if (pkt->pkt.public_key->seckey_info)
pkttype = PKT_SECRET_KEY;
break;
case PKT_PUBLIC_SUBKEY:
if (pkt->pkt.public_key->seckey_info)
pkttype = PKT_SECRET_SUBKEY;
break;
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break; case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED: case PKT_ENCRYPTED:
case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break; case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;

View File

@ -901,7 +901,27 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
put_membuf (data, buffer, length); put_membuf (data, buffer, length);
return 0; return 0;
} }
/* Helper returning a command option to describe the used hash
algorithm. See scd/command.c:cmd_pksign. */
static const char *
hash_algo_option (int algo)
{
switch (algo)
{
case GCRY_MD_RMD160: return "--hash=rmd160";
case GCRY_MD_SHA1 : return "--hash=sha1";
case GCRY_MD_SHA224: return "--hash=sha224";
case GCRY_MD_SHA256: return "--hash=sha256";
case GCRY_MD_SHA384: return "--hash=sha384";
case GCRY_MD_SHA512: return "--hash=sha512";
case GCRY_MD_MD5 : return "--hash=md5";
default: return "";
}
}
/* Send a sign command to the scdaemon via gpg-agent's pass thru /* Send a sign command to the scdaemon via gpg-agent's pass thru
mechanism. */ mechanism. */
int int
@ -942,14 +962,11 @@ agent_scd_pksign (const char *serialno, int hashalgo,
return rc; return rc;
init_membuf (&data, 1024); init_membuf (&data, 1024);
#if 0 /* if (!hashalgo) /\* Temporary test hack. *\/ */
if (!hashalgo) /* Temporary test hack. */ /* snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno); */
snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno); /* else */
else snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s",
#endif hash_algo_option (hashalgo), serialno);
snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
serialno);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, NULL, NULL, NULL);
@ -1325,6 +1342,57 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
return err; return err;
} }
/* Ask the agent whether a secret key is availabale for any of the
keys (primary or sub) in KEYBLOCK. Returns 0 if available. */
gpg_error_t
agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
char *p;
kbnode_t kbctx, node;
int nkeys;
unsigned char grip[20];
err = start_agent (ctrl, 0);
if (err)
return err;
err = gpg_error (GPG_ERR_NO_SECKEY); /* Just in case no key was
found in KEYBLOCK. */
p = stpcpy (line, "HAVEKEY");
for (kbctx=NULL, nkeys=0; (node = walk_kbnode (keyblock, &kbctx, 0)); )
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_KEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
{
if (nkeys && ((p - line) + 41) > (ASSUAN_LINELENGTH - 2))
{
err = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (err != gpg_err_code (GPG_ERR_NO_SECKEY))
break; /* Seckey available or unexpected error - ready. */
p = stpcpy (line, "HAVEKEY");
nkeys = 0;
}
err = keygrip_from_pk (node->pkt->pkt.public_key, grip);
if (err)
return err;
*p++ = ' ';
bin2hex (grip, 20, p);
p += 40;
nkeys++;
}
if (!err && nkeys)
err = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
return err;
}
static gpg_error_t static gpg_error_t
@ -1393,7 +1461,8 @@ agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
} }
/* Status callback for agent_import_key and agent_genkey. */ /* Status callback for agent_import_key, agent_export_key and
agent_genkey. */
static gpg_error_t static gpg_error_t
cache_nonce_status_cb (void *opaque, const char *line) cache_nonce_status_cb (void *opaque, const char *line)
{ {
@ -1849,3 +1918,56 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
} }
/* Receive a secret key from the agent. HEXKEYGRIP is the hexified
keygrip, DESC a prompt to be displayed with the agent's passphrase
question (needs to be plus+percent escaped). On success the key is
stored as a canonical S-expression at R_RESULT and R_RESULTLEN. */
gpg_error_t
agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen)
{
gpg_error_t err;
membuf_t data;
size_t len;
unsigned char *buf;
char line[ASSUAN_LINELENGTH];
*r_result = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
if (desc)
{
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
err = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
}
snprintf (line, DIM(line)-1, "EXPORT_KEY --openpgp %s%s %s",
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
hexkeygrip);
init_membuf_secure (&data, 1024);
err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data,
default_inq_cb, ctrl,
cache_nonce_status_cb, cache_nonce_addr);
if (err)
{
xfree (get_membuf (&data, &len));
return err;
}
buf = get_membuf (&data, &len);
if (!buf)
return gpg_error_from_syserror ();
*r_result = buf;
*r_resultlen = len;
return 0;
}

View File

@ -144,6 +144,11 @@ gpg_error_t agent_get_s2k_count (unsigned long *r_count);
0 if the secret key is available. */ 0 if the secret key is available. */
gpg_error_t agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk); gpg_error_t agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk);
/* Ask the agent whether a secret key is availabale for any of the
keys (primary or sub) in KEYBLOCK. Returns 0 if available. */
gpg_error_t agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock);
/* Return infos about the secret key with HEXKEYGRIP. */ /* Return infos about the secret key with HEXKEYGRIP. */
gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
char **r_serialno); char **r_serialno);
@ -174,6 +179,11 @@ gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
char **cache_nonce_addr, char **cache_nonce_addr,
const void *key, size_t keylen); const void *key, size_t keylen);
/* Receive a key from the agent. */
gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip,
const char *desc, char **cache_nonce_addr,
unsigned char **r_result, size_t *r_resultlen);
#endif /*GNUPG_G10_CALL_AGENT_H*/ #endif /*GNUPG_G10_CALL_AGENT_H*/

View File

@ -721,7 +721,7 @@ change_url (void)
/* Fetch the key from the URL given on the card or try to get it from /* Fetch the key from the URL given on the card or try to get it from
the default keyserver. */ the default keyserver. */
static int static int
fetch_url(void) fetch_url (ctrl_t ctrl)
{ {
int rc; int rc;
struct agent_card_info_s info; struct agent_card_info_s info;
@ -751,13 +751,13 @@ fetch_url(void)
event, the fpr/keyid is not meaningful for straight event, the fpr/keyid is not meaningful for straight
HTTP fetches, but using it allows the card to point HTTP fetches, but using it allows the card to point
to HKP and LDAP servers as well. */ to HKP and LDAP servers as well. */
rc=keyserver_import_fprint(info.fpr1,20,spec); rc = keyserver_import_fprint (ctrl, info.fpr1, 20, spec);
free_keyserver_spec(spec); free_keyserver_spec(spec);
} }
} }
else if (info.fpr1valid) else if (info.fpr1valid)
{ {
rc = keyserver_import_fprint (info.fpr1, 20, opt.keyserver); rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver);
} }
} }
@ -1765,7 +1765,7 @@ card_edit_completion(const char *text, int start, int end)
/* Menu to edit all user changeable values on an OpenPGP card. Only /* Menu to edit all user changeable values on an OpenPGP card. Only
Key creation is not handled here. */ Key creation is not handled here. */
void void
card_edit (strlist_t commands) card_edit (ctrl_t ctrl, strlist_t commands)
{ {
enum cmdids cmd = cmdNOP; enum cmdids cmd = cmdNOP;
int have_commands = !!commands; int have_commands = !!commands;
@ -1924,7 +1924,7 @@ card_edit (strlist_t commands)
break; break;
case cmdFETCH: case cmdFETCH:
fetch_url(); fetch_url (ctrl);
break; break;
case cmdLOGIN: case cmdLOGIN:

View File

@ -300,7 +300,7 @@ release_context (compress_filter_context_t *ctx)
* Handle a compressed packet * Handle a compressed packet
*/ */
int int
handle_compressed( void *procctx, PKT_compressed *cd, handle_compressed (ctrl_t ctrl, void *procctx, PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru ) int (*callback)(IOBUF, void *), void *passthru )
{ {
compress_filter_context_t *cfx; compress_filter_context_t *cfx;
@ -315,7 +315,7 @@ handle_compressed( void *procctx, PKT_compressed *cd,
if( callback ) if( callback )
rc = callback(cd->buf, passthru ); rc = callback(cd->buf, passthru );
else else
rc = proc_packets(procctx, cd->buf); rc = proc_packets (ctrl,procctx, cd->buf);
cd->buf = NULL; cd->buf = NULL;
return rc; return rc;
} }

View File

@ -74,7 +74,7 @@ release_dfx_context (decode_filter_ctx_t dfx)
* Decrypt the data, specified by ED with the key DEK. * Decrypt the data, specified by ED with the key DEK.
*/ */
int int
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek ) decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
{ {
decode_filter_ctx_t dfx; decode_filter_ctx_t dfx;
byte *p; byte *p;
@ -191,7 +191,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
else else
iobuf_push_filter ( ed->buf, decode_filter, dfx ); iobuf_push_filter ( ed->buf, decode_filter, dfx );
proc_packets ( procctx, ed->buf ); proc_packets (ctrl, procctx, ed->buf );
ed->buf = NULL; ed->buf = NULL;
if (dfx->eof_seen > 1 ) if (dfx->eof_seen > 1 )
rc = gpg_error (GPG_ERR_INV_PACKET); rc = gpg_error (GPG_ERR_INV_PACKET);

View File

@ -43,7 +43,7 @@
* rejects files which don't begin with an encrypted message. * rejects files which don't begin with an encrypted message.
*/ */
int int
decrypt_message (const char *filename) decrypt_message (ctrl_t ctrl, const char *filename)
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t *afx = NULL; armor_filter_context_t *afx = NULL;
@ -86,7 +86,7 @@ decrypt_message (const char *filename)
no_out = 1; no_out = 1;
opt.outfile = "-"; opt.outfile = "-";
} }
rc = proc_encryption_packets ( NULL, fp ); rc = proc_encryption_packets (ctrl, NULL, fp );
if (no_out) if (no_out)
opt.outfile = NULL; opt.outfile = NULL;
@ -100,7 +100,7 @@ decrypt_message (const char *filename)
/* Same as decrypt_message but takes a file descriptor for input and /* Same as decrypt_message but takes a file descriptor for input and
output. */ output. */
gpg_error_t gpg_error_t
decrypt_message_fd (int input_fd, int output_fd) decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd)
{ {
gpg_error_t err; gpg_error_t err;
IOBUF fp; IOBUF fp;
@ -158,7 +158,7 @@ decrypt_message_fd (int input_fd, int output_fd)
} }
} }
err = proc_encryption_packets ( NULL, fp ); err = proc_encryption_packets (ctrl, NULL, fp );
iobuf_close (fp); iobuf_close (fp);
fclose (opt.outfp); fclose (opt.outfp);
@ -170,7 +170,7 @@ decrypt_message_fd (int input_fd, int output_fd)
void void
decrypt_messages (int nfiles, char *files[]) decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t *afx = NULL; armor_filter_context_t *afx = NULL;
@ -251,7 +251,7 @@ decrypt_messages (int nfiles, char *files[])
push_armor_filter ( afx, fp ); push_armor_filter ( afx, fp );
} }
} }
rc = proc_packets(NULL, fp); rc = proc_packets (ctrl,NULL, fp);
iobuf_close(fp); iobuf_close(fp);
if (rc) if (rc)
log_error("%s: decryption failed: %s\n", print_fname_stdin(filename), log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),

View File

@ -461,7 +461,7 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
* PROVIDED_PKS; if not the function builds a list of keys on its own. * PROVIDED_PKS; if not the function builds a list of keys on its own.
*/ */
int int
encrypt_crypt (int filefd, const char *filename, encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
strlist_t remusr, int use_symkey, pk_list_t provided_keys, strlist_t remusr, int use_symkey, pk_list_t provided_keys,
int outputfd) int outputfd)
{ {
@ -503,7 +503,7 @@ encrypt_crypt (int filefd, const char *filename,
pk_list = provided_keys; pk_list = provided_keys;
else else
{ {
if ((rc = build_pk_list (remusr, &pk_list, PUBKEY_USAGE_ENC))) if ((rc = build_pk_list (ctrl, remusr, &pk_list, PUBKEY_USAGE_ENC)))
{ {
release_progress_context (pfx); release_progress_context (pfx);
return rc; return rc;
@ -939,7 +939,7 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
void void
encrypt_crypt_files (int nfiles, char **files, strlist_t remusr) encrypt_crypt_files (ctrl_t ctrl, int nfiles, char **files, strlist_t remusr)
{ {
int rc = 0; int rc = 0;
@ -963,7 +963,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
} }
line[strlen(line)-1] = '\0'; line[strlen(line)-1] = '\0';
print_file_status(STATUS_FILE_START, line, 2); print_file_status(STATUS_FILE_START, line, 2);
rc = encrypt_crypt (-1, line, remusr, 0, NULL, -1); rc = encrypt_crypt (ctrl, -1, line, remusr, 0, NULL, -1);
if (rc) if (rc)
log_error ("encryption of `%s' failed: %s\n", log_error ("encryption of `%s' failed: %s\n",
print_fname_stdin(line), g10_errstr(rc) ); print_fname_stdin(line), g10_errstr(rc) );
@ -975,7 +975,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
while (nfiles--) while (nfiles--)
{ {
print_file_status(STATUS_FILE_START, *files, 2); print_file_status(STATUS_FILE_START, *files, 2);
if ( (rc = encrypt_crypt (-1, *files, remusr, 0, NULL, -1)) ) if ( (rc = encrypt_crypt (ctrl, -1, *files, remusr, 0, NULL, -1)) )
log_error("encryption of `%s' failed: %s\n", log_error("encryption of `%s' failed: %s\n",
print_fname_stdin(*files), g10_errstr(rc) ); print_fname_stdin(*files), g10_errstr(rc) );
write_status( STATUS_FILE_DONE ); write_status( STATUS_FILE_DONE );

View File

@ -1,6 +1,6 @@
/* export.c /* export.c - Export keys in the OpenPGP defined format.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005 Free Software Foundation, Inc. * 2005, 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -34,7 +34,7 @@
#include "main.h" #include "main.h"
#include "i18n.h" #include "i18n.h"
#include "trustdb.h" #include "trustdb.h"
#include "call-agent.h"
/* An object to keep track of subkeys. */ /* An object to keep track of subkeys. */
struct subkey_list_s struct subkey_list_s
@ -45,10 +45,12 @@ struct subkey_list_s
typedef struct subkey_list_s *subkey_list_t; typedef struct subkey_list_s *subkey_list_t;
static int do_export( strlist_t users, int secret, unsigned int options ); static int do_export (ctrl_t ctrl,
static int do_export_stream( IOBUF out, strlist_t users, int secret, strlist_t users, int secret, unsigned int options );
KBNODE *keyblock_out, unsigned int options, static int do_export_stream (ctrl_t ctrl, iobuf_t out,
int *any ); strlist_t users, int secret,
kbnode_t *keyblock_out, unsigned int options,
int *any);
static int build_sexp (iobuf_t out, PACKET *pkt, int *indent); static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
@ -63,8 +65,6 @@ parse_export_options(char *str,unsigned int *options,int noisy)
N_("export attribute user IDs (generally photo IDs)")}, N_("export attribute user IDs (generally photo IDs)")},
{"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL, {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
N_("export revocation keys marked as \"sensitive\"")}, N_("export revocation keys marked as \"sensitive\"")},
{"export-reset-subkey-passwd",EXPORT_RESET_SUBKEY_PASSWD,NULL,
N_("remove the passphrase from exported subkeys")},
{"export-clean",EXPORT_CLEAN,NULL, {"export-clean",EXPORT_CLEAN,NULL,
N_("remove unusable parts from key during export")}, N_("remove unusable parts from key during export")},
{"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL, {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
@ -93,9 +93,9 @@ parse_export_options(char *str,unsigned int *options,int noisy)
* options are defined in main.h. * options are defined in main.h.
* If USERS is NULL, the complete ring will be exported. */ * If USERS is NULL, the complete ring will be exported. */
int int
export_pubkeys( strlist_t users, unsigned int options ) export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options )
{ {
return do_export( users, 0, options ); return do_export (ctrl, users, 0, options );
} }
/**************** /****************
@ -103,35 +103,41 @@ export_pubkeys( strlist_t users, unsigned int options )
* been exported * been exported
*/ */
int int
export_pubkeys_stream( IOBUF out, strlist_t users, export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
KBNODE *keyblock_out, unsigned int options ) kbnode_t *keyblock_out, unsigned int options )
{ {
int any, rc; int any, rc;
rc = do_export_stream( out, users, 0, keyblock_out, options, &any ); rc = do_export_stream (ctrl, out, users, 0, keyblock_out, options, &any);
if( !rc && !any ) if (!rc && !any)
rc = -1; rc = -1;
return rc; return rc;
} }
int int
export_seckeys( strlist_t users ) export_seckeys (ctrl_t ctrl, strlist_t users )
{ {
/* Use only relevant options for the secret key. */ /* Use only relevant options for the secret key. */
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT); unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
return do_export( users, 1, options ); return do_export (ctrl, users, 1, options);
} }
int int
export_secsubkeys( strlist_t users ) export_secsubkeys (ctrl_t ctrl, strlist_t users )
{ {
/* Use only relevant options for the secret key. */ /* Use only relevant options for the secret key. */
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT); unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
return do_export( users, 2, options ); return do_export (ctrl, users, 2, options);
} }
/* Export the keys identified by the list of strings in USERS. If
Secret is false public keys will be exported. With secret true
secret keys will be exported; in this case 1 means the entire
secret keyblock and 2 only the subkeys. OPTIONS are the export
options to apply. */
static int static int
do_export( strlist_t users, int secret, unsigned int options ) do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options )
{ {
IOBUF out = NULL; IOBUF out = NULL;
int any, rc; int any, rc;
@ -156,7 +162,7 @@ do_export( strlist_t users, int secret, unsigned int options )
push_compress_filter (out,&zfx,default_compress_algo()); push_compress_filter (out,&zfx,default_compress_algo());
} }
rc = do_export_stream ( out, users, secret, NULL, options, &any ); rc = do_export_stream (ctrl, out, users, secret, NULL, options, &any );
if ( rc || !any ) if ( rc || !any )
iobuf_cancel (out); iobuf_cancel (out);
@ -275,11 +281,324 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
} }
/* If keyblock_out is non-NULL, AND the exit code is zero, then it /* Return a canonicalized public key algoithms. This is used to
contains a pointer to the first keyblock found and exported. No compare different flavors of algorithms (e.g. ELG and ELG_E are
other keyblocks are exported. The caller must free it. */ considered the same). */
static int static int
do_export_stream (iobuf_t out, strlist_t users, int secret, canon_pubkey_algo (int algo)
{
switch (algo)
{
case GCRY_PK_RSA:
case GCRY_PK_RSA_E:
case GCRY_PK_RSA_S: return GCRY_PK_RSA;
case GCRY_PK_ELG:
case GCRY_PK_ELG_E: return GCRY_PK_ELG;
default: return algo;
}
}
/* Use the key transfer format given in S_PGP to create the secinfo
structure in PK and chnage the parameter array in PK to include the
secret parameters. */
static gpg_error_t
transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
{
gpg_error_t err;
gcry_sexp_t top_list;
gcry_sexp_t list = NULL;
const char *value;
size_t valuelen;
char *string;
int idx;
int is_v4, is_protected;
int pubkey_algo;
int protect_algo = 0;
char iv[16];
int ivlen = 0;
int s2k_mode = 0;
int s2k_algo = 0;
byte s2k_salt[8];
u32 s2k_count = 0;
size_t npkey, nskey;
gcry_mpi_t skey[10]; /* We support up to 9 parameters. */
u16 desired_csum;
int skeyidx = 0;
struct seckey_info *ski;
top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
if (!top_list)
goto bad_seckey;
list = gcry_sexp_find_token (top_list, "version", 0);
if (!list)
goto bad_seckey;
value = gcry_sexp_nth_data (list, 1, &valuelen);
if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
goto bad_seckey;
is_v4 = (value[0] == '4');
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "protection", 0);
if (!list)
goto bad_seckey;
value = gcry_sexp_nth_data (list, 1, &valuelen);
if (!value)
goto bad_seckey;
if (valuelen == 4 && !memcmp (value, "sha1", 4))
is_protected = 2;
else if (valuelen == 3 && !memcmp (value, "sum", 3))
is_protected = 1;
else if (valuelen == 4 && !memcmp (value, "none", 4))
is_protected = 0;
else
goto bad_seckey;
if (is_protected)
{
string = gcry_sexp_nth_string (list, 2);
if (!string)
goto bad_seckey;
protect_algo = gcry_cipher_map_name (string);
xfree (string);
value = gcry_sexp_nth_data (list, 3, &valuelen);
if (!value || !valuelen || valuelen > sizeof iv)
goto bad_seckey;
memcpy (iv, value, valuelen);
ivlen = valuelen;
string = gcry_sexp_nth_string (list, 4);
if (!string)
goto bad_seckey;
s2k_mode = strtol (string, NULL, 10);
xfree (string);
string = gcry_sexp_nth_string (list, 5);
if (!string)
goto bad_seckey;
s2k_algo = gcry_md_map_name (string);
xfree (string);
value = gcry_sexp_nth_data (list, 6, &valuelen);
if (!value || !valuelen || valuelen > sizeof s2k_salt)
goto bad_seckey;
memcpy (s2k_salt, value, valuelen);
string = gcry_sexp_nth_string (list, 7);
if (!string)
goto bad_seckey;
s2k_count = strtoul (string, NULL, 10);
xfree (string);
}
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "algo", 0);
if (!list)
goto bad_seckey;
string = gcry_sexp_nth_string (list, 1);
if (!string)
goto bad_seckey;
pubkey_algo = gcry_pk_map_name (string);
xfree (string);
if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
|| gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
|| !npkey || npkey >= nskey || nskey > PUBKEY_MAX_NSKEY)
goto bad_seckey;
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "skey", 0);
if (!list)
goto bad_seckey;
for (idx=0;;)
{
int is_enc;
value = gcry_sexp_nth_data (list, ++idx, &valuelen);
if (!value && skeyidx >= npkey)
break; /* Ready. */
/* Check for too many parameters. Note that depending on the
protection mode and version number we may see less than NSKEY
(but at least NPKEY+1) parameters. */
if (idx >= 2*nskey)
goto bad_seckey;
if (skeyidx >= DIM (skey)-1)
goto bad_seckey;
if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
goto bad_seckey;
is_enc = (value[0] == 'e');
value = gcry_sexp_nth_data (list, ++idx, &valuelen);
if (!value || !valuelen)
goto bad_seckey;
if (is_enc)
{
void *p = xtrymalloc (valuelen);
if (!p)
goto outofmem;
memcpy (p, value, valuelen);
skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
if (!skey[skeyidx])
goto outofmem;
}
else
{
if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
value, valuelen, NULL))
goto bad_seckey;
}
skeyidx++;
}
skey[skeyidx++] = NULL;
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "csum", 0);
if (list)
{
string = gcry_sexp_nth_string (list, 1);
if (!string)
goto bad_seckey;
desired_csum = strtoul (string, NULL, 10);
xfree (string);
}
else
desired_csum = 0;
gcry_sexp_release (list); list = NULL;
gcry_sexp_release (top_list); top_list = NULL;
/* log_debug ("XXX is_v4=%d\n", is_v4); */
/* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */
/* log_debug ("XXX is_protected=%d\n", is_protected); */
/* log_debug ("XXX protect_algo=%d\n", protect_algo); */
/* log_printhex ("XXX iv", iv, ivlen); */
/* log_debug ("XXX ivlen=%d\n", ivlen); */
/* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */
/* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */
/* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */
/* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */
/* for (idx=0; skey[idx]; idx++) */
/* { */
/* int is_enc = gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE); */
/* log_info ("XXX skey[%d]%s:", idx, is_enc? " (enc)":""); */
/* if (is_enc) */
/* { */
/* void *p; */
/* unsigned int nbits; */
/* p = gcry_mpi_get_opaque (skey[idx], &nbits); */
/* log_printhex (NULL, p, (nbits+7)/8); */
/* } */
/* else */
/* gcry_mpi_dump (skey[idx]); */
/* log_printf ("\n"); */
/* } */
if (!is_v4 || is_protected != 2 )
{
/* We only support the v4 format and a SHA-1 checksum. */
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
goto leave;
}
/* Do some sanity checks. */
if (s2k_count <= 1024)
{
/* The count must be larger so that encode_s2k_iterations does
not fall into a backward compatibility mode. */
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
if (canon_pubkey_algo (pubkey_algo) != canon_pubkey_algo (pk->pubkey_algo))
{
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
goto leave;
}
err = openpgp_cipher_test_algo (protect_algo);
if (err)
goto leave;
err = openpgp_md_test_algo (s2k_algo);
if (err)
goto leave;
/* Check that the public key parameters match. */
for (idx=0; idx < npkey; idx++)
if (gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
|| gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)
|| gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
{
err = gpg_error (GPG_ERR_BAD_PUBKEY);
goto leave;
}
/* Check that the first secret key parameter in SKEY is encrypted
and that there are no more secret key parameters. The latter is
guaranteed by the v4 packet format. */
if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE))
goto bad_seckey;
if (npkey+1 < DIM (skey) && skey[npkey+1])
goto bad_seckey;
/* Check that the secret key parameters in PK are all set to NULL. */
for (idx=npkey; idx < nskey; idx++)
if (pk->pkey[idx])
goto bad_seckey;
/* Now build the protection info. */
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
if (!ski)
{
err = gpg_error_from_syserror ();
goto leave;
}
ski->is_protected = 1;
ski->sha1chk = 1;
ski->algo = protect_algo;
ski->s2k.mode = s2k_mode;
ski->s2k.hash_algo = s2k_algo;
assert (sizeof ski->s2k.salt == sizeof s2k_salt);
memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
ski->s2k.count = encode_s2k_iterations (s2k_count);
assert (ivlen <= sizeof ski->iv);
memcpy (ski->iv, iv, ivlen);
ski->ivlen = ivlen;
/* Store the protected secret key parameter. */
pk->pkey[npkey] = skey[npkey];
skey[npkey] = NULL;
/* That's it. */
leave:
gcry_sexp_release (list);
gcry_sexp_release (top_list);
for (idx=0; idx < skeyidx; idx++)
gcry_mpi_release (skey[idx]);
return err;
bad_seckey:
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
outofmem:
err = gpg_error (GPG_ERR_ENOMEM);
goto leave;
}
/* Export the keys identified by the list of strings in USERS to the
stream OUT. If Secret is false public keys will be exported. With
secret true secret keys will be exported; in this case 1 means the
entire secret keyblock and 2 only the subkeys. OPTIONS are the
export options to apply. If KEYBLOCK_OUT is not NULL, AND the exit
code is zero, a pointer to the first keyblock found and exported
will be stored at this address; no other keyblocks are exported in
this case. The caller must free it the returned keyblock. If any
key has been exported true is stored at ANY. */
static int
do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
kbnode_t *keyblock_out, unsigned int options, int *any) kbnode_t *keyblock_out, unsigned int options, int *any)
{ {
gpg_error_t err = 0; gpg_error_t err = 0;
@ -292,6 +611,7 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
KEYDB_HANDLE kdbhd; KEYDB_HANDLE kdbhd;
strlist_t sl; strlist_t sl;
int indent = 0; int indent = 0;
gcry_cipher_hd_t cipherhd = NULL;
*any = 0; *any = 0;
init_packet (&pkt); init_packet (&pkt);
@ -330,21 +650,51 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
if (secret) if (secret)
{ {
log_error (_("exporting secret keys not allowed\n")); log_error (_("exporting secret keys not allowed\n"));
err = G10ERR_GENERAL; err = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave; goto leave;
} }
#endif #endif
/* For secret key export we need to setup a decryption context. */
if (secret)
{
void *kek = NULL;
size_t keklen;
err = agent_keywrap_key (ctrl, 1, &kek, &keklen);
if (err)
{
log_error ("error getting the KEK: %s\n", gpg_strerror (err));
goto leave;
}
/* Prepare a cipher context. */
err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
GCRY_CIPHER_MODE_AESWRAP, 0);
if (!err)
err = gcry_cipher_setkey (cipherhd, kek, keklen);
if (err)
{
log_error ("error setting up an encryption context: %s\n",
gpg_strerror (err));
goto leave;
}
xfree (kek);
kek = NULL;
}
while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex))) while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
{ {
int sha1_warned = 0;
int skip_until_subkey = 0; int skip_until_subkey = 0;
u32 keyid[2]; u32 keyid[2];
PKT_public_key *pk;
if (!users) if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT; desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* Read the keyblock. */ /* Read the keyblock. */
release_kbnode (keyblock);
keyblock = NULL;
err = keydb_get_keyblock (kdbhd, &keyblock); err = keydb_get_keyblock (kdbhd, &keyblock);
if (err) if (err)
{ {
@ -352,60 +702,57 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
goto leave; goto leave;
} }
if ((node=find_kbnode(keyblock, PKT_SECRET_KEY))) node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
if (!node)
{ {
PKT_public_key *pk = node->pkt->pkt.public_key; log_error ("public key packet not found in keyblock - skipped\n");
continue;
}
pk = node->pkt->pkt.public_key;
keyid_from_pk (pk, keyid);
keyid_from_pk (pk, keyid); /* If a secret key export is required we need to check whether
we have a secret key at all and if so create the seckey_info
structure. */
if (secret)
{
if (agent_probe_any_secret_key (ctrl, keyblock))
continue; /* No secret key (neither primary nor subkey). */
/* We can't apply GNU mode 1001 on an unprotected key. */ /* No v3 keys with GNU mode 1001. */
if( secret == 2 if (secret == 2 && pk->version == 3)
&& pk->seckey_info && !pk->seckey_info->is_protected )
{ {
log_info (_("key %s: not protected - skipped\n"), log_info (_("key %s: PGP 2.x style key - skipped\n"),
keystr (keyid)); keystr (keyid));
continue; continue;
} }
/* No v3 keys with GNU mode 1001. */ /* The agent does not yet allow to export v3 packets. It is
if( secret == 2 && pk->version == 3 ) actually questionable whether we should allow them at
all. */
if (pk->version == 3)
{ {
log_info(_("key %s: PGP 2.x style key - skipped\n"), log_info ("key %s: PGP 2.x style key (v3) export "
keystr (keyid)); "not yet supported - skipped\n", keystr (keyid));
continue; continue;
} }
}
/* It does not make sense to export a key with a primary /* Always do the cleaning on the public key part if requested.
key on card using a non-key stub. We simply skip those Note that we don't yet set this option if we are exporting
keys when used with --export-secret-subkeys. */ secret keys. Note that both export-clean and export-minimal
if (secret == 2 only apply to UID sigs (0x10, 0x11, 0x12, and 0x13). A
&& pk->seckey_info && pk->seckey_info->is_protected designated revocation is never stripped, even with
&& pk->seckey_info->s2k.mode == 1002 ) export-minimal set. */
{ if ((options & EXPORT_CLEAN))
log_info(_("key %s: key material on-card - skipped\n"), clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
keystr (keyid));
continue;
}
}
else
{
/* It's a public key export, so do the cleaning if
requested. Note that both export-clean and
export-minimal only apply to UID sigs (0x10, 0x11, 0x12,
and 0x13). A designated revocation is never stripped,
even with export-minimal set. */
if ( (options & EXPORT_CLEAN) )
clean_key (keyblock, opt.verbose, options&EXPORT_MINIMAL,
NULL, NULL);
}
/* And write it. */ /* And write it. */
for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); ) for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{ {
if (skip_until_subkey) if (skip_until_subkey)
{ {
if (node->pkt->pkttype==PKT_PUBLIC_SUBKEY if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)
skip_until_subkey = 0; skip_until_subkey = 0;
else else
continue; continue;
@ -425,8 +772,7 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
(plus the primary key, if the user didn't specifically (plus the primary key, if the user didn't specifically
request it). */ request it). */
if (desc[descindex].exact if (desc[descindex].exact
&& (node->pkt->pkttype == PKT_PUBLIC_SUBKEY && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|| node->pkt->pkttype == PKT_SECRET_SUBKEY))
{ {
if (!exact_subkey_match_p (desc+descindex, node)) if (!exact_subkey_match_p (desc+descindex, node))
{ {
@ -440,9 +786,9 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
skip in any case if the key is in that list. skip in any case if the key is in that list.
We need this whole mess because the import We need this whole mess because the import
function is not able to merge secret keys and function of GnuPG < 2.1 is not able to merge
thus it is useless to output them as two separate secret keys and thus it is useless to output them
keys and have import merge them. */ as two separate keys and have import merge them. */
if (subkey_in_list_p (subkey_list, node)) if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */ skip_until_subkey = 1; /* Already processed this one. */
else else
@ -508,88 +854,181 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
continue; continue;
} }
if (secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY) if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
{ {
/* We don't want to export the secret parts of the u32 subkidbuf[2], *subkid;
* primary key, this is done by temporary switching to char *hexgrip, *serialno;
* GNU protection mode 1001. */
int save_mode = node->pkt->pkt.public_key->seckey_info->s2k.mode; pk = node->pkt->pkt.public_key;
node->pkt->pkt.public_key->seckey_info->s2k.mode = 1001; if (node->pkt->pkttype == PKT_PUBLIC_KEY)
if ((options&EXPORT_SEXP_FORMAT)) subkid = NULL;
err = build_sexp (out, node->pkt, &indent);
else else
err = build_packet (out, node->pkt); {
node->pkt->pkt.public_key->seckey_info->s2k.mode = save_mode; keyid_from_pk (pk, subkidbuf);
} subkid = subkidbuf;
else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY }
&& (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
{
/* If the subkey is protected reset the passphrase to
export an unprotected subkey. This feature is useful
in cases of a subkey copied to an unattended machine
where a passphrase is not required. */
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
goto leave;
#warning We need to implement this
/* PKT_secret_key *sk_save, *sk; */
/* sk_save = node->pkt->pkt.secret_key; */ if (pk->seckey_info)
/* sk = copy_secret_key (NULL, sk_save); */ {
/* node->pkt->pkt.secret_key = sk; */ log_error ("key %s: oops: seckey_info already set"
" - skipped\n", keystr_with_sub (keyid, subkid));
skip_until_subkey = 1;
continue;
}
err = hexkeygrip_from_pk (pk, &hexgrip);
if (err)
{
log_error ("key %s: error computing keygrip: %s"
" - skipped\n", keystr_with_sub (keyid, subkid),
gpg_strerror (err));
skip_until_subkey = 1;
err = 0;
continue;
}
/* log_info (_("about to export an unprotected subkey\n")); */ if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
/* switch (is_secret_key_protected (sk)) */ {
/* { */ /* We are asked not to export the secret parts of
/* case -1: */ the primary key. Make up an error code to create
/* err = gpg_error (GPG_ERR_PUBKEY_ALGO); */ the stub. */
/* break; */ err = GPG_ERR_NOT_FOUND;
/* case 0: */ serialno = NULL;
/* break; */ }
/* default: */ else
/* if (sk->protect.s2k.mode == 1001) */ err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
/* ; /\* No secret parts. *\/ */
/* else if( sk->protect.s2k.mode == 1002 ) */
/* ; /\* Card key stub. *\/ */
/* else */
/* { */
/* /\* err = check_secret_key( sk, 0 ); *\/ */
/* } */
/* break; */
/* } */
/* if (err) */
/* { */
/* node->pkt->pkt.secret_key = sk_save; */
/* free_secret_key (sk); */
/* log_error (_("failed to unprotect the subkey: %s\n"), */
/* g10_errstr (rc)); */
/* goto leave; */
/* } */
/* if ((options&EXPORT_SEXP_FORMAT)) */ if ((!err && serialno)
/* err = build_sexp (out, node->pkt, &indent); */ && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
/* else */ {
/* err = build_packet (out, node->pkt); */ /* It does not make sense to export a key with its
primary key on card using a non-key stub. Thus
we skip those keys when used with
--export-secret-subkeys. */
log_info (_("key %s: key material on-card - skipped\n"),
keystr_with_sub (keyid, subkid));
skip_until_subkey = 1;
}
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
|| (!err && serialno))
{
/* Create a key stub. */
struct seckey_info *ski;
const char *s;
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
if (!ski)
{
err = gpg_error_from_syserror ();
xfree (hexgrip);
goto leave;
}
/* node->pkt->pkt.secret_key = sk_save; */ ski->is_protected = 1;
/* free_secret_key (sk); */ if (err)
ski->s2k.mode = 1001; /* GNU dummy (no secret key). */
else
{
ski->s2k.mode = 1002; /* GNU-divert-to-card. */
for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
ski->ivlen++, s += 2)
ski->iv[ski->ivlen] = xtoi_2 (s);
}
if ((options&EXPORT_SEXP_FORMAT))
err = build_sexp (out, node->pkt, &indent);
else
err = build_packet (out, node->pkt);
}
else if (!err)
{
/* FIXME: Move this spaghetti code into a separate
function. */
unsigned char *wrappedkey = NULL;
size_t wrappedkeylen;
unsigned char *key = NULL;
size_t keylen, realkeylen;
gcry_sexp_t s_skey;
if (opt.verbose)
log_info ("key %s: asking agent for the secret parts\n",
keystr_with_sub (keyid, subkid));
err = agent_export_key (ctrl, hexgrip, "Key foo", NULL,
&wrappedkey, &wrappedkeylen);
if (err)
goto unwraperror;
if (wrappedkeylen < 24)
{
err = gpg_error (GPG_ERR_INV_LENGTH);
goto unwraperror;
}
keylen = wrappedkeylen - 8;
key = xtrymalloc_secure (keylen);
if (!key)
{
err = gpg_error_from_syserror ();
goto unwraperror;
}
err = gcry_cipher_decrypt (cipherhd, key, keylen,
wrappedkey, wrappedkeylen);
if (err)
goto unwraperror;
realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
if (!realkeylen)
goto unwraperror; /* Invalid csexp. */
err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
xfree (key);
key = NULL;
if (err)
goto unwraperror;
err = transfer_format_to_openpgp (s_skey, pk);
gcry_sexp_release (s_skey);
if (err)
goto unwraperror;
if ((options&EXPORT_SEXP_FORMAT))
err = build_sexp (out, node->pkt, &indent);
else
err = build_packet (out, node->pkt);
goto unwraperror_leave;
unwraperror:
xfree (wrappedkey);
xfree (key);
if (err)
{
log_error ("key %s: error receiving key from agent:"
" %s%s\n",
keystr_with_sub (keyid, subkid),
gpg_strerror (err),
gpg_err_code (err) == GPG_ERR_FULLY_CANCELED?
"":_(" - skipped"));
if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
goto leave;
skip_until_subkey = 1;
err = 0;
}
unwraperror_leave:
;
}
else
{
log_error ("key %s: error getting keyinfo from agent: %s"
" - skipped\n", keystr_with_sub (keyid, subkid),
gpg_strerror (err));
skip_until_subkey = 1;
err = 0;
}
xfree (pk->seckey_info);
pk->seckey_info = NULL;
xfree (hexgrip);
} }
else else
{ {
/* Warn the user if the secret key or any of the secret
subkeys are protected with SHA1 and we have
simple_sk_checksum set. */
if (!sha1_warned && opt.simple_sk_checksum &&
(node->pkt->pkttype == PKT_SECRET_KEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
&& node->pkt->pkt.public_key->seckey_info->sha1chk)
{
/* I hope this warning doesn't confuse people. */
log_info(_("WARNING: secret key %s does not have a "
"simple SK checksum\n"), keystr (keyid));
sha1_warned = 1;
}
if ((options&EXPORT_SEXP_FORMAT)) if ((options&EXPORT_SEXP_FORMAT))
err = build_sexp (out, node->pkt, &indent); err = build_sexp (out, node->pkt, &indent);
else else
@ -602,6 +1041,9 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
node->pkt->pkttype, gpg_strerror (err)); node->pkt->pkttype, gpg_strerror (err));
goto leave; goto leave;
} }
if (!skip_until_subkey)
*any = 1;
} }
if ((options&EXPORT_SEXP_FORMAT) && indent) if ((options&EXPORT_SEXP_FORMAT) && indent)
@ -611,10 +1053,9 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
iobuf_put (out, '\n'); iobuf_put (out, '\n');
} }
++*any; if (keyblock_out)
if(keyblock_out)
{ {
*keyblock_out=keyblock; *keyblock_out = keyblock;
break; break;
} }
} }
@ -624,10 +1065,11 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
iobuf_put (out, ')'); iobuf_put (out, ')');
iobuf_put (out, '\n'); iobuf_put (out, '\n');
} }
if( err == -1 ) if (err == -1)
err = 0; err = 0;
leave: leave:
gcry_cipher_close (cipherhd);
release_subkey_list (subkey_list); release_subkey_list (subkey_list);
xfree(desc); xfree(desc);
keydb_release (kdbhd); keydb_release (kdbhd);
@ -672,6 +1114,10 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
static int static int
build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent) build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
{ {
(void)out;
(void)pkt;
(void)indent;
/* FIXME: Not yet implemented. */ /* FIXME: Not yet implemented. */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
/* PKT_secret_key *sk = pkt->pkt.secret_key; */ /* PKT_secret_key *sk = pkt->pkt.secret_key; */
@ -759,4 +1205,3 @@ build_sexp (iobuf_t out, PACKET *pkt, int *indent)
} }
return rc; return rc;
} }

View File

@ -25,9 +25,9 @@
#include <assert.h> #include <assert.h>
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "../common/iobuf.h" #include "../common/iobuf.h"
#include "util.h"
#include "cipher.h" #include "cipher.h"
#include "options.h" #include "options.h"

View File

@ -676,7 +676,7 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
to import the key via the online mechanisms defined by to import the key via the online mechanisms defined by
--auto-key-locate. */ --auto-key-locate. */
int int
get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk, get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
const char *name, KBNODE * ret_keyblock, const char *name, KBNODE * ret_keyblock,
KEYDB_HANDLE * ret_kdbhd, int include_unusable, int no_akl) KEYDB_HANDLE * ret_kdbhd, int include_unusable, int no_akl)
{ {
@ -770,21 +770,21 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk,
case AKL_CERT: case AKL_CERT:
mechanism = "DNS CERT"; mechanism = "DNS CERT";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_cert (name, &fpr, &fpr_len); rc = keyserver_import_cert (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
break; break;
case AKL_PKA: case AKL_PKA:
mechanism = "PKA"; mechanism = "PKA";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_pka (name, &fpr, &fpr_len); rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
break; break;
case AKL_LDAP: case AKL_LDAP:
mechanism = "LDAP"; mechanism = "LDAP";
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_ldap (name, &fpr, &fpr_len); rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
break; break;
@ -797,9 +797,8 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk,
{ {
mechanism = opt.keyserver->uri; mechanism = opt.keyserver->uri;
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc = rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
keyserver_import_name (name, &fpr, &fpr_len, opt.keyserver);
opt.keyserver);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
} }
else else
@ -816,7 +815,8 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk,
mechanism = akl->spec->uri; mechanism = akl->spec->uri;
keyserver = keyserver_match (akl->spec); keyserver = keyserver_match (akl->spec);
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
rc = keyserver_import_name (name, &fpr, &fpr_len, keyserver); rc = keyserver_import_name (ctrl,
name, &fpr, &fpr_len, keyserver);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
} }
break; break;

View File

@ -37,9 +37,9 @@
#define INCLUDED_BY_MAIN_MODULE 1 #define INCLUDED_BY_MAIN_MODULE 1
#include "gpg.h" #include "gpg.h"
#include <assuan.h> #include <assuan.h>
#include "packet.h"
#include "../common/iobuf.h" #include "../common/iobuf.h"
#include "util.h" #include "util.h"
#include "packet.h"
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "keydb.h" #include "keydb.h"
@ -273,7 +273,6 @@ enum cmd_and_opt_values
oS2KDigest, oS2KDigest,
oS2KCipher, oS2KCipher,
oS2KCount, oS2KCount,
oSimpleSKChecksum,
oDisplayCharset, oDisplayCharset,
oNotDashEscaped, oNotDashEscaped,
oEscapeFrom, oEscapeFrom,
@ -565,7 +564,6 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oS2KDigest, "s2k-digest-algo", "@"), ARGPARSE_s_s (oS2KDigest, "s2k-digest-algo", "@"),
ARGPARSE_s_s (oS2KCipher, "s2k-cipher-algo", "@"), ARGPARSE_s_s (oS2KCipher, "s2k-cipher-algo", "@"),
ARGPARSE_s_i (oS2KCount, "s2k-count", "@"), ARGPARSE_s_i (oS2KCount, "s2k-count", "@"),
ARGPARSE_s_n (oSimpleSKChecksum, "simple-sk-checksum", "@"),
ARGPARSE_s_s (oCipherAlgo, "cipher-algo", "@"), ARGPARSE_s_s (oCipherAlgo, "cipher-algo", "@"),
ARGPARSE_s_s (oDigestAlgo, "digest-algo", "@"), ARGPARSE_s_s (oDigestAlgo, "digest-algo", "@"),
ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"), ARGPARSE_s_s (oCertDigestAlgo, "cert-digest-algo", "@"),
@ -2504,7 +2502,6 @@ main (int argc, char **argv)
else else
opt.s2k_count = 0; /* Auto-calibrate when needed. */ opt.s2k_count = 0; /* Auto-calibrate when needed. */
break; break;
case oSimpleSKChecksum: opt.simple_sk_checksum = 1; break;
case oNoEncryptTo: opt.no_encrypt_to = 1; break; case oNoEncryptTo: opt.no_encrypt_to = 1; break;
case oEncryptTo: /* store the recipient in the second list */ case oEncryptTo: /* store the recipient in the second list */
sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings ); sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
@ -2966,8 +2963,8 @@ main (int argc, char **argv)
} }
} }
if (configfp)
if( configfp ) { {
fclose( configfp ); fclose( configfp );
configfp = NULL; configfp = NULL;
/* Remember the first config file name. */ /* Remember the first config file name. */
@ -2977,10 +2974,10 @@ main (int argc, char **argv)
xfree(configname); xfree(configname);
configname = NULL; configname = NULL;
goto next_pass; goto next_pass;
} }
xfree( configname ); configname = NULL; xfree(configname); configname = NULL;
if( log_get_errorcount(0) ) if (log_get_errorcount (0))
g10_exit(2); g10_exit(2);
/* The command --gpgconf-list is pretty simple and may be called /* The command --gpgconf-list is pretty simple and may be called
directly after the option parsing. */ directly after the option parsing. */
@ -3405,7 +3402,7 @@ main (int argc, char **argv)
if(fname && utf8_strings) if(fname && utf8_strings)
opt.flags.utf8_filename=1; opt.flags.utf8_filename=1;
ctrl = xtrycalloc (1, sizeof *ctrl); ctrl = xcalloc (1, sizeof *ctrl);
gpg_init_default_ctrl (ctrl); gpg_init_default_ctrl (ctrl);
switch( cmd ) { switch( cmd ) {
@ -3463,12 +3460,12 @@ main (int argc, char **argv)
case aEncr: /* encrypt the given file */ case aEncr: /* encrypt the given file */
if(multifile) if(multifile)
encrypt_crypt_files(argc, argv, remusr); encrypt_crypt_files (ctrl, argc, argv, remusr);
else else
{ {
if( argc > 1 ) if( argc > 1 )
wrong_args(_("--encrypt [filename]")); wrong_args(_("--encrypt [filename]"));
if( (rc = encrypt_crypt (-1, fname, remusr, 0, NULL, -1)) ) if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 0, NULL, -1)) )
log_error("%s: encryption failed: %s\n", log_error("%s: encryption failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) ); print_fname_stdin(fname), g10_errstr(rc) );
} }
@ -3489,7 +3486,7 @@ main (int argc, char **argv)
" while in %s mode\n"),compliance_option_string()); " while in %s mode\n"),compliance_option_string());
else else
{ {
if( (rc = encrypt_crypt (-1, fname, remusr, 1, NULL, -1)) ) if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 1, NULL, -1)) )
log_error("%s: encryption failed: %s\n", log_error("%s: encryption failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) ); print_fname_stdin(fname), g10_errstr(rc) );
} }
@ -3509,7 +3506,7 @@ main (int argc, char **argv)
strcpy(sl->d, fname); strcpy(sl->d, fname);
} }
} }
if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) ) if( (rc = sign_file (ctrl, sl, detached_sig, locusr, 0, NULL, NULL)) )
log_error("signing failed: %s\n", g10_errstr(rc) ); log_error("signing failed: %s\n", g10_errstr(rc) );
free_strlist(sl); free_strlist(sl);
break; break;
@ -3523,7 +3520,7 @@ main (int argc, char **argv)
} }
else else
sl = NULL; sl = NULL;
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) ) if ((rc = sign_file (ctrl, sl, detached_sig, locusr, 1, remusr, NULL)))
log_error("%s: sign+encrypt failed: %s\n", log_error("%s: sign+encrypt failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) ); print_fname_stdin(fname), g10_errstr(rc) );
free_strlist(sl); free_strlist(sl);
@ -3547,7 +3544,8 @@ main (int argc, char **argv)
} }
else else
sl = NULL; sl = NULL;
if( (rc = sign_file(sl, detached_sig, locusr, 2, remusr, NULL)) ) if ((rc = sign_file (ctrl, sl, detached_sig, locusr,
2, remusr, NULL)))
log_error("%s: symmetric+sign+encrypt failed: %s\n", log_error("%s: symmetric+sign+encrypt failed: %s\n",
print_fname_stdin(fname), g10_errstr(rc) ); print_fname_stdin(fname), g10_errstr(rc) );
free_strlist(sl); free_strlist(sl);
@ -3572,26 +3570,26 @@ main (int argc, char **argv)
break; break;
case aVerify: case aVerify:
if(multifile) if (multifile)
{ {
if( (rc = verify_files( argc, argv ) )) if ((rc = verify_files (ctrl, argc, argv)))
log_error("verify files failed: %s\n", g10_errstr(rc) ); log_error("verify files failed: %s\n", g10_errstr(rc) );
} }
else else
{ {
if( (rc = verify_signatures( argc, argv ) )) if ((rc = verify_signatures (ctrl, argc, argv)))
log_error("verify signatures failed: %s\n", g10_errstr(rc) ); log_error("verify signatures failed: %s\n", g10_errstr(rc) );
} }
break; break;
case aDecrypt: case aDecrypt:
if(multifile) if (multifile)
decrypt_messages(argc, argv); decrypt_messages (ctrl, argc, argv);
else else
{ {
if( argc > 1 ) if( argc > 1 )
wrong_args(_("--decrypt [filename]")); wrong_args(_("--decrypt [filename]"));
if( (rc = decrypt_message( fname ) )) if( (rc = decrypt_message (ctrl, fname) ))
log_error("decrypt_message failed: %s\n", g10_errstr(rc) ); log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
} }
break; break;
@ -3616,7 +3614,7 @@ main (int argc, char **argv)
append_to_strlist( &sl, "save" ); append_to_strlist( &sl, "save" );
username = make_username( fname ); username = make_username( fname );
keyedit_menu (username, locusr, sl, 0, 0 ); keyedit_menu (ctrl, username, locusr, sl, 0, 0 );
xfree(username); xfree(username);
free_strlist(sl); free_strlist(sl);
break; break;
@ -3629,11 +3627,11 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( argc--, argv++ ; argc; argc--, argv++ ) for( argc--, argv++ ; argc; argc--, argv++ )
append_to_strlist( &sl, *argv ); append_to_strlist( &sl, *argv );
keyedit_menu( username, locusr, sl, 0, 1 ); keyedit_menu (ctrl, username, locusr, sl, 0, 1 );
free_strlist(sl); free_strlist(sl);
} }
else else
keyedit_menu(username, locusr, NULL, 0, 1 ); keyedit_menu (ctrl, username, locusr, NULL, 0, 1 );
xfree(username); xfree(username);
break; break;
@ -3669,21 +3667,21 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list( sl, 0 ); public_key_list (ctrl, sl, 0);
free_strlist(sl); free_strlist(sl);
break; break;
case aListSecretKeys: case aListSecretKeys:
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
secret_key_list( sl ); secret_key_list (ctrl, sl);
free_strlist(sl); free_strlist(sl);
break; break;
case aLocateKeys: case aLocateKeys:
sl = NULL; sl = NULL;
for (; argc; argc--, argv++) for (; argc; argc--, argv++)
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
public_key_list (sl, 1); public_key_list (ctrl, sl, 1);
free_strlist (sl); free_strlist (sl);
break; break;
@ -3718,11 +3716,11 @@ main (int argc, char **argv)
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings ); append_to_strlist2( &sl, *argv, utf8_strings );
if( cmd == aSendKeys ) if( cmd == aSendKeys )
rc=keyserver_export( sl ); rc = keyserver_export (ctrl, sl );
else if( cmd == aRecvKeys ) else if( cmd == aRecvKeys )
rc=keyserver_import( sl ); rc = keyserver_import (ctrl, sl );
else else
rc=export_pubkeys( sl, opt.export_options ); rc = export_pubkeys (ctrl, sl, opt.export_options);
if(rc) if(rc)
{ {
if(cmd==aSendKeys) if(cmd==aSendKeys)
@ -3739,7 +3737,7 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings ); append_to_strlist2( &sl, *argv, utf8_strings );
rc=keyserver_search( sl ); rc = keyserver_search (ctrl, sl);
if(rc) if(rc)
log_error(_("keyserver search failed: %s\n"),g10_errstr(rc)); log_error(_("keyserver search failed: %s\n"),g10_errstr(rc));
free_strlist(sl); free_strlist(sl);
@ -3749,7 +3747,7 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings ); append_to_strlist2( &sl, *argv, utf8_strings );
rc=keyserver_refresh(sl); rc = keyserver_refresh (ctrl, sl);
if(rc) if(rc)
log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc)); log_error(_("keyserver refresh failed: %s\n"),g10_errstr(rc));
free_strlist(sl); free_strlist(sl);
@ -3759,7 +3757,7 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings ); append_to_strlist2( &sl, *argv, utf8_strings );
rc=keyserver_fetch(sl); rc = keyserver_fetch (ctrl, sl);
if(rc) if(rc)
log_error("key fetch failed: %s\n",g10_errstr(rc)); log_error("key fetch failed: %s\n",g10_errstr(rc));
free_strlist(sl); free_strlist(sl);
@ -3769,7 +3767,7 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
export_seckeys( sl ); export_seckeys (ctrl, sl);
free_strlist(sl); free_strlist(sl);
break; break;
@ -3777,7 +3775,7 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for( ; argc; argc--, argv++ ) for( ; argc; argc--, argv++ )
add_to_strlist2( &sl, *argv, utf8_strings ); add_to_strlist2( &sl, *argv, utf8_strings );
export_secsubkeys( sl ); export_secsubkeys (ctrl, sl);
free_strlist(sl); free_strlist(sl);
break; break;
@ -3987,11 +3985,11 @@ main (int argc, char **argv)
sl = NULL; sl = NULL;
for (argc--, argv++ ; argc; argc--, argv++) for (argc--, argv++ ; argc; argc--, argv++)
append_to_strlist (&sl, *argv); append_to_strlist (&sl, *argv);
card_edit (sl); card_edit (ctrl, sl);
free_strlist (sl); free_strlist (sl);
} }
else else
card_edit (NULL); card_edit (ctrl, NULL);
break; break;
case aChangePIN: case aChangePIN:
@ -4045,7 +4043,7 @@ main (int argc, char **argv)
set_packet_list_mode(1); set_packet_list_mode(1);
opt.list_packets=1; opt.list_packets=1;
} }
rc = proc_packets(NULL, a ); rc = proc_packets (ctrl, NULL, a );
if( rc ) if( rc )
log_error("processing message failed: %s\n", g10_errstr(rc) ); log_error("processing message failed: %s\n", g10_errstr(rc) );
iobuf_close(a); iobuf_close(a);

View File

@ -35,9 +35,9 @@
#define INCLUDED_BY_MAIN_MODULE 1 #define INCLUDED_BY_MAIN_MODULE 1
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "iobuf.h" #include "iobuf.h"
#include "util.h"
#include "main.h" #include "main.h"
#include "options.h" #include "options.h"
#include "keydb.h" #include "keydb.h"
@ -140,8 +140,9 @@ main( int argc, char **argv )
ARGPARSE_ARGS pargs; ARGPARSE_ARGS pargs;
int rc=0; int rc=0;
strlist_t sl; strlist_t sl;
strlist_t nrings=NULL; strlist_t nrings = NULL;
unsigned configlineno; unsigned configlineno;
ctrl_t ctrl;
set_strusage (my_strusage); set_strusage (my_strusage);
log_set_prefix ("gpgv", 1); log_set_prefix ("gpgv", 1);
@ -201,10 +202,14 @@ main( int argc, char **argv )
keydb_add_resource (sl->d, 8); keydb_add_resource (sl->d, 8);
FREE_STRLIST (nrings); FREE_STRLIST (nrings);
ctrl = xcalloc (1, sizeof *ctrl);
if ( (rc = verify_signatures( argc, argv ) )) if ((rc = verify_signatures (ctrl, argc, argv)))
log_error("verify signatures failed: %s\n", g10_errstr(rc) ); log_error("verify signatures failed: %s\n", g10_errstr(rc) );
xfree (ctrl);
/* cleanup */ /* cleanup */
g10_exit (0); g10_exit (0);
return 8; /*NOTREACHED*/ return 8; /*NOTREACHED*/
@ -377,8 +382,9 @@ get_override_session_key (DEK *dek, const char *string)
/* Stub: */ /* Stub: */
int int
decrypt_data (void *procctx, PKT_encrypted *ed, DEK *dek) decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
{ {
(void)ctrl;
(void)procctx; (void)procctx;
(void)ed; (void)ed;
(void)dek; (void)dek;

View File

@ -64,10 +64,11 @@ static int import (ctrl_t ctrl,
IOBUF inp, const char* fname, struct stats_s *stats, IOBUF inp, const char* fname, struct stats_s *stats,
unsigned char **fpr, size_t *fpr_len, unsigned int options); unsigned char **fpr, size_t *fpr_len, unsigned int options);
static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root ); static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
static void revocation_present(KBNODE keyblock); static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats, static int import_one (ctrl_t ctrl,
unsigned char **fpr,size_t *fpr_len, const char *fname, KBNODE keyblock,struct stats_s *stats,
unsigned int options,int from_sk); unsigned char **fpr,size_t *fpr_len,
unsigned int options,int from_sk);
static int import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock, static int import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
struct stats_s *stats, unsigned int options); struct stats_s *stats, unsigned int options);
static int import_revoke_cert( const char *fname, KBNODE node, static int import_revoke_cert( const char *fname, KBNODE node,
@ -265,7 +266,8 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) { while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
rc = import_one( fname, keyblock, stats, fpr, fpr_len, options, 0); rc = import_one (ctrl, fname, keyblock,
stats, fpr, fpr_len, options, 0);
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
rc = import_secret_one (ctrl, fname, keyblock, stats, options); rc = import_secret_one (ctrl, fname, keyblock, stats, options);
else if( keyblock->pkt->pkttype == PKT_SIGNATURE else if( keyblock->pkt->pkttype == PKT_SIGNATURE
@ -614,9 +616,9 @@ check_prefs_warning(PKT_public_key *pk)
} }
static void static void
check_prefs(KBNODE keyblock) check_prefs (ctrl_t ctrl, kbnode_t keyblock)
{ {
KBNODE node; kbnode_t node;
PKT_public_key *pk; PKT_public_key *pk;
int problem=0; int problem=0;
@ -711,7 +713,7 @@ check_prefs(KBNODE keyblock)
append_to_strlist(&sl,"updpref"); append_to_strlist(&sl,"updpref");
append_to_strlist(&sl,"save"); append_to_strlist(&sl,"save");
keyedit_menu( username, locusr, sl, 1, 1 ); keyedit_menu (ctrl, username, locusr, sl, 1, 1 );
free_strlist(sl); free_strlist(sl);
free_strlist(locusr); free_strlist(locusr);
} }
@ -728,7 +730,8 @@ check_prefs(KBNODE keyblock)
* which called gpg. * which called gpg.
*/ */
static int static int
import_one( const char *fname, KBNODE keyblock, struct stats_s *stats, import_one (ctrl_t ctrl,
const char *fname, KBNODE keyblock, struct stats_s *stats,
unsigned char **fpr,size_t *fpr_len,unsigned int options, unsigned char **fpr,size_t *fpr_len,unsigned int options,
int from_sk ) int from_sk )
{ {
@ -1060,15 +1063,15 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
if (mod_key) if (mod_key)
{ {
revocation_present (keyblock_orig); revocation_present (ctrl, keyblock_orig);
if (!from_sk && have_secret_key_with_kid (keyid)) if (!from_sk && have_secret_key_with_kid (keyid))
check_prefs (keyblock_orig); check_prefs (ctrl, keyblock_orig);
} }
else if (new_key) else if (new_key)
{ {
revocation_present (keyblock); revocation_present (ctrl, keyblock);
if (!from_sk && have_secret_key_with_kid (keyid)) if (!from_sk && have_secret_key_with_kid (keyid))
check_prefs (keyblock); check_prefs (ctrl, keyblock);
} }
release_kbnode( keyblock_orig ); release_kbnode( keyblock_orig );
@ -1425,7 +1428,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
keystr_from_pk (pk)); keystr_from_pk (pk));
else else
{ {
import_one (fname, pub_keyblock, stats, import_one (ctrl, fname, pub_keyblock, stats,
NULL, NULL, opt.import_options, 1); NULL, NULL, opt.import_options, 1);
/* Fixme: We should check for an invalid keyblock and /* Fixme: We should check for an invalid keyblock and
cancel the secret key import in this case. */ cancel the secret key import in this case. */
@ -1448,7 +1451,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
keystr_from_pk (pk)); keystr_from_pk (pk));
if (is_status_enabled ()) if (is_status_enabled ())
print_import_ok (pk, 1|16); print_import_ok (pk, 1|16);
check_prefs (node); check_prefs (ctrl, node);
} }
release_kbnode (node); release_kbnode (node);
} }
@ -2051,10 +2054,10 @@ collapse_uids( KBNODE *keyblock )
present. This may be called without the benefit of merge_xxxx so present. This may be called without the benefit of merge_xxxx so
you can't rely on pk->revkey and friends. */ you can't rely on pk->revkey and friends. */
static void static void
revocation_present(KBNODE keyblock) revocation_present (ctrl_t ctrl, kbnode_t keyblock)
{ {
KBNODE onode,inode; kbnode_t onode, inode;
PKT_public_key *pk=keyblock->pkt->pkt.public_key; PKT_public_key *pk = keyblock->pkt->pkt.public_key;
for(onode=keyblock->next;onode;onode=onode->next) for(onode=keyblock->next;onode;onode=onode->next)
{ {
@ -2106,9 +2109,10 @@ revocation_present(KBNODE keyblock)
log_info(_("WARNING: key %s may be revoked:" log_info(_("WARNING: key %s may be revoked:"
" fetching revocation key %s\n"), " fetching revocation key %s\n"),
tempkeystr,keystr(keyid)); tempkeystr,keystr(keyid));
keyserver_import_fprint(sig->revkey[idx]->fpr, keyserver_import_fprint (ctrl,
MAX_FINGERPRINT_LEN, sig->revkey[idx]->fpr,
opt.keyserver); MAX_FINGERPRINT_LEN,
opt.keyserver);
/* Do we have it now? */ /* Do we have it now? */
rc=get_pubkey_byfprint_fast (NULL, rc=get_pubkey_byfprint_fast (NULL,

View File

@ -157,8 +157,10 @@ void show_revocation_reason( PKT_public_key *pk, int mode );
int check_signatures_trust( PKT_signature *sig ); int check_signatures_trust( PKT_signature *sig );
void release_pk_list (PK_LIST pk_list); void release_pk_list (PK_LIST pk_list);
int build_pk_list (strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use); int build_pk_list (ctrl_t ctrl,
gpg_error_t find_and_check_key (const char *name, unsigned int use, strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use);
gpg_error_t find_and_check_key (ctrl_t ctrl,
const char *name, unsigned int use,
int mark_hidden, pk_list_t *pk_list_addr); int mark_hidden, pk_list_t *pk_list_addr);
int algo_available( preftype_t preftype, int algo, int algo_available( preftype_t preftype, int algo,
@ -204,7 +206,8 @@ void getkey_disable_caches(void);
int get_pubkey( PKT_public_key *pk, u32 *keyid ); int get_pubkey( PKT_public_key *pk, u32 *keyid );
int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid ); int get_pubkey_fast ( PKT_public_key *pk, u32 *keyid );
KBNODE get_pubkeyblock( u32 *keyid ); KBNODE get_pubkeyblock( u32 *keyid );
int get_pubkey_byname (GETKEY_CTX *rx, PKT_public_key *pk, const char *name, int get_pubkey_byname (ctrl_t ctrl,
GETKEY_CTX *rx, PKT_public_key *pk, const char *name,
KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd, KBNODE *ret_keyblock, KEYDB_HANDLE *ret_kdbhd,
int include_unusable, int no_akl ); int include_unusable, int no_akl );
int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk, int get_pubkey_bynames( GETKEY_CTX *rx, PKT_public_key *pk,

View File

@ -60,7 +60,7 @@ static void menu_deluid (KBNODE pub_keyblock);
static int menu_delsig (KBNODE pub_keyblock); static int menu_delsig (KBNODE pub_keyblock);
static int menu_clean (KBNODE keyblock, int self_only); static int menu_clean (KBNODE keyblock, int self_only);
static void menu_delkey (KBNODE pub_keyblock); static void menu_delkey (KBNODE pub_keyblock);
static int menu_addrevoker (KBNODE pub_keyblock, int sensitive); static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
static int menu_expire (KBNODE pub_keyblock); static int menu_expire (KBNODE pub_keyblock);
static int menu_backsign (KBNODE pub_keyblock); static int menu_backsign (KBNODE pub_keyblock);
static int menu_set_primary_uid (KBNODE pub_keyblock); static int menu_set_primary_uid (KBNODE pub_keyblock);
@ -1586,7 +1586,7 @@ keyedit_completion (const char *text, int start, int end)
/* Main function of the menu driven key editor. */ /* Main function of the menu driven key editor. */
void void
keyedit_menu (const char *username, strlist_t locusr, keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
strlist_t commands, int quiet, int seckey_check) strlist_t commands, int quiet, int seckey_check)
{ {
enum cmdids cmd = 0; enum cmdids cmd = 0;
@ -1599,7 +1599,6 @@ keyedit_menu (const char *username, strlist_t locusr,
int modified = 0; int modified = 0;
int toggle; int toggle;
int have_commands = !!commands; int have_commands = !!commands;
ctrl_t ctrl = NULL; /* Dummy for now. */
if (opt.command_fd != -1) if (opt.command_fd != -1)
; ;
@ -1623,7 +1622,7 @@ keyedit_menu (const char *username, strlist_t locusr,
#endif #endif
/* Get the public key */ /* Get the public key */
err = get_pubkey_byname (NULL, NULL, username, &keyblock, &kdbhd, 1, 1); err = get_pubkey_byname (ctrl, NULL, NULL, username, &keyblock, &kdbhd, 1, 1);
if (err) if (err)
goto leave; goto leave;
if (fix_keyblock (keyblock)) if (fix_keyblock (keyblock))
@ -2095,7 +2094,7 @@ keyedit_menu (const char *username, strlist_t locusr,
if (ascii_strcasecmp (arg_string, "sensitive") == 0) if (ascii_strcasecmp (arg_string, "sensitive") == 0)
sensitive = 1; sensitive = 1;
if (menu_addrevoker (keyblock, sensitive)) if (menu_addrevoker (ctrl, keyblock, sensitive))
{ {
redisplay = 1; redisplay = 1;
modified = 1; modified = 1;
@ -2886,9 +2885,10 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
if (pk->is_revoked) if (pk->is_revoked)
{ {
char *user = get_user_id_string_native (pk->revoked.keyid); char *user = get_user_id_string_native (pk->revoked.keyid);
const char *algo = gcry_pk_algo_name (pk->revoked.algo); tty_printf (_("The following key was revoked on"
tty_printf (_("This key was revoked on %s by %s key %s\n"), " %s by %s key %s\n"),
revokestr_from_pk (pk), algo ? algo : "?", user); revokestr_from_pk (pk),
gcry_pk_algo_name (pk->revoked.algo), user);
xfree (user); xfree (user);
} }
@ -3444,7 +3444,7 @@ menu_delkey (KBNODE pub_keyblock)
* the keyblock. Returns true if there is a new revoker. * the keyblock. Returns true if there is a new revoker.
*/ */
static int static int
menu_addrevoker (KBNODE pub_keyblock, int sensitive) menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
{ {
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
PKT_public_key *revoker_pk = NULL; PKT_public_key *revoker_pk = NULL;
@ -3508,7 +3508,7 @@ menu_addrevoker (KBNODE pub_keyblock, int sensitive)
primary keys only, but some casual testing shows that PGP and primary keys only, but some casual testing shows that PGP and
GnuPG both can handle a designated revocation from a subkey. */ GnuPG both can handle a designated revocation from a subkey. */
revoker_pk->req_usage = PUBKEY_USAGE_CERT; revoker_pk->req_usage = PUBKEY_USAGE_CERT;
rc = get_pubkey_byname (NULL, revoker_pk, answer, NULL, NULL, 1, 1); rc = get_pubkey_byname (ctrl, NULL, revoker_pk, answer, NULL, NULL, 1, 1);
if (rc) if (rc)
{ {
log_error (_("key \"%s\" not found: %s\n"), answer, log_error (_("key \"%s\" not found: %s\n"), answer,

View File

@ -1123,7 +1123,7 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp,
{ {
for (i=0; i<idx; i++) for (i=0; i<idx; i++)
{ {
xfree (array[i]); gcry_mpi_release (array[i]);
array[i] = NULL; array[i] = NULL;
} }
gcry_sexp_release (list); gcry_sexp_release (list);

View File

@ -242,9 +242,12 @@ keystr_with_sub (u32 *main_kid, u32 *sub_kid)
char *p; char *p;
mem2str (buffer, keystr (main_kid), KEYID_STR_SIZE); mem2str (buffer, keystr (main_kid), KEYID_STR_SIZE);
p = buffer + strlen (buffer); if (sub_kid)
*p++ = '/'; {
mem2str (p, keystr (sub_kid), KEYID_STR_SIZE); p = buffer + strlen (buffer);
*p++ = '/';
mem2str (p, keystr (sub_kid), KEYID_STR_SIZE);
}
return buffer; return buffer;
} }
@ -262,9 +265,10 @@ const char *
keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk) keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk)
{ {
keyid_from_pk (main_pk, NULL); keyid_from_pk (main_pk, NULL);
keyid_from_pk (sub_pk, NULL); if (sub_pk)
keyid_from_pk (sub_pk, NULL);
return keystr_with_sub (main_pk->keyid, sub_pk->keyid); return keystr_with_sub (main_pk->keyid, sub_pk? sub_pk->keyid:NULL);
} }

View File

@ -43,7 +43,7 @@
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 (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 (PKT_public_key *sk);
struct sig_stats struct sig_stats
@ -61,7 +61,7 @@ static estream_t attrib_fp;
With LOCATE_MODE set the locate algorithm is used to find a With LOCATE_MODE set the locate algorithm is used to find a
key. */ key. */
void void
public_key_list (strlist_t list, int locate_mode) public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
{ {
if (opt.with_colons) if (opt.with_colons)
{ {
@ -107,7 +107,7 @@ public_key_list (strlist_t list, int locate_mode)
check_trustdb_stale (); check_trustdb_stale ();
if (locate_mode) if (locate_mode)
locate_one (list); locate_one (ctrl, list);
else if (!list) else if (!list)
list_all (0); list_all (0);
else else
@ -116,8 +116,10 @@ public_key_list (strlist_t list, int locate_mode)
void void
secret_key_list (strlist_t list) secret_key_list (ctrl_t ctrl, strlist_t list)
{ {
(void)ctrl;
check_trustdb_stale (); check_trustdb_stale ();
if (!list) if (!list)
@ -533,7 +535,7 @@ list_one (strlist_t names, int secret)
static void static void
locate_one (strlist_t names) locate_one (ctrl_t ctrl, strlist_t names)
{ {
int rc = 0; int rc = 0;
strlist_t sl; strlist_t sl;
@ -545,7 +547,7 @@ locate_one (strlist_t names)
for (sl = names; sl; sl = sl->next) for (sl = names; sl; sl = sl->next)
{ {
rc = get_pubkey_byname (&ctx, NULL, sl->d, &keyblock, NULL, 1, 0); rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
if (rc) if (rc)
{ {
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY) if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)

View File

@ -33,20 +33,23 @@ struct keyserver_spec *parse_keyserver_uri(const char *string,
const char *configname, const char *configname,
unsigned int configlineno); unsigned int configlineno);
struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig); struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig);
int keyserver_export(strlist_t users); int keyserver_export (ctrl_t ctrl, strlist_t users);
int keyserver_import(strlist_t users); int keyserver_import (ctrl_t ctrl, strlist_t users);
int keyserver_import_fprint(const byte *fprint,size_t fprint_len, int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver); struct keyserver_spec *keyserver);
int keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver); int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
int keyserver_refresh(strlist_t users); struct keyserver_spec *keyserver);
int keyserver_search(strlist_t tokens); int keyserver_refresh (ctrl_t ctrl, strlist_t users);
int keyserver_fetch(strlist_t urilist); int keyserver_search (ctrl_t ctrl, strlist_t tokens);
int keyserver_import_cert(const char *name, int keyserver_fetch (ctrl_t ctrl, strlist_t urilist);
unsigned char **fpr,size_t *fpr_len); int keyserver_import_cert (ctrl_t ctrl, const char *name,
int keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len); unsigned char **fpr,size_t *fpr_len);
int keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len, int keyserver_import_pka (ctrl_t ctrl,
struct keyserver_spec *keyserver); const char *name,unsigned char **fpr,size_t *fpr_len);
int keyserver_import_ldap(const char *name, int keyserver_import_name (ctrl_t ctrl,
unsigned char **fpr,size_t *fpr_len); const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
int keyserver_import_ldap (ctrl_t ctrl, const char *name,
unsigned char **fpr,size_t *fpr_len);
#endif /* !_KEYSERVER_INTERNAL_H_ */ #endif /* !_KEYSERVER_INTERNAL_H_ */

View File

@ -89,10 +89,10 @@ static struct parse_options keyserver_opts[]=
{NULL,0,NULL,NULL} {NULL,0,NULL,NULL}
}; };
static int keyserver_work(enum ks_action action,strlist_t list, static int keyserver_work (ctrl_t ctrl, enum ks_action action,strlist_t list,
KEYDB_SEARCH_DESC *desc,int count, KEYDB_SEARCH_DESC *desc,int count,
unsigned char **fpr,size_t *fpr_len, unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver); struct keyserver_spec *keyserver);
/* Reasonable guess */ /* Reasonable guess */
#define DEFAULT_MAX_CERT_SIZE 16384 #define DEFAULT_MAX_CERT_SIZE 16384
@ -732,7 +732,8 @@ parse_keyrec(char *keystring)
(cosmetics, really) and to better take advantage of the keyservers (cosmetics, really) and to better take advantage of the keyservers
that can do multiple fetches in one go (LDAP). */ that can do multiple fetches in one go (LDAP). */
static int static int
show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search) show_prompt (ctrl_t ctrl,
KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
{ {
char *answer; char *answer;
@ -765,8 +766,8 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
while((num=strsep(&split," ,"))!=NULL) while((num=strsep(&split," ,"))!=NULL)
if(atoi(num)>=1 && atoi(num)<=numdesc) if(atoi(num)>=1 && atoi(num)<=numdesc)
keyserver_work(KS_GET,NULL,&desc[atoi(num)-1],1, keyserver_work (ctrl, KS_GET,NULL,&desc[atoi(num)-1],1,
NULL,NULL,opt.keyserver); NULL,NULL,opt.keyserver);
xfree(answer); xfree(answer);
return 1; return 1;
@ -779,7 +780,7 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
small, it will grow safely. If negative it disables the "Key x-y small, it will grow safely. If negative it disables the "Key x-y
of z" messages. searchstr should be UTF-8 (rather than native). */ of z" messages. searchstr should be UTF-8 (rather than native). */
static void static void
keyserver_search_prompt(IOBUF buffer,const char *searchstr) keyserver_search_prompt (ctrl_t ctrl, IOBUF buffer,const char *searchstr)
{ {
int i=0,validcount=0,started=0,header=0,count=1; int i=0,validcount=0,started=0,header=0,count=1;
unsigned int maxlen,buflen,numlines=0; unsigned int maxlen,buflen,numlines=0;
@ -872,7 +873,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr)
for(;;) for(;;)
{ {
if(show_prompt(desc,i,validcount?count:0,localstr)) if (show_prompt (ctrl, desc, i, validcount?count:0, localstr))
break; break;
validcount=0; validcount=0;
} }
@ -901,7 +902,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr)
/* screen_lines - 1 for the prompt. */ /* screen_lines - 1 for the prompt. */
if(numlines+keyrec->lines>opt.screen_lines-1) if(numlines+keyrec->lines>opt.screen_lines-1)
{ {
if(show_prompt(desc,i,validcount?count:0,localstr)) if (show_prompt (ctrl, desc, i, validcount?count:0, localstr))
break; break;
else else
numlines=0; numlines=0;
@ -977,9 +978,10 @@ direct_uri_map(const char *scheme,unsigned int is_direct)
#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\"" #define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
static int static int
keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc, keyserver_spawn (ctrl_t ctrl,
int count,int *prog,unsigned char **fpr,size_t *fpr_len, enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
struct keyserver_spec *keyserver) int count,int *prog,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
{ {
int ret=0,i,gotversion=0,outofband=0; int ret=0,i,gotversion=0,outofband=0;
strlist_t temp; strlist_t temp;
@ -1243,8 +1245,8 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
/* TODO: Remove Comment: lines from keys exported this /* TODO: Remove Comment: lines from keys exported this
way? */ way? */
if(export_pubkeys_stream(buffer,temp,&block, if(export_pubkeys_stream (ctrl, buffer,temp,&block,
opt.keyserver_options.export_options)==-1) opt.keyserver_options.export_options)==-1)
iobuf_close(buffer); iobuf_close(buffer);
else else
{ {
@ -1510,7 +1512,7 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
break; break;
case KS_SEARCH: case KS_SEARCH:
keyserver_search_prompt(spawn->fromchild,searchstr); keyserver_search_prompt (ctrl, spawn->fromchild,searchstr);
break; break;
default: default:
@ -1529,9 +1531,10 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
} }
static int static int
keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc, keyserver_work (ctrl_t ctrl,
int count,unsigned char **fpr,size_t *fpr_len, enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
struct keyserver_spec *keyserver) int count,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
{ {
int rc=0,ret=0; int rc=0,ret=0;
@ -1549,7 +1552,8 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
#else #else
/* Spawn a handler */ /* Spawn a handler */
rc=keyserver_spawn(action,list,desc,count,&ret,fpr,fpr_len,keyserver); rc = keyserver_spawn (ctrl, action, list, desc, count,
&ret, fpr, fpr_len, keyserver);
if(ret) if(ret)
{ {
switch(ret) switch(ret)
@ -1599,7 +1603,7 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
} }
int int
keyserver_export(strlist_t users) keyserver_export (ctrl_t ctrl, strlist_t users)
{ {
gpg_error_t err; gpg_error_t err;
strlist_t sl=NULL; strlist_t sl=NULL;
@ -1624,7 +1628,7 @@ keyserver_export(strlist_t users)
if(sl) if(sl)
{ {
rc=keyserver_work(KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver); rc = keyserver_work (ctrl, KS_SEND,sl,NULL,0,NULL,NULL,opt.keyserver);
free_strlist(sl); free_strlist(sl);
} }
@ -1632,7 +1636,7 @@ keyserver_export(strlist_t users)
} }
int int
keyserver_import(strlist_t users) keyserver_import (ctrl_t ctrl, strlist_t users)
{ {
gpg_error_t err; gpg_error_t err;
KEYDB_SEARCH_DESC *desc; KEYDB_SEARCH_DESC *desc;
@ -1663,7 +1667,8 @@ keyserver_import(strlist_t users)
} }
if(count>0) if(count>0)
rc=keyserver_work(KS_GET,NULL,desc,count,NULL,NULL,opt.keyserver); rc=keyserver_work (ctrl, KS_GET, NULL, desc, count,
NULL, NULL, opt.keyserver);
xfree(desc); xfree(desc);
@ -1671,8 +1676,8 @@ keyserver_import(strlist_t users)
} }
int int
keyserver_import_fprint(const byte *fprint,size_t fprint_len, keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver) struct keyserver_spec *keyserver)
{ {
KEYDB_SEARCH_DESC desc; KEYDB_SEARCH_DESC desc;
@ -1689,11 +1694,12 @@ keyserver_import_fprint(const byte *fprint,size_t fprint_len,
/* TODO: Warn here if the fingerprint we got doesn't match the one /* TODO: Warn here if the fingerprint we got doesn't match the one
we asked for? */ we asked for? */
return keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,keyserver); return keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, keyserver);
} }
int int
keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver) keyserver_import_keyid (ctrl_t ctrl,
u32 *keyid,struct keyserver_spec *keyserver)
{ {
KEYDB_SEARCH_DESC desc; KEYDB_SEARCH_DESC desc;
@ -1703,7 +1709,7 @@ keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver)
desc.u.kid[0]=keyid[0]; desc.u.kid[0]=keyid[0];
desc.u.kid[1]=keyid[1]; desc.u.kid[1]=keyid[1];
return keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,keyserver); return keyserver_work (ctrl, KS_GET,NULL,&desc,1,NULL,NULL,keyserver);
} }
/* code mostly stolen from do_export_stream */ /* code mostly stolen from do_export_stream */
@ -1865,7 +1871,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
usernames to refresh only part of the keyring. */ usernames to refresh only part of the keyring. */
int int
keyserver_refresh(strlist_t users) keyserver_refresh (ctrl_t ctrl, strlist_t users)
{ {
int rc,count,numdesc,fakev3=0; int rc,count,numdesc,fakev3=0;
KEYDB_SEARCH_DESC *desc; KEYDB_SEARCH_DESC *desc;
@ -1908,7 +1914,8 @@ keyserver_refresh(strlist_t users)
Note that a preferred keyserver without a scheme:// Note that a preferred keyserver without a scheme://
will be interpreted as hkp:// */ will be interpreted as hkp:// */
rc=keyserver_work(KS_GET,NULL,&desc[i],1,NULL,NULL,keyserver); rc = keyserver_work (ctrl, KS_GET, NULL, &desc[i], 1,
NULL, NULL, keyserver);
if(rc) if(rc)
log_info(_("WARNING: unable to refresh key %s" log_info(_("WARNING: unable to refresh key %s"
" via %s: %s\n"),keystr_from_desc(&desc[i]), " via %s: %s\n"),keystr_from_desc(&desc[i]),
@ -1938,7 +1945,8 @@ keyserver_refresh(strlist_t users)
count,opt.keyserver->uri); count,opt.keyserver->uri);
} }
rc=keyserver_work(KS_GET,NULL,desc,numdesc,NULL,NULL,opt.keyserver); rc=keyserver_work (ctrl, KS_GET, NULL, desc, numdesc,
NULL, NULL, opt.keyserver);
} }
xfree(desc); xfree(desc);
@ -1954,16 +1962,16 @@ keyserver_refresh(strlist_t users)
} }
int int
keyserver_search(strlist_t tokens) keyserver_search (ctrl_t ctrl, strlist_t tokens)
{ {
if(tokens) if (tokens)
return keyserver_work(KS_SEARCH,tokens,NULL,0,NULL,NULL,opt.keyserver); return keyserver_work (ctrl, KS_SEARCH, tokens, NULL, 0,
else NULL, NULL, opt.keyserver);
return 0; return 0;
} }
int int
keyserver_fetch(strlist_t urilist) keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
{ {
KEYDB_SEARCH_DESC desc; KEYDB_SEARCH_DESC desc;
strlist_t sl; strlist_t sl;
@ -1988,7 +1996,7 @@ keyserver_fetch(strlist_t urilist)
{ {
int rc; int rc;
rc=keyserver_work(KS_GET,NULL,&desc,1,NULL,NULL,spec); rc = keyserver_work (ctrl, KS_GET, NULL, &desc, 1, NULL, NULL, spec);
if(rc) if(rc)
log_info (_("WARNING: unable to fetch URI %s: %s\n"), log_info (_("WARNING: unable to fetch URI %s: %s\n"),
sl->d,g10_errstr(rc)); sl->d,g10_errstr(rc));
@ -2011,7 +2019,8 @@ keyserver_fetch(strlist_t urilist)
/* Import key in a CERT or pointed to by a CERT */ /* Import key in a CERT or pointed to by a CERT */
int int
keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len) keyserver_import_cert (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len)
{ {
char *domain,*look,*url; char *domain,*look,*url;
IOBUF key; IOBUF key;
@ -2058,7 +2067,7 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
spec=parse_keyserver_uri(url,1,NULL,0); spec=parse_keyserver_uri(url,1,NULL,0);
if(spec) if(spec)
{ {
rc=keyserver_import_fprint(*fpr,*fpr_len,spec); rc = keyserver_import_fprint (ctrl, *fpr,*fpr_len,spec);
free_keyserver_spec(spec); free_keyserver_spec(spec);
} }
} }
@ -2067,7 +2076,7 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
/* If only a fingerprint is provided, try and fetch it from /* If only a fingerprint is provided, try and fetch it from
our --keyserver */ our --keyserver */
rc=keyserver_import_fprint(*fpr,*fpr_len,opt.keyserver); rc = keyserver_import_fprint (ctrl, *fpr,*fpr_len,opt.keyserver);
} }
else else
log_info(_("no keyserver known (use option --keyserver)\n")); log_info(_("no keyserver known (use option --keyserver)\n"));
@ -2087,7 +2096,8 @@ keyserver_import_cert(const char *name,unsigned char **fpr,size_t *fpr_len)
/* Import key pointed to by a PKA record. Return the requested /* Import key pointed to by a PKA record. Return the requested
fingerprint in fpr. */ fingerprint in fpr. */
int int
keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len) keyserver_import_pka (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len)
{ {
char *uri; char *uri;
int rc = G10ERR_NO_PUBKEY; int rc = G10ERR_NO_PUBKEY;
@ -2103,7 +2113,7 @@ keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len)
spec = parse_keyserver_uri (uri, 1, NULL, 0); spec = parse_keyserver_uri (uri, 1, NULL, 0);
if (spec) if (spec)
{ {
rc = keyserver_import_fprint (*fpr, 20, spec); rc = keyserver_import_fprint (ctrl, *fpr, 20, spec);
free_keyserver_spec (spec); free_keyserver_spec (spec);
} }
xfree (uri); xfree (uri);
@ -2120,15 +2130,17 @@ keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len)
/* Import all keys that match name */ /* Import all keys that match name */
int int
keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len, keyserver_import_name (ctrl_t ctrl, const char *name,
struct keyserver_spec *keyserver) unsigned char **fpr, size_t *fpr_len,
struct keyserver_spec *keyserver)
{ {
strlist_t list=NULL; strlist_t list=NULL;
int rc; int rc;
append_to_strlist(&list,name); append_to_strlist(&list,name);
rc=keyserver_work(KS_GETNAME,list,NULL,0,fpr,fpr_len,keyserver); rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
0, fpr, fpr_len, keyserver);
free_strlist(list); free_strlist(list);
@ -2137,7 +2149,8 @@ keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len,
/* Import a key by name using LDAP */ /* Import a key by name using LDAP */
int int
keyserver_import_ldap(const char *name,unsigned char **fpr,size_t *fpr_len) keyserver_import_ldap (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len)
{ {
char *domain; char *domain;
struct keyserver_spec *keyserver; struct keyserver_spec *keyserver;
@ -2200,7 +2213,8 @@ keyserver_import_ldap(const char *name,unsigned char **fpr,size_t *fpr_len)
append_to_strlist(&list,name); append_to_strlist(&list,name);
rc=keyserver_work(KS_GETNAME,list,NULL,0,fpr,fpr_len,keyserver); rc = keyserver_work (ctrl, KS_GETNAME, list, NULL,
0, fpr, fpr_len, keyserver);
free_strlist(list); free_strlist(list);

View File

@ -192,10 +192,11 @@ void display_online_help( const char *keyword );
int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek); int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
int encrypt_symmetric (const char *filename ); int encrypt_symmetric (const char *filename );
int encrypt_store (const char *filename ); int encrypt_store (const char *filename );
int encrypt_crypt (int filefd, const char *filename, int encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
strlist_t remusr, int use_symkey, pk_list_t provided_keys, strlist_t remusr, int use_symkey, pk_list_t provided_keys,
int outputfd); int outputfd);
void encrypt_crypt_files (int nfiles, char **files, strlist_t remusr); void encrypt_crypt_files (ctrl_t ctrl,
int nfiles, char **files, strlist_t remusr);
int encrypt_filter (void *opaque, int control, int encrypt_filter (void *opaque, int control,
iobuf_t a, byte *buf, size_t *ret_len); iobuf_t a, byte *buf, size_t *ret_len);
@ -203,7 +204,7 @@ int encrypt_filter (void *opaque, int control,
/*-- sign.c --*/ /*-- sign.c --*/
int complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md, int complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md,
const char *cache_nonce); const char *cache_nonce);
int sign_file( strlist_t filenames, int detached, strlist_t locusr, int sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
int do_encrypt, strlist_t remusr, const char *outfile ); int do_encrypt, strlist_t remusr, const char *outfile );
int clearsign_file( const char *fname, strlist_t locusr, const char *outfile ); int clearsign_file( const char *fname, strlist_t locusr, const char *outfile );
int sign_symencrypt_file (const char *fname, strlist_t locusr); int sign_symencrypt_file (const char *fname, strlist_t locusr);
@ -221,7 +222,7 @@ int check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
int delete_keys( strlist_t names, int secret, int allow_both ); int delete_keys( strlist_t names, int secret, int allow_both );
/*-- keyedit.c --*/ /*-- keyedit.c --*/
void keyedit_menu( const char *username, strlist_t locusr, void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
strlist_t commands, int quiet, int seckey_check ); strlist_t commands, int quiet, int seckey_check );
void keyedit_passwd (const char *username); void keyedit_passwd (const char *username);
void show_basic_key_info (KBNODE keyblock); void show_basic_key_info (KBNODE keyblock);
@ -280,11 +281,11 @@ int collapse_uids( KBNODE *keyblock );
/*-- export.c --*/ /*-- export.c --*/
int parse_export_options(char *str,unsigned int *options,int noisy); int parse_export_options(char *str,unsigned int *options,int noisy);
int export_pubkeys( strlist_t users, unsigned int options ); int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options );
int export_pubkeys_stream( iobuf_t out, strlist_t users, int export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
KBNODE *keyblock_out, unsigned int options ); kbnode_t *keyblock_out, unsigned int options );
int export_seckeys( strlist_t users ); int export_seckeys (ctrl_t ctrl, strlist_t users);
int export_secsubkeys( strlist_t users ); int export_secsubkeys (ctrl_t ctrl, strlist_t users);
/* dearmor.c --*/ /* dearmor.c --*/
int dearmor_file( const char *fname ); int dearmor_file( const char *fname );
@ -300,8 +301,8 @@ struct revocation_reason_info *
void release_revocation_reason_info( struct revocation_reason_info *reason ); void release_revocation_reason_info( struct revocation_reason_info *reason );
/*-- keylist.c --*/ /*-- keylist.c --*/
void public_key_list( strlist_t list, int locate_mode ); void public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode );
void secret_key_list( strlist_t list ); void secret_key_list (ctrl_t ctrl, strlist_t list );
void print_subpackets_colon(PKT_signature *sig); void print_subpackets_colon(PKT_signature *sig);
void reorder_keyblock (KBNODE keyblock); void reorder_keyblock (KBNODE keyblock);
void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque ); void list_keyblock( KBNODE keyblock, int secret, int fpr, void *opaque );
@ -318,14 +319,14 @@ void print_card_key_info (estream_t fp, KBNODE keyblock);
/*-- verify.c --*/ /*-- verify.c --*/
void print_file_status( int status, const char *name, int what ); void print_file_status( int status, const char *name, int what );
int verify_signatures( int nfiles, char **files ); int verify_signatures (ctrl_t ctrl, int nfiles, char **files );
int verify_files( int nfiles, char **files ); int verify_files (ctrl_t ctrl, int nfiles, char **files );
int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp); int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp);
/*-- decrypt.c --*/ /*-- decrypt.c --*/
int decrypt_message( const char *filename ); int decrypt_message (ctrl_t ctrl, const char *filename );
gpg_error_t decrypt_message_fd (int input_fd, int output_fd); gpg_error_t decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd);
void decrypt_messages(int nfiles, char *files[]); void decrypt_messages (ctrl_t ctrl, int nfiles, char *files[]);
/*-- plaintext.c --*/ /*-- plaintext.c --*/
int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2,
@ -346,7 +347,7 @@ int gpg_server (ctrl_t);
/*-- card-util.c --*/ /*-- card-util.c --*/
void change_pin (int no, int allow_admin); void change_pin (int no, int allow_admin);
void card_status (estream_t fp, char *serialno, size_t serialnobuflen); void card_status (estream_t fp, char *serialno, size_t serialnobuflen);
void card_edit (strlist_t commands); void card_edit (ctrl_t ctrl, strlist_t commands);
int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock); int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock);
int card_store_subkey (KBNODE node, int use); int card_store_subkey (KBNODE node, int use);
#endif #endif

View File

@ -26,10 +26,10 @@
#include <time.h> #include <time.h>
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "iobuf.h" #include "iobuf.h"
#include "options.h" #include "options.h"
#include "util.h"
#include "cipher.h" #include "cipher.h"
#include "keydb.h" #include "keydb.h"
#include "filter.h" #include "filter.h"
@ -56,6 +56,7 @@ struct kidlist_item {
typedef struct mainproc_context *CTX; typedef struct mainproc_context *CTX;
struct mainproc_context struct mainproc_context
{ {
ctrl_t ctrl;
struct mainproc_context *anchor; /* May be useful in the future. */ struct mainproc_context *anchor; /* May be useful in the future. */
PKT_public_key *last_pubkey; PKT_public_key *last_pubkey;
PKT_user_id *last_user_id; PKT_user_id *last_user_id;
@ -563,8 +564,8 @@ proc_encrypted( CTX c, PACKET *pkt )
} }
else if( !c->dek ) else if( !c->dek )
result = G10ERR_NO_SECKEY; result = G10ERR_NO_SECKEY;
if( !result ) if (!result)
result = decrypt_data( c, pkt->pkt.encrypted, c->dek ); result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
if( result == -1 ) if( result == -1 )
; ;
@ -757,18 +758,19 @@ proc_compressed_cb( IOBUF a, void *info )
{ {
if ( ((CTX)info)->signed_data.used if ( ((CTX)info)->signed_data.used
&& ((CTX)info)->signed_data.data_fd != -1) && ((CTX)info)->signed_data.data_fd != -1)
return proc_signature_packets_by_fd (info, a, return proc_signature_packets_by_fd (((CTX)info)->ctrl, info, a,
((CTX)info)->signed_data.data_fd); ((CTX)info)->signed_data.data_fd);
else else
return proc_signature_packets (info, a, return proc_signature_packets (((CTX)info)->ctrl, info, a,
((CTX)info)->signed_data.data_names, ((CTX)info)->signed_data.data_names,
((CTX)info)->sigfilename ); ((CTX)info)->sigfilename );
} }
static int static int
proc_encrypt_cb( IOBUF a, void *info ) proc_encrypt_cb (IOBUF a, void *info )
{ {
return proc_encryption_packets( info, a ); CTX c = info;
return proc_encryption_packets (c->ctrl, info, a );
} }
static void static void
@ -781,11 +783,11 @@ proc_compressed( CTX c, PACKET *pkt )
if( !zd->algorithm ) if( !zd->algorithm )
rc=G10ERR_COMPR_ALGO; rc=G10ERR_COMPR_ALGO;
else if( c->sigs_only ) else if( c->sigs_only )
rc = handle_compressed( c, zd, proc_compressed_cb, c ); rc = handle_compressed (c->ctrl, c, zd, proc_compressed_cb, c );
else if( c->encrypt_only ) else if( c->encrypt_only )
rc = handle_compressed( c, zd, proc_encrypt_cb, c ); rc = handle_compressed (c->ctrl, c, zd, proc_encrypt_cb, c );
else else
rc = handle_compressed( c, zd, NULL, NULL ); rc = handle_compressed (c->ctrl, c, zd, NULL, NULL );
if( rc ) if( rc )
log_error("uncompressing failed: %s\n", g10_errstr(rc)); log_error("uncompressing failed: %s\n", g10_errstr(rc));
free_packet(pkt); free_packet(pkt);
@ -1174,11 +1176,12 @@ list_node( CTX c, KBNODE node )
int int
proc_packets( void *anchor, IOBUF a ) proc_packets (ctrl_t ctrl, void *anchor, IOBUF a )
{ {
int rc; int rc;
CTX c = xmalloc_clear( sizeof *c ); CTX c = xmalloc_clear( sizeof *c );
c->ctrl = ctrl;
c->anchor = anchor; c->anchor = anchor;
rc = do_proc_packets( c, a ); rc = do_proc_packets( c, a );
xfree( c ); xfree( c );
@ -1188,12 +1191,13 @@ proc_packets( void *anchor, IOBUF a )
int int
proc_signature_packets( void *anchor, IOBUF a, proc_signature_packets (ctrl_t ctrl, void *anchor, IOBUF a,
strlist_t signedfiles, const char *sigfilename ) strlist_t signedfiles, const char *sigfilename )
{ {
CTX c = xmalloc_clear( sizeof *c ); CTX c = xmalloc_clear( sizeof *c );
int rc; int rc;
c->ctrl = ctrl;
c->anchor = anchor; c->anchor = anchor;
c->sigs_only = 1; c->sigs_only = 1;
@ -1228,7 +1232,8 @@ proc_signature_packets( void *anchor, IOBUF a,
int int
proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd ) proc_signature_packets_by_fd (ctrl_t ctrl,
void *anchor, IOBUF a, int signed_data_fd )
{ {
int rc; int rc;
CTX c; CTX c;
@ -1237,6 +1242,7 @@ proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd )
if (!c) if (!c)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
c->ctrl = ctrl;
c->anchor = anchor; c->anchor = anchor;
c->sigs_only = 1; c->sigs_only = 1;
@ -1269,11 +1275,12 @@ proc_signature_packets_by_fd (void *anchor, IOBUF a, int signed_data_fd )
int int
proc_encryption_packets( void *anchor, IOBUF a ) proc_encryption_packets (ctrl_t ctrl, void *anchor, IOBUF a )
{ {
CTX c = xmalloc_clear( sizeof *c ); CTX c = xmalloc_clear( sizeof *c );
int rc; int rc;
c->ctrl = ctrl;
c->anchor = anchor; c->anchor = anchor;
c->encrypt_only = 1; c->encrypt_only = 1;
rc = do_proc_packets( c, a ); rc = do_proc_packets( c, a );
@ -1652,7 +1659,7 @@ check_sig_and_print( CTX c, KBNODE node )
int res; int res;
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
res=keyserver_import_keyid(sig->keyid,spec); res = keyserver_import_keyid (c->ctrl, sig->keyid,spec);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(!res) if(!res)
rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey );
@ -1684,7 +1691,7 @@ check_sig_and_print( CTX c, KBNODE node )
if (spec) if (spec)
{ {
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
res = keyserver_import_keyid (sig->keyid, spec); res = keyserver_import_keyid (c->ctrl, sig->keyid, spec);
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
free_keyserver_spec (spec); free_keyserver_spec (spec);
if (!res) if (!res)
@ -1702,7 +1709,7 @@ check_sig_and_print( CTX c, KBNODE node )
int res; int res;
glo_ctrl.in_auto_key_retrieve++; glo_ctrl.in_auto_key_retrieve++;
res=keyserver_import_keyid ( sig->keyid, opt.keyserver ); res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
glo_ctrl.in_auto_key_retrieve--; glo_ctrl.in_auto_key_retrieve--;
if(!res) if(!res)
rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey );

View File

@ -124,8 +124,6 @@ struct
int s2k_cipher_algo; int s2k_cipher_algo;
unsigned char s2k_count; /* This is the encoded form, not the raw unsigned char s2k_count; /* This is the encoded form, not the raw
count */ count */
int simple_sk_checksum; /* create the deprecated rfc2440 secret key
protection */
int not_dash_escaped; int not_dash_escaped;
int escape_from; int escape_from;
int lock_once; int lock_once;

View File

@ -370,11 +370,12 @@ struct notation
/*-- mainproc.c --*/ /*-- mainproc.c --*/
void reset_literals_seen(void); void reset_literals_seen(void);
int proc_packets( void *ctx, iobuf_t a ); int proc_packets (ctrl_t ctrl, void *ctx, iobuf_t a );
int proc_signature_packets( void *ctx, iobuf_t a, int proc_signature_packets (ctrl_t ctrl, void *ctx, iobuf_t a,
strlist_t signedfiles, const char *sigfile ); strlist_t signedfiles, const char *sigfile );
int proc_signature_packets_by_fd ( void *anchor, IOBUF a, int signed_data_fd ); int proc_signature_packets_by_fd (ctrl_t ctrl,
int proc_encryption_packets( void *ctx, iobuf_t a ); void *anchor, IOBUF a, int signed_data_fd );
int proc_encryption_packets (ctrl_t ctrl, void *ctx, iobuf_t a);
int list_packets( iobuf_t a ); int list_packets( iobuf_t a );
/*-- parse-packet.c --*/ /*-- parse-packet.c --*/
@ -475,11 +476,11 @@ gpg_error_t get_session_key (PKT_pubkey_enc *k, DEK *dek);
gpg_error_t get_override_session_key (DEK *dek, const char *string); gpg_error_t get_override_session_key (DEK *dek, const char *string);
/*-- compress.c --*/ /*-- compress.c --*/
int handle_compressed( void *ctx, PKT_compressed *cd, int handle_compressed (ctrl_t ctrl, void *ctx, PKT_compressed *cd,
int (*callback)(iobuf_t, void *), void *passthru ); int (*callback)(iobuf_t, void *), void *passthru );
/*-- encr-data.c --*/ /*-- encr-data.c --*/
int decrypt_data( void *ctx, PKT_encrypted *ed, DEK *dek ); int decrypt_data (ctrl_t ctrl, void *ctx, PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/ /*-- plaintext.c --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx, int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,

View File

@ -25,9 +25,9 @@
#include <assert.h> #include <assert.h>
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "iobuf.h" #include "iobuf.h"
#include "util.h"
#include "cipher.h" #include "cipher.h"
#include "filter.h" #include "filter.h"
#include "photoid.h" #include "photoid.h"

View File

@ -29,11 +29,11 @@
#endif #endif
#include "gpg.h" #include "gpg.h"
#include "util.h"
#include "packet.h" #include "packet.h"
#include "status.h" #include "status.h"
#include "exec.h" #include "exec.h"
#include "keydb.h" #include "keydb.h"
#include "util.h"
#include "i18n.h" #include "i18n.h"
#include "iobuf.h" #include "iobuf.h"
#include "options.h" #include "options.h"

View File

@ -778,7 +778,7 @@ expand_group(strlist_t input)
of the key. USE the requested usage and a set MARK_HIDDEN will mark of the key. USE the requested usage and a set MARK_HIDDEN will mark
the key in the updated list as a hidden recipient. */ the key in the updated list as a hidden recipient. */
gpg_error_t gpg_error_t
find_and_check_key (const char *name, unsigned int use, find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
int mark_hidden, pk_list_t *pk_list_addr) int mark_hidden, pk_list_t *pk_list_addr)
{ {
int rc; int rc;
@ -793,7 +793,7 @@ find_and_check_key (const char *name, unsigned int use,
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
pk->req_usage = use; pk->req_usage = use;
rc = get_pubkey_byname (NULL, pk, name, NULL, NULL, 0, 0); rc = get_pubkey_byname (ctrl, NULL, pk, name, NULL, NULL, 0, 0);
if (rc) if (rc)
{ {
/* Key not found or other error. */ /* Key not found or other error. */
@ -883,7 +883,8 @@ find_and_check_key (const char *name, unsigned int use,
not changed. not changed.
*/ */
int int
build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use ) build_pk_list (ctrl_t ctrl,
strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
{ {
PK_LIST pk_list = NULL; PK_LIST pk_list = NULL;
PKT_public_key *pk=NULL; PKT_public_key *pk=NULL;
@ -929,7 +930,8 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
/* We explicitly allow encrypt-to to an disabled key; thus /* We explicitly allow encrypt-to to an disabled key; thus
we pass 1for the second last argument and 1 as the last we pass 1for the second last argument and 1 as the last
argument to disable AKL. */ argument to disable AKL. */
if ( (rc = get_pubkey_byname (NULL, pk, rov->d, NULL, NULL, 1, 1)) ) if ( (rc = get_pubkey_byname (ctrl,
NULL, pk, rov->d, NULL, NULL, 1, 1)) )
{ {
free_public_key ( pk ); pk = NULL; free_public_key ( pk ); pk = NULL;
log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
@ -1066,7 +1068,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
free_public_key (pk); free_public_key (pk);
pk = xmalloc_clear( sizeof *pk ); pk = xmalloc_clear( sizeof *pk );
pk->req_usage = use; pk->req_usage = use;
rc = get_pubkey_byname (NULL, pk, answer, NULL, NULL, 0, 0 ); rc = get_pubkey_byname (ctrl, NULL, pk, answer, NULL, NULL, 0, 0 );
if (rc) if (rc)
tty_printf(_("No such user ID.\n")); tty_printf(_("No such user ID.\n"));
else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) ) else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) )
@ -1140,7 +1142,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
/* The default recipient is allowed to be disabled; thus pass 1 /* The default recipient is allowed to be disabled; thus pass 1
as second last argument. We also don't want an AKL. */ as second last argument. We also don't want an AKL. */
rc = get_pubkey_byname (NULL, pk, def_rec, NULL, NULL, 1, 1); rc = get_pubkey_byname (ctrl, NULL, pk, def_rec, NULL, NULL, 1, 1);
if (rc) if (rc)
log_error(_("unknown default recipient \"%s\"\n"), def_rec ); log_error(_("unknown default recipient \"%s\"\n"), def_rec );
else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) ) else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use)) )
@ -1178,7 +1180,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
if ( (remusr->flags & 1) ) if ( (remusr->flags & 1) )
continue; /* encrypt-to keys are already handled. */ continue; /* encrypt-to keys are already handled. */
rc = find_and_check_key (remusr->d, use, !!(remusr->flags&2), rc = find_and_check_key (ctrl, remusr->d, use, !!(remusr->flags&2),
&pk_list); &pk_list);
if (rc) if (rc)
goto fail; goto fail;

View File

@ -231,7 +231,7 @@ cmd_recipient (assuan_context_t ctx, char *line)
remusr = rcpts; remusr = rcpts;
*/ */
err = find_and_check_key (line, PUBKEY_USAGE_ENC, hidden, err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
&ctrl->server_local->recplist); &ctrl->server_local->recplist);
if (err) if (err)
@ -324,7 +324,7 @@ cmd_encrypt (assuan_context_t ctx, char *line)
/* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/ /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
err = encrypt_crypt (inp_fd, NULL, NULL, 0, err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
ctrl->server_local->recplist, ctrl->server_local->recplist,
out_fd); out_fd);
@ -368,7 +368,7 @@ cmd_decrypt (assuan_context_t ctx, char *line)
return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
glo_ctrl.lasterr = 0; glo_ctrl.lasterr = 0;
err = decrypt_message_fd (inp_fd, out_fd); err = decrypt_message_fd (ctrl, inp_fd, out_fd);
if (!err) if (!err)
err = glo_ctrl.lasterr; err = glo_ctrl.lasterr;

View File

@ -762,7 +762,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
* uncompressed, non-armored and in binary mode. * uncompressed, non-armored and in binary mode.
*/ */
int int
sign_file( strlist_t filenames, int detached, strlist_t locusr, sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
int encryptflag, strlist_t remusr, const char *outfile ) int encryptflag, strlist_t remusr, const char *outfile )
{ {
const char *fname; const char *fname;
@ -822,7 +822,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
compliance_failure(); compliance_failure();
} }
if(encryptflag && (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC ))) if (encryptflag
&& (rc=build_pk_list (ctrl, remusr, &pk_list, PUBKEY_USAGE_ENC)))
goto leave; goto leave;
/* prepare iobufs */ /* prepare iobufs */

View File

@ -50,7 +50,7 @@
*/ */
int int
verify_signatures( int nfiles, char **files ) verify_signatures (ctrl_t ctrl, int nfiles, char **files )
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t *afx = NULL; armor_filter_context_t *afx = NULL;
@ -110,7 +110,7 @@ verify_signatures( int nfiles, char **files )
sl = NULL; sl = NULL;
for(i=nfiles-1 ; i > 0 ; i-- ) for(i=nfiles-1 ; i > 0 ; i-- )
add_to_strlist( &sl, files[i] ); add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( NULL, fp, sl, sigfile ); rc = proc_signature_packets (ctrl, NULL, fp, sl, sigfile );
free_strlist(sl); free_strlist(sl);
iobuf_close(fp); iobuf_close(fp);
if( (afx && afx->no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) { if( (afx && afx->no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) {
@ -139,7 +139,7 @@ print_file_status( int status, const char *name, int what )
static int static int
verify_one_file( const char *name ) verify_one_file (ctrl_t ctrl, const char *name )
{ {
IOBUF fp; IOBUF fp;
armor_filter_context_t *afx = NULL; armor_filter_context_t *afx = NULL;
@ -172,7 +172,7 @@ verify_one_file( const char *name )
} }
} }
rc = proc_signature_packets( NULL, fp, NULL, name ); rc = proc_signature_packets (ctrl, NULL, fp, NULL, name );
iobuf_close(fp); iobuf_close(fp);
write_status( STATUS_FILE_DONE ); write_status( STATUS_FILE_DONE );
@ -190,7 +190,7 @@ verify_one_file( const char *name )
* Note: This function can not handle detached signatures. * Note: This function can not handle detached signatures.
*/ */
int int
verify_files( int nfiles, char **files ) verify_files (ctrl_t ctrl, int nfiles, char **files )
{ {
int i; int i;
@ -208,13 +208,13 @@ verify_files( int nfiles, char **files )
* also no script languages available. We don't strip any * also no script languages available. We don't strip any
* spaces, so that we can process nearly all filenames */ * spaces, so that we can process nearly all filenames */
line[strlen(line)-1] = 0; line[strlen(line)-1] = 0;
verify_one_file( line ); verify_one_file (ctrl, line );
} }
} }
else { /* take filenames from the array */ else { /* take filenames from the array */
for(i=0; i < nfiles; i++ ) for(i=0; i < nfiles; i++ )
verify_one_file( files[i] ); verify_one_file (ctrl, files[i] );
} }
return 0; return 0;
} }
@ -262,7 +262,7 @@ gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, estream_t out_fp)
push_armor_filter (afx, fp); push_armor_filter (afx, fp);
} }
rc = proc_signature_packets_by_fd (NULL, fp, data_fd); rc = proc_signature_packets_by_fd (ctrl, NULL, fp, data_fd);
if ( afx && afx->no_openpgp_data if ( afx && afx->no_openpgp_data
&& (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) ) && (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) )

View File

@ -918,12 +918,13 @@ parse_ccid_descriptor (ccid_driver_t handle,
DEBUGOUT_1 (" bMaxCCIDBusySlots %5u\n", buf[53]); DEBUGOUT_1 (" bMaxCCIDBusySlots %5u\n", buf[53]);
if (buf[0] > 54) { if (buf[0] > 54)
DEBUGOUT (" junk "); {
for (i=54; i < buf[0]-54; i++) DEBUGOUT (" junk ");
DEBUGOUT_CONT_1 (" %02X", buf[i]); for (i=54; i < buf[0]-54; i++)
DEBUGOUT_LF (); DEBUGOUT_CONT_1 (" %02X", buf[i]);
} DEBUGOUT_LF ();
}
if (!have_t1 || !(have_tpdu || handle->apdu_level) || !have_auto_conf) if (!have_t1 || !(have_tpdu || handle->apdu_level) || !have_auto_conf)
{ {

View File

@ -1,3 +1,13 @@
2010-09-16 Werner Koch <wk@g10code.com>
* certchain.c (gpgsm_walk_cert_chain): Use GPG_ERR_MISSING_ISSUER_CERT.
(do_validate_chain): Ditto.
(gpgsm_basic_cert_check): Ditto.
* call-agent.c (learn_cb): Take care of new
GPG_ERR_MISSING_ISSUER_CERT.
* import.c (check_and_store): Ditto.
(check_and_store): Ditto.
2010-08-16 Werner Koch <wk@g10code.com> 2010-08-16 Werner Koch <wk@g10code.com>
* gpgsm.c (main) <aGPGConfList>: Use es_printf. * gpgsm.c (main) <aGPGConfList>: Use es_printf.

View File

@ -887,7 +887,8 @@ learn_cb (void *opaque, const void *buffer, size_t length)
because we can assume that the --learn-card command has been used because we can assume that the --learn-card command has been used
on purpose. */ on purpose. */
rc = gpgsm_basic_cert_check (parm->ctrl, cert); rc = gpgsm_basic_cert_check (parm->ctrl, cert);
if (rc && gpg_err_code (rc) != GPG_ERR_MISSING_CERT) if (rc && gpg_err_code (rc) != GPG_ERR_MISSING_CERT
&& gpg_err_code (rc) != GPG_ERR_MISSING_ISSUER_CERT)
log_error ("invalid certificate: %s\n", gpg_strerror (rc)); log_error ("invalid certificate: %s\n", gpg_strerror (rc));
else else
{ {

View File

@ -789,7 +789,7 @@ gpgsm_walk_cert_chain (ctrl_t ctrl, ksba_cert_t start, ksba_cert_t *r_next)
print an error here. */ print an error here. */
if (rc != -1 && opt.verbose > 1) if (rc != -1 && opt.verbose > 1)
log_error ("failed to find issuer's certificate: rc=%d\n", rc); log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = gpg_error (GPG_ERR_MISSING_CERT); rc = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
goto leave; goto leave;
} }
@ -1496,7 +1496,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
} }
else else
log_error ("failed to find issuer's certificate: rc=%d\n", rc); log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = gpg_error (GPG_ERR_MISSING_CERT); rc = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
goto leave; goto leave;
} }
@ -1897,7 +1897,7 @@ gpgsm_basic_cert_check (ctrl_t ctrl, ksba_cert_t cert)
} }
else else
log_error ("failed to find issuer's certificate: rc=%d\n", rc); log_error ("failed to find issuer's certificate: rc=%d\n", rc);
rc = gpg_error (GPG_ERR_MISSING_CERT); rc = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
goto leave; goto leave;
} }

View File

@ -287,7 +287,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oAuditLog, "audit-log", ARGPARSE_s_s (oAuditLog, "audit-log",
N_("|FILE|write an audit log to FILE")), N_("|FILE|write an audit log to FILE")),
ARGPARSE_s_s (oHtmlAuditLog, "html-audit-log", ""), ARGPARSE_s_s (oHtmlAuditLog, "html-audit-log", "@"),
ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")), ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")), ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")), ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),

View File

@ -194,7 +194,8 @@ check_and_store (ctrl_t ctrl, struct stats_s *stats,
if (!rc && ctrl->with_validation) if (!rc && ctrl->with_validation)
rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL); rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL);
if (!rc || (!ctrl->with_validation if (!rc || (!ctrl->with_validation
&& gpg_err_code (rc) == GPG_ERR_MISSING_CERT) ) && (gpg_err_code (rc) == GPG_ERR_MISSING_CERT
|| gpg_err_code (rc) == GPG_ERR_MISSING_ISSUER_CERT)))
{ {
int existed; int existed;
@ -253,9 +254,14 @@ check_and_store (ctrl_t ctrl, struct stats_s *stats,
log_error (_("basic certificate checks failed - not imported\n")); log_error (_("basic certificate checks failed - not imported\n"));
if (stats) if (stats)
stats->not_imported++; stats->not_imported++;
print_import_problem (ctrl, cert, /* We keep the test for GPG_ERR_MISSING_CERT only in case
gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 : GPG_ERR_MISSING_CERT has been used instead of the newer
gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0); GPG_ERR_MISSING_ISSUER_CERT. */
print_import_problem
(ctrl, cert,
gpg_err_code (rc) == GPG_ERR_MISSING_ISSUER_CERT? 2 :
gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 :
gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0);
} }
} }