1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

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.
* Dirmngr is now a part of this package. Dirmngr is now also
expected to run as a system service and the configuraion
directories are changed to the gnupg name space.
expected to run as a system service and the configuration
directories are changed to the GnuPG name space.
* 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.
* Removed options:
--export-options: export-secret-subkey-passwd
--simple-sk-checksum
Noteworthy changes in version 2.0.13 (2009-09-04)
-------------------------------------------------

View File

@ -23,6 +23,7 @@ Release process:
(Mainly config.guess and config.sub).
* [1.4 only] Update gpg.texi and gpgv.texi from the trunk:
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".
* Write NEWS entries and set the release date in NEWS.
* 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>
* 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_CLEAR = 1,
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,
cache_mode_t cache_mode,
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,
const unsigned char *grip,
gcry_sexp_t *result);
@ -251,7 +253,7 @@ int pinentry_active_p (ctrl_t ctrl, int waitseconds);
int agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *inital_errtext,
struct pin_entry_info_s *pininfo);
struct pin_entry_info_s *pininfo, int *r_cancelall);
int agent_get_passphrase (ctrl_t ctrl, char **retpass,
const char *desc, const char *prompt,
const char *errtext, int with_qualitybar);
@ -289,7 +291,7 @@ int agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase);
char **r_passphrase, int *r_cancelall);
int agent_genkey (ctrl_t ctrl, const char *cache_nonce,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);

View File

@ -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
number here and repeat it as long as we have invalid formed
@ -704,7 +727,7 @@ int
agent_askpin (ctrl_t ctrl,
const char *desc_text, const char *prompt_text,
const char *initial_errtext,
struct pin_entry_info_s *pininfo)
struct pin_entry_info_s *pininfo, int *r_cancel_all)
{
int rc;
char line[ASSUAN_LINELENGTH];
@ -712,6 +735,10 @@ agent_askpin (ctrl_t ctrl,
const char *errtext = NULL;
int is_pin = 0;
int saveflag;
int close_button;
if (r_cancel_all)
*r_cancel_all = 0;
if (opt.batch)
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);
assuan_begin_confidential (entry_ctx);
close_button = 0;
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
inq_quality, entry_ctx, NULL, NULL);
inq_quality, entry_ctx,
close_button_status_cb, &close_button);
assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
/* Most pinentries out in the wild return the old Assuan error code
for canceled which gets translated to an assuan Cancel error and
@ -801,6 +830,11 @@ agent_askpin (ctrl_t ctrl,
&& gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
/* Set a flag in case the window close button was clicked to
cancel the operation. */
if (close_button && r_cancel_all && gpg_err_code (rc) == GPG_ERR_CANCELED)
*r_cancel_all = 1;
if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
errtext = is_pin? _("PIN 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;
next_try:
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL);
initial_errtext = NULL;
if (err)
goto out;
@ -2433,7 +2433,7 @@ ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
/* Unless the passphrase is empty, ask to confirm it. */
if (pi->pin && *pi->pin)
{
err = agent_askpin (ctrl, description2, NULL, NULL, pi2);
err = agent_askpin (ctrl, description2, NULL, NULL, pi2, NULL);
if (err == -1)
{ /* The re-entered one did not match and the user did not
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 */
static int
has_option (const char *line, const char *name)
@ -177,6 +194,8 @@ has_option (const char *line, const char *name)
int n = strlen (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)));
}
@ -190,6 +209,8 @@ has_option_name (const char *line, const char *name)
int n = strlen (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) || s[n] == '='));
}
@ -203,6 +224,8 @@ option_value (const char *line, const char *name)
int n = strlen (name);
s = strstr (line, name);
if (s && s >= skip_options (line))
return NULL;
if (s && (s == line || spacep (s-1))
&& 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. */
static void
plus_to_blank (char *s)
@ -530,23 +536,35 @@ cmd_marktrusted (assuan_context_t ctx, char *line)
static const char hlp_havekey[] =
"HAVEKEY <hexstring_with_keygrip>\n"
"HAVEKEY <hexstrings_with_keygrips>\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
cmd_havekey (assuan_context_t ctx, char *line)
{
int rc;
gpg_error_t err;
unsigned char buf[20];
rc = parse_keygrip (ctx, line, buf);
if (rc)
return rc;
do
{
err = parse_keygrip (ctx, line, buf);
if (err)
return err;
if (agent_key_available (buf))
return gpg_error (GPG_ERR_NO_SECKEY);
if (!agent_key_available (buf))
return 0; /* Found. */
return 0;
while (*line && *line != ' ' && *line != '\t')
line++;
while (*line == ' ' || *line == '\t')
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++;
rc = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc,
grip, &shadow_info, CACHE_MODE_IGNORE, NULL,
&s_skey);
&s_skey, NULL);
if (rc)
;
{
/* Not all users of gpg-agent know about fully cancled; thus we
map it back. */
if (gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
}
else if (!s_skey)
{
log_error ("changing a smartcard PIN is not yet supported\n");
@ -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
key import. */
err = convert_openpgp (ctrl, openpgp_sexp, grip,
ctrl->server_local->keydesc, cache_nonce,
&key, &passphrase);
err = convert_from_openpgp (ctrl, openpgp_sexp, grip,
ctrl->server_local->keydesc, cache_nonce,
&key, &passphrase);
if (err)
goto leave;
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
(ctrl, _("Please enter the passphrase to protect the "
"imported object within the GnuPG system."),
&passphrase);
&passphrase, NULL);
if (err)
goto leave;
}
@ -1650,7 +1673,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
static const char hlp_export_key[] =
"EXPORT_KEY <hexstring_with_keygrip>\n"
"EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp] <hexstring_with_keygrip>\n"
"\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"
@ -1668,6 +1691,26 @@ cmd_export_key (assuan_context_t ctx, char *line)
gcry_cipher_hd_t cipherhd = NULL;
unsigned char *wrappedkey = NULL;
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)
{
@ -1685,8 +1728,11 @@ cmd_export_key (assuan_context_t ctx, char *line)
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,
NULL, CACHE_MODE_IGNORE, NULL, &s_skey);
NULL, CACHE_MODE_IGNORE, NULL, &s_skey,
openpgp ? &passphrase : NULL);
if (err)
goto leave;
if (!s_skey)
@ -1698,7 +1744,32 @@ cmd_export_key (assuan_context_t ctx, char *line)
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)
goto leave;
gcry_sexp_release (s_skey);
@ -1735,12 +1806,18 @@ cmd_export_key (assuan_context_t ctx, char *line)
leave:
xfree (passphrase);
xfree (wrappedkey);
gcry_cipher_close (cipherhd);
xfree (key);
gcry_sexp_release (s_skey);
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
/* Not all users of gpg-agent know about fully cancled; thus we map
it back unless we know that it is okay. */
if (!openpgp && gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
err = gpg_err_make (gpg_err_source (err), GPG_ERR_CANCELED);
return leave_cmd (ctx, err);
}

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
arguments. */
gpg_error_t
convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase)
convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase)
{
gpg_error_t err;
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);
}
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;
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
#define GNUPG_AGENT_CVT_OPENPGP_H
gpg_error_t convert_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase);
gpg_error_t convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
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*/

View File

@ -266,7 +266,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
if (any_flags)
{
rc = agent_askpin (ctrl, info, prompt, again_text, pi);
rc = agent_askpin (ctrl, info, prompt, again_text, pi, NULL);
again_text = NULL;
if (!rc && newpin)
{
@ -288,7 +288,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
is_puk?
_("Repeat this PUK"):
_("Repeat this PIN")),
prompt, NULL, pi2);
prompt, NULL, pi2, NULL);
if (!rc && strcmp (pi->pin, pi2->pin))
{
again_text = (resetcode?
@ -312,7 +312,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
info? info:"",
info? "')":"") < 0)
desc = NULL;
rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi);
rc = agent_askpin (ctrl, desc?desc:info, prompt, NULL, pi, NULL);
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. */
static int
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
caching mechanism. DESC_TEXT may be set to override the default
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
unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
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 try_unprotect_arg_s arg;
@ -285,6 +290,10 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
unsigned char *result;
size_t resultlen;
char hexgrip[40+1];
int fully_canceled;
if (r_passphrase)
*r_passphrase = NULL;
bin2hex (grip, 20, hexgrip);
@ -297,13 +306,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
if (pw)
{
rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
xfree (pw);
if (!rc)
{
if (r_passphrase)
*r_passphrase = pw;
else
xfree (pw);
xfree (*keybuf);
*keybuf = result;
return 0;
}
xfree (pw);
}
}
@ -318,13 +331,17 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
if (pw)
{
rc = agent_unprotect (*keybuf, pw, NULL, &result, &resultlen);
xfree (pw);
if (!rc)
{
if (r_passphrase)
*r_passphrase = pw;
else
xfree (pw);
xfree (*keybuf);
*keybuf = result;
return 0;
}
xfree (pw);
rc = 0;
}
@ -366,7 +383,9 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
arg.change_required = 0;
pi->check_cb_arg = &arg;
rc = agent_askpin (ctrl, desc_text, NULL, NULL, pi);
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)
{
assert (arg.unprotected_key);
@ -400,8 +419,13 @@ unprotect (ctrl_t ctrl, const char *cache_nonce, const char *desc_text,
return rc;
}
}
agent_put_cache (hexgrip, cache_mode, pi->pin,
lookup_ttl? lookup_ttl (hexgrip) : 0);
else
{
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);
*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
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
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
agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
const char *desc_text,
const unsigned char *grip, unsigned char **shadow_info,
cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
gcry_sexp_t *result)
gcry_sexp_t *result, char **r_passphrase)
{
int rc;
unsigned char *buf;
@ -518,6 +546,8 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
*result = NULL;
if (shadow_info)
*shadow_info = NULL;
if (r_passphrase)
*r_passphrase = NULL;
rc = read_key_file (grip, &s_skey);
if (rc)
@ -579,7 +609,7 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (!rc)
{
rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
cache_mode, lookup_ttl);
cache_mode, lookup_ttl, r_passphrase);
if (rc)
log_error ("failed to unprotect the secret key: %s\n",
gpg_strerror (rc));
@ -626,6 +656,11 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
if (rc || got_shadow_info)
{
xfree (buf);
if (r_passphrase)
{
xfree (*r_passphrase);
*r_passphrase = NULL;
}
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",
(unsigned int)erroff, gpg_strerror (rc));
if (r_passphrase)
{
xfree (*r_passphrase);
*r_passphrase = NULL;
}
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
user opted not to use a passphrase NULL will be stored there. The
user needs to free the returned string. In case of an error and
error code is returned and NULL stored at R_PASSPHRASE. */
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
agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
char **r_passphrase)
char **r_passphrase, int *r_cancel_all)
{
gpg_error_t err;
const char *text1 = prompt;
@ -314,7 +316,7 @@ agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
pi2->check_cb_arg = pi->pin;
next_try:
err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi, r_cancel_all);
initial_errtext = NULL;
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. */
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)
{ /* The re-entered one did not match and the user did not
hit cancel. */
@ -379,7 +381,7 @@ agent_genkey (ctrl_t ctrl, const char *cache_nonce,
rc = agent_ask_new_passphrase (ctrl,
_("Please enter the passphrase to%0A"
"to protect your new key"),
&passphrase);
&passphrase, NULL);
if (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,
_("Please enter the new passphrase"),
&passphrase);
&passphrase, NULL);
if (!rc)
{
rc = store_key (s_skey, passphrase, 1);

View File

@ -440,6 +440,11 @@ remove_socket (char *name)
static void
cleanup (void)
{
static int done;
if (done)
return;
done = 1;
deinitialize_module_cache ();
remove_socket (socket_name);
remove_socket (socket_name_ssh);
@ -724,6 +729,12 @@ main (int argc, char **argv )
if( parse_debug )
log_info (_("NOTE: no default option file `%s'\n"),
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
{
@ -811,10 +822,15 @@ main (int argc, char **argv )
fclose( configfp );
configfp = NULL;
/* 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;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (log_get_errorcount(0))
@ -1262,6 +1278,12 @@ void
agent_exit (int rc)
{
/*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
/* at this time a bit annoying */
if (opt.debug & DBG_MEMSTAT_VALUE)
@ -1337,8 +1359,8 @@ reread_configuration (void)
fp = fopen (config_filename, "r");
if (!fp)
{
log_error (_("option file `%s': %s\n"),
config_filename, strerror(errno) );
log_info (_("option file `%s': %s\n"),
config_filename, strerror(errno) );
return;
}

View File

@ -14,7 +14,8 @@ the ~/.gnupg home directory. This directory is named
and should have permissions 700.
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
==============================
@ -166,21 +167,23 @@ This format is used to transfer keys between gpg and gpg-agent.
(openpgp-private-key
(version V)
(protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)
(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).
* 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
the secrect key parameters are encrypted if the "protection" list is
given. To make this more explicit each parameter is preceded by a
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"
the old 16 bit checksum is used and if it is "none" no protection at
all is used.
the old 16 bit checksum (above) is used and if it is "none" no
protection at all is used.
* PROTALGO is a Libgcrypt style cipher algorithm name
* IV is the initialization verctor.
* 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.
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:
======

View File

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

View File

@ -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,
&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)
{
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
a 20 byte buffer. This function is suitable for any algorithms. */
/* Calculate the MIC for a private key or shared secret S-expression.
SHA1HASH should point to a 20 byte buffer. This function is
suitable for all algorithms. */
static int
calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
{
const unsigned char *hash_begin, *hash_end;
const unsigned char *s;
size_t n;
int is_shared_secret;
s = plainkey;
if (*s != '(')
@ -207,16 +209,23 @@ calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
n = snext (&s);
if (!n)
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);
if (*s != '(')
return gpg_error (GPG_ERR_UNKNOWN_SEXP);
hash_begin = s;
s++;
n = snext (&s);
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* skip over the algorithm name */
if (!is_shared_secret)
{
s++;
n = snext (&s);
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
s += n; /* Skip the algorithm name. */
}
while (*s == '(')
{
@ -955,7 +964,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
xfree (final);
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. */
if (cutlen)
{

View File

@ -289,6 +289,13 @@ test_agent_get_shadow_info (void)
}
static void
test_agent_protect_shared_secret (void)
{
}
int
@ -305,6 +312,7 @@ main (int argc, char **argv)
test_make_shadow_info ();
test_agent_shadow_key ();
test_agent_get_shadow_info ();
test_agent_protect_shared_secret ();
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>
* homedir.c (gnupg_bindir) [W32CE]: Change to bin/.

View File

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

View File

@ -68,6 +68,9 @@
#ifndef EAFNOSUPPORT
# define EAFNOSUPPORT EINVAL
#endif
#ifndef INADDR_NONE /* Slowaris is missing that. */
#define INADDR_NONE ((unsigned long)(-1))
#endif /*INADDR_NONE*/
#ifdef HAVE_W32_SYSTEM
#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
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. */
static inline int
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_MISSING_CERT: errstr = "11"; break;
case GPG_ERR_MISSING_ISSUER_CERT: errstr = "12"; break;
default: errstr = "0"; break;
}

View File

@ -33,6 +33,12 @@
#ifndef GPG_ERR_NOT_INITIALIZED
#define GPG_ERR_NOT_INITIALIZED 184
#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. */

View File

@ -396,7 +396,7 @@ AH_BOTTOM([
# define GNUPG_DEFAULT_HOMEDIR "/gnupg"
# endif
#elif defined(__VMS)
#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg"
#define GNUPG_DEFAULT_HOMEDIR "/SYS$LOGIN/gnupg"
#else
#define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
#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>
* 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"),
gpg_strerror (err));
/* Use a better understandable error code. */
err = gpg_error (GPG_ERR_MISSING_CERT);
err = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
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>
* gpg.texi (OpenPGP Options): Clarify that --force-v3-sigs

View File

@ -586,7 +586,8 @@ more arguments in future versions.
8 := "Policy mismatch"
9 := "Not a secret key"
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
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
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"
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
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
such a certificate. You may use the @code{relax} flag in
@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}
@opindex log-file
Append all logging output to @var{file}. This is very helpful in
seeing what the agent actually does.
Append all logging output to @var{file}. This is very helpful in seeing
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}
@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.
@example
HAVEKEY @var{keygrip}
HAVEKEY @var{keygrips}
@end example
The Agent answers either with OK or @code{No_Secret_Key} (208). The
caller may want to check for other error codes as well.
The agent answers either with OK or @code{No_Secret_Key} (208). The
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

View File

@ -3,6 +3,11 @@
@c This is part of the GnuPG manual.
@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
@chapter Invoking GPG
@cindex GPG command options
@ -68,18 +73,19 @@ implementation.
@ifset gpgone
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
@ifclear gpgone
In contrast to the standalone version @command{gpg}, which is more
suited for server and embedded platforms, this version is installed
under the name @command{gpg2} and more targeted to the desktop as it
requires several other modules to be installed. The standalone version
will be kept maintained and it is possible to install both versions on
the same system. If you need to use different configuration files, you
should make use of something like @file{gpg.conf-2} instead of just
@file{gpg.conf}.
suited for server and embedded platforms, this version is commonly
installed under the name @command{gpg2} and more targeted to the desktop
as it requires several other modules to be installed. The standalone
version will be kept maintained and it is possible to install both
versions on the same system. If you need to use different configuration
files, you should make use of something like @file{gpg.conf-2} instead
of just @file{gpg.conf}.
@end ifclear
@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
primary key useless; this is a GNU extension to OpenPGP and other
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
an exported key with an older OpenPGP implementation.
@end ifclear
@item --import
@itemx --fast-import
@ -1550,6 +1558,7 @@ key signer (defaults to 3)
@item --max-cert-depth @code{n}
Maximum depth of a certification chain (default is 5).
@ifclear gpgtwoone
@item --simple-sk-checksum
Secret keys are integrity protected by using a SHA-1 checksum. This
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
to change the passphrase on the key (even changing it to the same
value is acceptable).
@end ifclear
@item --no-sig-cache
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
"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
When using the @option{--export-secret-subkeys} command, this option resets
the passphrases for all exported subkeys to empty. This is useful
when the exported subkey is to be used on an unattended machine where
a passphrase doesn't necessarily make sense. Defaults to no.
@end ifclear
@item export-clean
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
encryption and signing services on X.509 certificates and the CMS
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.
@manpause
@ -286,7 +286,7 @@ smartcard is not yet supported.
@node GPGSM Options
@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.
@menu
@ -566,10 +566,9 @@ certificate.
@item --include-certs @var{n}
@opindex include-certs
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
the signers cert (this is the default) and all other positive
values include up to @var{n} certificates starting with the signer cert.
The default is -2.
-1 includes all certs, 0 does not include any certs, 1 includes only the
signers cert and all other positive values include up to @var{n}
certificates starting with the signer cert. The default is -2.
@item --cipher-algo @var{oid}
@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>
* options.skel: Make the example for force-v3-sigs match

View File

@ -26,10 +26,10 @@
#include <ctype.h>
#include "gpg.h"
#include "util.h"
#include "packet.h"
#include "status.h"
#include "iobuf.h"
#include "util.h"
#include "cipher.h"
#include "i18n.h"
#include "options.h"
@ -71,8 +71,16 @@ build_packet( IOBUF out, PACKET *pkt )
log_debug("build_packet() type=%d\n", pkt->pkttype );
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_ENCRYPTED:
case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;

View File

@ -902,6 +902,26 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
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
mechanism. */
int
@ -942,14 +962,11 @@ agent_scd_pksign (const char *serialno, int hashalgo,
return rc;
init_membuf (&data, 1024);
#if 0
if (!hashalgo) /* Temporary test hack. */
snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
else
#endif
snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
serialno);
/* if (!hashalgo) /\* Temporary test hack. *\/ */
/* snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno); */
/* else */
snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s",
hash_algo_option (hashalgo), serialno);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL);
@ -1325,6 +1342,57 @@ agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk)
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
@ -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
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. */
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. */
gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
char **r_serialno);
@ -174,6 +179,11 @@ gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
char **cache_nonce_addr,
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*/

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
the default keyserver. */
static int
fetch_url(void)
fetch_url (ctrl_t ctrl)
{
int rc;
struct agent_card_info_s info;
@ -751,13 +751,13 @@ fetch_url(void)
event, the fpr/keyid is not meaningful for straight
HTTP fetches, but using it allows the card to point
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);
}
}
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
Key creation is not handled here. */
void
card_edit (strlist_t commands)
card_edit (ctrl_t ctrl, strlist_t commands)
{
enum cmdids cmd = cmdNOP;
int have_commands = !!commands;
@ -1924,7 +1924,7 @@ card_edit (strlist_t commands)
break;
case cmdFETCH:
fetch_url();
fetch_url (ctrl);
break;
case cmdLOGIN:

View File

@ -300,7 +300,7 @@ release_context (compress_filter_context_t *ctx)
* Handle a compressed packet
*/
int
handle_compressed( void *procctx, PKT_compressed *cd,
handle_compressed (ctrl_t ctrl, void *procctx, PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru )
{
compress_filter_context_t *cfx;
@ -315,7 +315,7 @@ handle_compressed( void *procctx, PKT_compressed *cd,
if( callback )
rc = callback(cd->buf, passthru );
else
rc = proc_packets(procctx, cd->buf);
rc = proc_packets (ctrl,procctx, cd->buf);
cd->buf = NULL;
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.
*/
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;
byte *p;
@ -191,7 +191,7 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
else
iobuf_push_filter ( ed->buf, decode_filter, dfx );
proc_packets ( procctx, ed->buf );
proc_packets (ctrl, procctx, ed->buf );
ed->buf = NULL;
if (dfx->eof_seen > 1 )
rc = gpg_error (GPG_ERR_INV_PACKET);

View File

@ -43,7 +43,7 @@
* rejects files which don't begin with an encrypted message.
*/
int
decrypt_message (const char *filename)
decrypt_message (ctrl_t ctrl, const char *filename)
{
IOBUF fp;
armor_filter_context_t *afx = NULL;
@ -86,7 +86,7 @@ decrypt_message (const char *filename)
no_out = 1;
opt.outfile = "-";
}
rc = proc_encryption_packets ( NULL, fp );
rc = proc_encryption_packets (ctrl, NULL, fp );
if (no_out)
opt.outfile = NULL;
@ -100,7 +100,7 @@ decrypt_message (const char *filename)
/* Same as decrypt_message but takes a file descriptor for input and
output. */
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;
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);
fclose (opt.outfp);
@ -170,7 +170,7 @@ decrypt_message_fd (int input_fd, int output_fd)
void
decrypt_messages (int nfiles, char *files[])
decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
{
IOBUF fp;
armor_filter_context_t *afx = NULL;
@ -251,7 +251,7 @@ decrypt_messages (int nfiles, char *files[])
push_armor_filter ( afx, fp );
}
}
rc = proc_packets(NULL, fp);
rc = proc_packets (ctrl,NULL, fp);
iobuf_close(fp);
if (rc)
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.
*/
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,
int outputfd)
{
@ -503,7 +503,7 @@ encrypt_crypt (int filefd, const char *filename,
pk_list = provided_keys;
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);
return rc;
@ -939,7 +939,7 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out)
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;
@ -963,7 +963,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
}
line[strlen(line)-1] = '\0';
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)
log_error ("encryption of `%s' failed: %s\n",
print_fname_stdin(line), g10_errstr(rc) );
@ -975,7 +975,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
while (nfiles--)
{
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",
print_fname_stdin(*files), g10_errstr(rc) );
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,
* 2005 Free Software Foundation, Inc.
* 2005, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -34,7 +34,7 @@
#include "main.h"
#include "i18n.h"
#include "trustdb.h"
#include "call-agent.h"
/* An object to keep track of subkeys. */
struct subkey_list_s
@ -45,10 +45,12 @@ struct subkey_list_s
typedef struct subkey_list_s *subkey_list_t;
static int do_export( strlist_t users, int secret, unsigned int options );
static int do_export_stream( IOBUF out, strlist_t users, int secret,
KBNODE *keyblock_out, unsigned int options,
int *any );
static int do_export (ctrl_t ctrl,
strlist_t users, int secret, unsigned int options );
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);
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)")},
{"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
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,
N_("remove unusable parts from key during export")},
{"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.
* If USERS is NULL, the complete ring will be exported. */
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
*/
int
export_pubkeys_stream( IOBUF out, strlist_t users,
KBNODE *keyblock_out, unsigned int options )
export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
kbnode_t *keyblock_out, unsigned int options )
{
int any, rc;
int any, rc;
rc = do_export_stream( out, users, 0, keyblock_out, options, &any );
if( !rc && !any )
rc = -1;
return rc;
rc = do_export_stream (ctrl, out, users, 0, keyblock_out, options, &any);
if (!rc && !any)
rc = -1;
return rc;
}
int
export_seckeys( strlist_t users )
export_seckeys (ctrl_t ctrl, strlist_t users )
{
/* Use only relevant options for the secret key. */
unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
return do_export( users, 1, options );
return do_export (ctrl, users, 1, options);
}
int
export_secsubkeys( strlist_t users )
export_secsubkeys (ctrl_t ctrl, strlist_t users )
{
/* Use only relevant options for the secret key. */
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
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;
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());
}
rc = do_export_stream ( out, users, secret, NULL, options, &any );
rc = do_export_stream (ctrl, out, users, secret, NULL, options, &any );
if ( rc || !any )
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
contains a pointer to the first keyblock found and exported. No
other keyblocks are exported. The caller must free it. */
/* Return a canonicalized public key algoithms. This is used to
compare different flavors of algorithms (e.g. ELG and ELG_E are
considered the same). */
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)
{
gpg_error_t err = 0;
@ -292,6 +611,7 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
KEYDB_HANDLE kdbhd;
strlist_t sl;
int indent = 0;
gcry_cipher_hd_t cipherhd = NULL;
*any = 0;
init_packet (&pkt);
@ -330,21 +650,51 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
if (secret)
{
log_error (_("exporting secret keys not allowed\n"));
err = G10ERR_GENERAL;
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
}
#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)))
{
int sha1_warned = 0;
int skip_until_subkey = 0;
u32 keyid[2];
PKT_public_key *pk;
if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* Read the keyblock. */
release_kbnode (keyblock);
keyblock = NULL;
err = keydb_get_keyblock (kdbhd, &keyblock);
if (err)
{
@ -352,60 +702,57 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
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. */
if( secret == 2
&& pk->seckey_info && !pk->seckey_info->is_protected )
/* No v3 keys with GNU mode 1001. */
if (secret == 2 && pk->version == 3)
{
log_info (_("key %s: not protected - skipped\n"),
log_info (_("key %s: PGP 2.x style key - skipped\n"),
keystr (keyid));
continue;
}
/* No v3 keys with GNU mode 1001. */
if( secret == 2 && pk->version == 3 )
/* The agent does not yet allow to export v3 packets. It is
actually questionable whether we should allow them at
all. */
if (pk->version == 3)
{
log_info(_("key %s: PGP 2.x style key - skipped\n"),
keystr (keyid));
log_info ("key %s: PGP 2.x style key (v3) export "
"not yet supported - skipped\n", keystr (keyid));
continue;
}
}
/* It does not make sense to export a key with a primary
key on card using a non-key stub. We simply skip those
keys when used with --export-secret-subkeys. */
if (secret == 2
&& pk->seckey_info && pk->seckey_info->is_protected
&& pk->seckey_info->s2k.mode == 1002 )
{
log_info(_("key %s: key material on-card - skipped\n"),
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);
}
/* Always do the cleaning on the public key part if requested.
Note that we don't yet set this option if we are exporting
secret keys. 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. */
for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{
if (skip_until_subkey)
{
if (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
skip_until_subkey = 0;
else
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
request it). */
if (desc[descindex].exact
&& (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY))
&& node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
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.
We need this whole mess because the import
function is not able to merge secret keys and
thus it is useless to output them as two separate
keys and have import merge them. */
function of GnuPG < 2.1 is not able to merge
secret keys and thus it is useless to output them
as two separate keys and have import merge them. */
if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */
else
@ -508,88 +854,181 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
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
* primary key, this is done by temporary switching to
* GNU protection mode 1001. */
int save_mode = node->pkt->pkt.public_key->seckey_info->s2k.mode;
node->pkt->pkt.public_key->seckey_info->s2k.mode = 1001;
if ((options&EXPORT_SEXP_FORMAT))
err = build_sexp (out, node->pkt, &indent);
u32 subkidbuf[2], *subkid;
char *hexgrip, *serialno;
pk = node->pkt->pkt.public_key;
if (node->pkt->pkttype == PKT_PUBLIC_KEY)
subkid = NULL;
else
err = build_packet (out, node->pkt);
node->pkt->pkt.public_key->seckey_info->s2k.mode = save_mode;
}
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; */
{
keyid_from_pk (pk, subkidbuf);
subkid = subkidbuf;
}
/* sk_save = node->pkt->pkt.secret_key; */
/* sk = copy_secret_key (NULL, sk_save); */
/* node->pkt->pkt.secret_key = sk; */
if (pk->seckey_info)
{
log_error ("key %s: oops: seckey_info already set"
" - skipped\n", keystr_with_sub (keyid, subkid));
skip_until_subkey = 1;
continue;
}
/* log_info (_("about to export an unprotected subkey\n")); */
/* switch (is_secret_key_protected (sk)) */
/* { */
/* case -1: */
/* err = gpg_error (GPG_ERR_PUBKEY_ALGO); */
/* break; */
/* case 0: */
/* break; */
/* default: */
/* if (sk->protect.s2k.mode == 1001) */
/* ; /\* 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; */
/* } */
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;
}
/* if ((options&EXPORT_SEXP_FORMAT)) */
/* err = build_sexp (out, node->pkt, &indent); */
/* else */
/* err = build_packet (out, node->pkt); */
if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
{
/* We are asked not to export the secret parts of
the primary key. Make up an error code to create
the stub. */
err = GPG_ERR_NOT_FOUND;
serialno = NULL;
}
else
err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
/* node->pkt->pkt.secret_key = sk_save; */
/* free_secret_key (sk); */
if ((!err && serialno)
&& secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
{
/* 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;
}
ski->is_protected = 1;
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
{
/* 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))
err = build_sexp (out, node->pkt, &indent);
else
@ -602,6 +1041,9 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
node->pkt->pkttype, gpg_strerror (err));
goto leave;
}
if (!skip_until_subkey)
*any = 1;
}
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');
}
++*any;
if(keyblock_out)
if (keyblock_out)
{
*keyblock_out=keyblock;
*keyblock_out = keyblock;
break;
}
}
@ -624,10 +1065,11 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
iobuf_put (out, ')');
iobuf_put (out, '\n');
}
if( err == -1 )
if (err == -1)
err = 0;
leave:
gcry_cipher_close (cipherhd);
release_subkey_list (subkey_list);
xfree(desc);
keydb_release (kdbhd);
@ -672,6 +1114,10 @@ do_export_stream (iobuf_t out, strlist_t users, int secret,
static int
build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
{
(void)out;
(void)pkt;
(void)indent;
/* FIXME: Not yet implemented. */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
/* PKT_secret_key *sk = pkt->pkt.secret_key; */
@ -759,4 +1205,3 @@ build_sexp (iobuf_t out, PACKET *pkt, int *indent)
}
return rc;
}

View File

@ -25,9 +25,9 @@
#include <assert.h>
#include "gpg.h"
#include "util.h"
#include "packet.h"
#include "../common/iobuf.h"
#include "util.h"
#include "cipher.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
--auto-key-locate. */
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,
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:
mechanism = "DNS CERT";
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--;
break;
case AKL_PKA:
mechanism = "PKA";
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--;
break;
case AKL_LDAP:
mechanism = "LDAP";
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--;
break;
@ -797,9 +797,8 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk,
{
mechanism = opt.keyserver->uri;
glo_ctrl.in_auto_key_retrieve++;
rc =
keyserver_import_name (name, &fpr, &fpr_len,
opt.keyserver);
rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
opt.keyserver);
glo_ctrl.in_auto_key_retrieve--;
}
else
@ -816,7 +815,8 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk,
mechanism = akl->spec->uri;
keyserver = keyserver_match (akl->spec);
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--;
}
break;

View File

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

View File

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

View File

@ -64,10 +64,11 @@ static int import (ctrl_t ctrl,
IOBUF inp, const char* fname, struct stats_s *stats,
unsigned char **fpr, size_t *fpr_len, unsigned int options);
static int read_block( IOBUF a, PACKET **pending_pkt, KBNODE *ret_root );
static void revocation_present(KBNODE keyblock);
static int import_one(const char *fname, KBNODE keyblock,struct stats_s *stats,
unsigned char **fpr,size_t *fpr_len,
unsigned int options,int from_sk);
static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
static int import_one (ctrl_t ctrl,
const char *fname, KBNODE keyblock,struct stats_s *stats,
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,
struct stats_s *stats, unsigned int options);
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) )) {
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 )
rc = import_secret_one (ctrl, fname, keyblock, stats, options);
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
@ -614,9 +616,9 @@ check_prefs_warning(PKT_public_key *pk)
}
static void
check_prefs(KBNODE keyblock)
check_prefs (ctrl_t ctrl, kbnode_t keyblock)
{
KBNODE node;
kbnode_t node;
PKT_public_key *pk;
int problem=0;
@ -711,7 +713,7 @@ check_prefs(KBNODE keyblock)
append_to_strlist(&sl,"updpref");
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(locusr);
}
@ -728,7 +730,8 @@ check_prefs(KBNODE keyblock)
* which called gpg.
*/
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,
int from_sk )
{
@ -1060,15 +1063,15 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
if (mod_key)
{
revocation_present (keyblock_orig);
revocation_present (ctrl, keyblock_orig);
if (!from_sk && have_secret_key_with_kid (keyid))
check_prefs (keyblock_orig);
check_prefs (ctrl, keyblock_orig);
}
else if (new_key)
{
revocation_present (keyblock);
revocation_present (ctrl, keyblock);
if (!from_sk && have_secret_key_with_kid (keyid))
check_prefs (keyblock);
check_prefs (ctrl, keyblock);
}
release_kbnode( keyblock_orig );
@ -1425,7 +1428,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
keystr_from_pk (pk));
else
{
import_one (fname, pub_keyblock, stats,
import_one (ctrl, fname, pub_keyblock, stats,
NULL, NULL, opt.import_options, 1);
/* Fixme: We should check for an invalid keyblock and
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));
if (is_status_enabled ())
print_import_ok (pk, 1|16);
check_prefs (node);
check_prefs (ctrl, node);
}
release_kbnode (node);
}
@ -2051,10 +2054,10 @@ collapse_uids( KBNODE *keyblock )
present. This may be called without the benefit of merge_xxxx so
you can't rely on pk->revkey and friends. */
static void
revocation_present(KBNODE keyblock)
revocation_present (ctrl_t ctrl, kbnode_t keyblock)
{
KBNODE onode,inode;
PKT_public_key *pk=keyblock->pkt->pkt.public_key;
kbnode_t onode, inode;
PKT_public_key *pk = keyblock->pkt->pkt.public_key;
for(onode=keyblock->next;onode;onode=onode->next)
{
@ -2106,9 +2109,10 @@ revocation_present(KBNODE keyblock)
log_info(_("WARNING: key %s may be revoked:"
" fetching revocation key %s\n"),
tempkeystr,keystr(keyid));
keyserver_import_fprint(sig->revkey[idx]->fpr,
MAX_FINGERPRINT_LEN,
opt.keyserver);
keyserver_import_fprint (ctrl,
sig->revkey[idx]->fpr,
MAX_FINGERPRINT_LEN,
opt.keyserver);
/* Do we have it now? */
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 );
void release_pk_list (PK_LIST pk_list);
int build_pk_list (strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use);
gpg_error_t find_and_check_key (const char *name, unsigned int use,
int build_pk_list (ctrl_t ctrl,
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 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_fast ( PKT_public_key *pk, 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,
int include_unusable, int no_akl );
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_clean (KBNODE keyblock, int self_only);
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_backsign (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. */
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)
{
enum cmdids cmd = 0;
@ -1599,7 +1599,6 @@ keyedit_menu (const char *username, strlist_t locusr,
int modified = 0;
int toggle;
int have_commands = !!commands;
ctrl_t ctrl = NULL; /* Dummy for now. */
if (opt.command_fd != -1)
;
@ -1623,7 +1622,7 @@ keyedit_menu (const char *username, strlist_t locusr,
#endif
/* 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)
goto leave;
if (fix_keyblock (keyblock))
@ -2095,7 +2094,7 @@ keyedit_menu (const char *username, strlist_t locusr,
if (ascii_strcasecmp (arg_string, "sensitive") == 0)
sensitive = 1;
if (menu_addrevoker (keyblock, sensitive))
if (menu_addrevoker (ctrl, keyblock, sensitive))
{
redisplay = 1;
modified = 1;
@ -2886,9 +2885,10 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
if (pk->is_revoked)
{
char *user = get_user_id_string_native (pk->revoked.keyid);
const char *algo = gcry_pk_algo_name (pk->revoked.algo);
tty_printf (_("This key was revoked on %s by %s key %s\n"),
revokestr_from_pk (pk), algo ? algo : "?", user);
tty_printf (_("The following key was revoked on"
" %s by %s key %s\n"),
revokestr_from_pk (pk),
gcry_pk_algo_name (pk->revoked.algo), user);
xfree (user);
}
@ -3444,7 +3444,7 @@ menu_delkey (KBNODE pub_keyblock)
* the keyblock. Returns true if there is a new revoker.
*/
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 *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
GnuPG both can handle a designated revocation from a subkey. */
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)
{
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++)
{
xfree (array[i]);
gcry_mpi_release (array[i]);
array[i] = NULL;
}
gcry_sexp_release (list);

View File

@ -242,9 +242,12 @@ keystr_with_sub (u32 *main_kid, u32 *sub_kid)
char *p;
mem2str (buffer, keystr (main_kid), KEYID_STR_SIZE);
p = buffer + strlen (buffer);
*p++ = '/';
mem2str (p, keystr (sub_kid), KEYID_STR_SIZE);
if (sub_kid)
{
p = buffer + strlen (buffer);
*p++ = '/';
mem2str (p, keystr (sub_kid), KEYID_STR_SIZE);
}
return buffer;
}
@ -262,9 +265,10 @@ const char *
keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk)
{
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_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);
struct sig_stats
@ -61,7 +61,7 @@ static estream_t attrib_fp;
With LOCATE_MODE set the locate algorithm is used to find a
key. */
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)
{
@ -107,7 +107,7 @@ public_key_list (strlist_t list, int locate_mode)
check_trustdb_stale ();
if (locate_mode)
locate_one (list);
locate_one (ctrl, list);
else if (!list)
list_all (0);
else
@ -116,8 +116,10 @@ public_key_list (strlist_t list, int locate_mode)
void
secret_key_list (strlist_t list)
secret_key_list (ctrl_t ctrl, strlist_t list)
{
(void)ctrl;
check_trustdb_stale ();
if (!list)
@ -533,7 +535,7 @@ list_one (strlist_t names, int secret)
static void
locate_one (strlist_t names)
locate_one (ctrl_t ctrl, strlist_t names)
{
int rc = 0;
strlist_t sl;
@ -545,7 +547,7 @@ locate_one (strlist_t names)
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 (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,
unsigned int configlineno);
struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig);
int keyserver_export(strlist_t users);
int keyserver_import(strlist_t users);
int keyserver_import_fprint(const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver);
int keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver);
int keyserver_refresh(strlist_t users);
int keyserver_search(strlist_t tokens);
int keyserver_fetch(strlist_t urilist);
int keyserver_import_cert(const char *name,
unsigned char **fpr,size_t *fpr_len);
int keyserver_import_pka(const char *name,unsigned char **fpr,size_t *fpr_len);
int keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
int keyserver_import_ldap(const char *name,
unsigned char **fpr,size_t *fpr_len);
int keyserver_export (ctrl_t ctrl, strlist_t users);
int keyserver_import (ctrl_t ctrl, strlist_t users);
int keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver);
int keyserver_import_keyid (ctrl_t ctrl, u32 *keyid,
struct keyserver_spec *keyserver);
int keyserver_refresh (ctrl_t ctrl, strlist_t users);
int keyserver_search (ctrl_t ctrl, strlist_t tokens);
int keyserver_fetch (ctrl_t ctrl, strlist_t urilist);
int keyserver_import_cert (ctrl_t ctrl, const char *name,
unsigned char **fpr,size_t *fpr_len);
int keyserver_import_pka (ctrl_t ctrl,
const char *name,unsigned char **fpr,size_t *fpr_len);
int keyserver_import_name (ctrl_t ctrl,
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_ */

View File

@ -89,10 +89,10 @@ static struct parse_options keyserver_opts[]=
{NULL,0,NULL,NULL}
};
static int keyserver_work(enum ks_action action,strlist_t list,
KEYDB_SEARCH_DESC *desc,int count,
unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
static int keyserver_work (ctrl_t ctrl, enum ks_action action,strlist_t list,
KEYDB_SEARCH_DESC *desc,int count,
unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver);
/* Reasonable guess */
#define DEFAULT_MAX_CERT_SIZE 16384
@ -732,7 +732,8 @@ parse_keyrec(char *keystring)
(cosmetics, really) and to better take advantage of the keyservers
that can do multiple fetches in one go (LDAP). */
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;
@ -765,8 +766,8 @@ show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
while((num=strsep(&split," ,"))!=NULL)
if(atoi(num)>=1 && atoi(num)<=numdesc)
keyserver_work(KS_GET,NULL,&desc[atoi(num)-1],1,
NULL,NULL,opt.keyserver);
keyserver_work (ctrl, KS_GET,NULL,&desc[atoi(num)-1],1,
NULL,NULL,opt.keyserver);
xfree(answer);
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
of z" messages. searchstr should be UTF-8 (rather than native). */
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;
unsigned int maxlen,buflen,numlines=0;
@ -872,7 +873,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr)
for(;;)
{
if(show_prompt(desc,i,validcount?count:0,localstr))
if (show_prompt (ctrl, desc, i, validcount?count:0, localstr))
break;
validcount=0;
}
@ -901,7 +902,7 @@ keyserver_search_prompt(IOBUF buffer,const char *searchstr)
/* screen_lines - 1 for the prompt. */
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;
else
numlines=0;
@ -977,9 +978,10 @@ direct_uri_map(const char *scheme,unsigned int is_direct)
#define KEYSERVER_ARGS_NOKEEP " -o \"%o\" \"%i\""
static int
keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
int count,int *prog,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
keyserver_spawn (ctrl_t ctrl,
enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
int count,int *prog,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
{
int ret=0,i,gotversion=0,outofband=0;
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
way? */
if(export_pubkeys_stream(buffer,temp,&block,
opt.keyserver_options.export_options)==-1)
if(export_pubkeys_stream (ctrl, buffer,temp,&block,
opt.keyserver_options.export_options)==-1)
iobuf_close(buffer);
else
{
@ -1510,7 +1512,7 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
break;
case KS_SEARCH:
keyserver_search_prompt(spawn->fromchild,searchstr);
keyserver_search_prompt (ctrl, spawn->fromchild,searchstr);
break;
default:
@ -1529,9 +1531,10 @@ keyserver_spawn(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
}
static int
keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
int count,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
keyserver_work (ctrl_t ctrl,
enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
int count,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
{
int rc=0,ret=0;
@ -1549,7 +1552,8 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
#else
/* 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)
{
switch(ret)
@ -1599,7 +1603,7 @@ keyserver_work(enum ks_action action,strlist_t list,KEYDB_SEARCH_DESC *desc,
}
int
keyserver_export(strlist_t users)
keyserver_export (ctrl_t ctrl, strlist_t users)
{
gpg_error_t err;
strlist_t sl=NULL;
@ -1624,7 +1628,7 @@ keyserver_export(strlist_t users)
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);
}
@ -1632,7 +1636,7 @@ keyserver_export(strlist_t users)
}
int
keyserver_import(strlist_t users)
keyserver_import (ctrl_t ctrl, strlist_t users)
{
gpg_error_t err;
KEYDB_SEARCH_DESC *desc;
@ -1663,7 +1667,8 @@ keyserver_import(strlist_t users)
}
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);
@ -1671,8 +1676,8 @@ keyserver_import(strlist_t users)
}
int
keyserver_import_fprint(const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver)
keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver)
{
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
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
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;
@ -1703,7 +1709,7 @@ keyserver_import_keyid(u32 *keyid,struct keyserver_spec *keyserver)
desc.u.kid[0]=keyid[0];
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 */
@ -1865,7 +1871,7 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
usernames to refresh only part of the keyring. */
int
keyserver_refresh(strlist_t users)
keyserver_refresh (ctrl_t ctrl, strlist_t users)
{
int rc,count,numdesc,fakev3=0;
KEYDB_SEARCH_DESC *desc;
@ -1908,7 +1914,8 @@ keyserver_refresh(strlist_t users)
Note that a preferred keyserver without a scheme://
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)
log_info(_("WARNING: unable to refresh key %s"
" via %s: %s\n"),keystr_from_desc(&desc[i]),
@ -1938,7 +1945,8 @@ keyserver_refresh(strlist_t users)
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);
@ -1954,16 +1962,16 @@ keyserver_refresh(strlist_t users)
}
int
keyserver_search(strlist_t tokens)
keyserver_search (ctrl_t ctrl, strlist_t tokens)
{
if(tokens)
return keyserver_work(KS_SEARCH,tokens,NULL,0,NULL,NULL,opt.keyserver);
else
return 0;
if (tokens)
return keyserver_work (ctrl, KS_SEARCH, tokens, NULL, 0,
NULL, NULL, opt.keyserver);
return 0;
}
int
keyserver_fetch(strlist_t urilist)
keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
{
KEYDB_SEARCH_DESC desc;
strlist_t sl;
@ -1988,7 +1996,7 @@ keyserver_fetch(strlist_t urilist)
{
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)
log_info (_("WARNING: unable to fetch URI %s: %s\n"),
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 */
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;
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);
if(spec)
{
rc=keyserver_import_fprint(*fpr,*fpr_len,spec);
rc = keyserver_import_fprint (ctrl, *fpr,*fpr_len,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
our --keyserver */
rc=keyserver_import_fprint(*fpr,*fpr_len,opt.keyserver);
rc = keyserver_import_fprint (ctrl, *fpr,*fpr_len,opt.keyserver);
}
else
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
fingerprint in fpr. */
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;
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);
if (spec)
{
rc = keyserver_import_fprint (*fpr, 20, spec);
rc = keyserver_import_fprint (ctrl, *fpr, 20, spec);
free_keyserver_spec (spec);
}
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 */
int
keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len,
struct keyserver_spec *keyserver)
keyserver_import_name (ctrl_t ctrl, const char *name,
unsigned char **fpr, size_t *fpr_len,
struct keyserver_spec *keyserver)
{
strlist_t list=NULL;
int rc;
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);
@ -2137,7 +2149,8 @@ keyserver_import_name(const char *name,unsigned char **fpr,size_t *fpr_len,
/* Import a key by name using LDAP */
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;
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);
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);

View File

@ -192,10 +192,11 @@ void display_online_help( const char *keyword );
int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
int encrypt_symmetric (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,
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,
iobuf_t a, byte *buf, size_t *ret_len);
@ -203,7 +204,7 @@ int encrypt_filter (void *opaque, int control,
/*-- sign.c --*/
int complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md,
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 clearsign_file( const char *fname, strlist_t locusr, const char *outfile );
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 );
/*-- 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 );
void keyedit_passwd (const char *username);
void show_basic_key_info (KBNODE keyblock);
@ -280,11 +281,11 @@ int collapse_uids( KBNODE *keyblock );
/*-- export.c --*/
int parse_export_options(char *str,unsigned int *options,int noisy);
int export_pubkeys( strlist_t users, unsigned int options );
int export_pubkeys_stream( iobuf_t out, strlist_t users,
KBNODE *keyblock_out, unsigned int options );
int export_seckeys( strlist_t users );
int export_secsubkeys( strlist_t users );
int export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options );
int export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
kbnode_t *keyblock_out, unsigned int options );
int export_seckeys (ctrl_t ctrl, strlist_t users);
int export_secsubkeys (ctrl_t ctrl, strlist_t users);
/* dearmor.c --*/
int dearmor_file( const char *fname );
@ -300,8 +301,8 @@ struct revocation_reason_info *
void release_revocation_reason_info( struct revocation_reason_info *reason );
/*-- keylist.c --*/
void public_key_list( strlist_t list, int locate_mode );
void secret_key_list( strlist_t list );
void public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode );
void secret_key_list (ctrl_t ctrl, strlist_t list );
void print_subpackets_colon(PKT_signature *sig);
void reorder_keyblock (KBNODE keyblock);
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 --*/
void print_file_status( int status, const char *name, int what );
int verify_signatures( int nfiles, char **files );
int verify_files( int nfiles, char **files );
int verify_signatures (ctrl_t ctrl, 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);
/*-- decrypt.c --*/
int decrypt_message( const char *filename );
gpg_error_t decrypt_message_fd (int input_fd, int output_fd);
void decrypt_messages(int nfiles, char *files[]);
int decrypt_message (ctrl_t ctrl, const char *filename );
gpg_error_t decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd);
void decrypt_messages (ctrl_t ctrl, int nfiles, char *files[]);
/*-- plaintext.c --*/
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 --*/
void change_pin (int no, int allow_admin);
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_store_subkey (KBNODE node, int use);
#endif

View File

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

View File

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

View File

@ -370,11 +370,12 @@ struct notation
/*-- mainproc.c --*/
void reset_literals_seen(void);
int proc_packets( void *ctx, iobuf_t a );
int proc_signature_packets( void *ctx, iobuf_t a,
int proc_packets (ctrl_t ctrl, void *ctx, iobuf_t a );
int proc_signature_packets (ctrl_t ctrl, void *ctx, iobuf_t a,
strlist_t signedfiles, const char *sigfile );
int proc_signature_packets_by_fd ( void *anchor, IOBUF a, int signed_data_fd );
int proc_encryption_packets( void *ctx, iobuf_t a );
int proc_signature_packets_by_fd (ctrl_t ctrl,
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 );
/*-- 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);
/*-- 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 );
/*-- 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 --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,

View File

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

View File

@ -29,11 +29,11 @@
#endif
#include "gpg.h"
#include "util.h"
#include "packet.h"
#include "status.h"
#include "exec.h"
#include "keydb.h"
#include "util.h"
#include "i18n.h"
#include "iobuf.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
the key in the updated list as a hidden recipient. */
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 rc;
@ -793,7 +793,7 @@ find_and_check_key (const char *name, unsigned int use,
return gpg_error_from_syserror ();
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)
{
/* Key not found or other error. */
@ -883,7 +883,8 @@ find_and_check_key (const char *name, unsigned int use,
not changed.
*/
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;
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 pass 1for the second last argument and 1 as the last
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;
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);
pk = xmalloc_clear( sizeof *pk );
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)
tty_printf(_("No such user ID.\n"));
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
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)
log_error(_("unknown default recipient \"%s\"\n"), def_rec );
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) )
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);
if (rc)
goto fail;

View File

@ -231,7 +231,7 @@ cmd_recipient (assuan_context_t ctx, char *line)
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);
if (err)
@ -324,7 +324,7 @@ cmd_encrypt (assuan_context_t ctx, char *line)
/* 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,
out_fd);
@ -368,7 +368,7 @@ cmd_decrypt (assuan_context_t ctx, char *line)
return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
glo_ctrl.lasterr = 0;
err = decrypt_message_fd (inp_fd, out_fd);
err = decrypt_message_fd (ctrl, inp_fd, out_fd);
if (!err)
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.
*/
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 )
{
const char *fname;
@ -822,7 +822,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
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;
/* prepare iobufs */

View File

@ -50,7 +50,7 @@
*/
int
verify_signatures( int nfiles, char **files )
verify_signatures (ctrl_t ctrl, int nfiles, char **files )
{
IOBUF fp;
armor_filter_context_t *afx = NULL;
@ -110,7 +110,7 @@ verify_signatures( int nfiles, char **files )
sl = NULL;
for(i=nfiles-1 ; i > 0 ; 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);
iobuf_close(fp);
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
verify_one_file( const char *name )
verify_one_file (ctrl_t ctrl, const char *name )
{
IOBUF fp;
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);
write_status( STATUS_FILE_DONE );
@ -190,7 +190,7 @@ verify_one_file( const char *name )
* Note: This function can not handle detached signatures.
*/
int
verify_files( int nfiles, char **files )
verify_files (ctrl_t ctrl, int nfiles, char **files )
{
int i;
@ -208,13 +208,13 @@ verify_files( int nfiles, char **files )
* also no script languages available. We don't strip any
* spaces, so that we can process nearly all filenames */
line[strlen(line)-1] = 0;
verify_one_file( line );
verify_one_file (ctrl, line );
}
}
else { /* take filenames from the array */
for(i=0; i < nfiles; i++ )
verify_one_file( files[i] );
verify_one_file (ctrl, files[i] );
}
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);
}
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
&& (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]);
if (buf[0] > 54) {
DEBUGOUT (" junk ");
for (i=54; i < buf[0]-54; i++)
DEBUGOUT_CONT_1 (" %02X", buf[i]);
DEBUGOUT_LF ();
}
if (buf[0] > 54)
{
DEBUGOUT (" junk ");
for (i=54; i < buf[0]-54; i++)
DEBUGOUT_CONT_1 (" %02X", buf[i]);
DEBUGOUT_LF ();
}
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>
* 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
on purpose. */
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));
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. */
if (rc != -1 && opt.verbose > 1)
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;
}
@ -1496,7 +1496,7 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
}
else
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;
}
@ -1897,7 +1897,7 @@ gpgsm_basic_cert_check (ctrl_t ctrl, ksba_cert_t cert)
}
else
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;
}

View File

@ -287,7 +287,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oAuditLog, "audit-log",
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 (oBatch, "batch", N_("batch mode: never ask")),
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)
rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL);
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;
@ -253,9 +254,14 @@ check_and_store (ctrl_t ctrl, struct stats_s *stats,
log_error (_("basic certificate checks failed - not imported\n"));
if (stats)
stats->not_imported++;
print_import_problem (ctrl, cert,
gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 :
gpg_err_code (rc) == GPG_ERR_BAD_CERT? 1 : 0);
/* We keep the test for GPG_ERR_MISSING_CERT only in case
GPG_ERR_MISSING_CERT has been used instead of the newer
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);
}
}