mirror of
git://git.gnupg.org/gnupg.git
synced 2025-04-11 22:01:08 +02:00
gpg: Auto-migrate existing secring.gpg.
* g10/migrate.c: New. * g10/import.c (import_old_secring): New. (import_one): Add arg silent. (transfer_secret_keys): Add arg batch. (import_secret_one): Add args batch and for_migration. * g10/gpg.c (main): Call migration function.
This commit is contained in:
parent
09a2d4ec74
commit
4f0625889b
29
README
29
README
@ -85,21 +85,10 @@ MIGRATION FROM 1.4 or 2.0 to 2.1
|
|||||||
The major change in 2.1 is gpg-agent taking care of the OpenPGP secret
|
The major change in 2.1 is gpg-agent taking care of the OpenPGP secret
|
||||||
keys (those managed by GPG). The former file "secring.gpg" will not
|
keys (those managed by GPG). The former file "secring.gpg" will not
|
||||||
be used anymore. Newly generated keys are stored in the agent's key
|
be used anymore. Newly generated keys are stored in the agent's key
|
||||||
store directory "~/.gnupg/private-keys-v1.d/".
|
store directory "~/.gnupg/private-keys-v1.d/". The first time gpg
|
||||||
|
needs a secret key it checks whether a "secring.gpg" exists and
|
||||||
To migrate your existing keys you need to run the command
|
copies them to the new store. The old secring.gpg is kept for use by
|
||||||
|
older versions of gpg.
|
||||||
gpg2 --batch --import ~/.gnupg/secring.gpg
|
|
||||||
|
|
||||||
Secret keys already imported are skipped by this command. It is
|
|
||||||
advisable to keep the secring.gpg for use with older versions of GPG.
|
|
||||||
|
|
||||||
The use of "--batch" with "--import" is highly recommended. If you do
|
|
||||||
not use "--batch" the agent would ask for the passphrase of each key.
|
|
||||||
In this case you may use the Cancel button of the Pinentry to skip
|
|
||||||
importing this key. If you want to stop the enite import process and
|
|
||||||
you use a decent version of Pinentry, you should close the Pinentry
|
|
||||||
window instead of hitting the Cancel button.
|
|
||||||
|
|
||||||
Note that gpg-agent now uses a fixed socket by default. All tools
|
Note that gpg-agent now uses a fixed socket by default. All tools
|
||||||
will start the gpg-agent as needed. In general there is no more need
|
will start the gpg-agent as needed. In general there is no more need
|
||||||
@ -111,11 +100,11 @@ of the card related sub-commands of --edit-key are not yet fully
|
|||||||
supported. However, signing and decryption with a smartcard does
|
supported. However, signing and decryption with a smartcard does
|
||||||
work.
|
work.
|
||||||
|
|
||||||
The Dirmngr is now part of GnuPG proper. Thus there is no more need
|
The Dirmngr is now part of GnuPG proper and also used to access
|
||||||
to install the separate dirmngr package. The directroy layout of
|
OpenPGP keyservers. The directroy layout of Dirmngr changed to make
|
||||||
Dirmngr changed to make use of the GnuPG directories; for example you
|
use of the GnuPG directories. Dirmngr is started by gpg or gpgsm as
|
||||||
use /etc/gnupg/trusted-certs and /var/lib/gnupg/extra-certs. Dirmngr
|
needed needed. There is no more need to install a separate dirmngr
|
||||||
needs to be started as a system daemon.
|
package.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
30
doc/gpg.texi
30
doc/gpg.texi
@ -3042,18 +3042,33 @@ files; They all live in in the current home directory (@pxref{option
|
|||||||
|
|
||||||
|
|
||||||
@table @file
|
@table @file
|
||||||
@item ~/.gnupg/secring.gpg
|
|
||||||
The secret keyring. You should backup this file.
|
|
||||||
|
|
||||||
@item ~/.gnupg/secring.gpg.lock
|
|
||||||
The lock file for the secret keyring.
|
|
||||||
|
|
||||||
@item ~/.gnupg/pubring.gpg
|
@item ~/.gnupg/pubring.gpg
|
||||||
The public keyring. You should backup this file.
|
The public keyring. You should backup this file.
|
||||||
|
|
||||||
@item ~/.gnupg/pubring.gpg.lock
|
@item ~/.gnupg/pubring.gpg.lock
|
||||||
The lock file for the public keyring.
|
The lock file for the public keyring.
|
||||||
|
|
||||||
|
@ifset gpgtwoone
|
||||||
|
@item ~/.gnupg/pubring.kbx
|
||||||
|
The public keyring using a different format. This file is sharred
|
||||||
|
with @command{gpgsm}. You should backup this file.
|
||||||
|
|
||||||
|
@item ~/.gnupg/pubring.kbx.lock
|
||||||
|
The lock file for @file{pubring.kbx}.
|
||||||
|
@end ifset
|
||||||
|
|
||||||
|
@item ~/.gnupg/secring.gpg
|
||||||
|
@ifclear gpgtwoone
|
||||||
|
The secret keyring. You should backup this file.
|
||||||
|
@end ifclear
|
||||||
|
@ifset gpgtwoone
|
||||||
|
A secret keyring as used by GnuPG versions before 2.1. It is not
|
||||||
|
used by GnuPG 2.1 and later.
|
||||||
|
|
||||||
|
@item ~/.gnupg/.gpg-v21-migrated
|
||||||
|
File indicating that a migration to GnuPG 2.1 has taken place.
|
||||||
|
@end ifset
|
||||||
|
|
||||||
@item ~/.gnupg/trustdb.gpg
|
@item ~/.gnupg/trustdb.gpg
|
||||||
The trust database. There is no need to backup this file; it is better
|
The trust database. There is no need to backup this file; it is better
|
||||||
to backup the ownertrust values (@pxref{option --export-ownertrust}).
|
to backup the ownertrust values (@pxref{option --export-ownertrust}).
|
||||||
@ -3064,6 +3079,9 @@ files; They all live in in the current home directory (@pxref{option
|
|||||||
@item ~/.gnupg/random_seed
|
@item ~/.gnupg/random_seed
|
||||||
A file used to preserve the state of the internal random pool.
|
A file used to preserve the state of the internal random pool.
|
||||||
|
|
||||||
|
@item ~/.gnupg/secring.gpg.lock
|
||||||
|
The lock file for the secret keyring.
|
||||||
|
|
||||||
@item /usr[/local]/share/gnupg/options.skel
|
@item /usr[/local]/share/gnupg/options.skel
|
||||||
The skeleton options file.
|
The skeleton options file.
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ gpg2_SOURCES = gpg.c \
|
|||||||
dearmor.c \
|
dearmor.c \
|
||||||
import.c \
|
import.c \
|
||||||
export.c \
|
export.c \
|
||||||
|
migrate.c \
|
||||||
delkey.c \
|
delkey.c \
|
||||||
keygen.c \
|
keygen.c \
|
||||||
helptext.c \
|
helptext.c \
|
||||||
|
37
g10/gpg.c
37
g10/gpg.c
@ -3594,6 +3594,43 @@ main (int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check for certain command whether we need to migrate a
|
||||||
|
secring.gpg to the gpg-agent. */
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case aListSecretKeys:
|
||||||
|
case aSign:
|
||||||
|
case aSignEncr:
|
||||||
|
case aSignEncrSym:
|
||||||
|
case aSignSym:
|
||||||
|
case aClearsign:
|
||||||
|
case aDecrypt:
|
||||||
|
case aSignKey:
|
||||||
|
case aLSignKey:
|
||||||
|
case aEditKey:
|
||||||
|
case aPasswd:
|
||||||
|
case aDeleteSecretKeys:
|
||||||
|
case aDeleteSecretAndPublicKeys:
|
||||||
|
case aKeygen:
|
||||||
|
case aImport:
|
||||||
|
case aExportSecret:
|
||||||
|
case aExportSecretSub:
|
||||||
|
case aGenRevoke:
|
||||||
|
case aDesigRevoke:
|
||||||
|
case aCardEdit:
|
||||||
|
case aChangePIN:
|
||||||
|
migrate_secring (ctrl);
|
||||||
|
break;
|
||||||
|
case aListKeys:
|
||||||
|
if (opt.with_secret)
|
||||||
|
migrate_secring (ctrl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The command dispatcher. */
|
||||||
switch( cmd )
|
switch( cmd )
|
||||||
{
|
{
|
||||||
case aServer:
|
case aServer:
|
||||||
|
140
g10/import.c
140
g10/import.c
@ -1,6 +1,7 @@
|
|||||||
/* import.c - import a key into our key storage.
|
/* import.c - import a key into our key storage.
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||||
* 2007, 2010, 2011 Free Software Foundation, Inc.
|
* 2007, 2010, 2011 Free Software Foundation, Inc.
|
||||||
|
* Copyright (C) 2014 Werner Koch
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -68,9 +69,10 @@ static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
|
|||||||
static int import_one (ctrl_t ctrl,
|
static int import_one (ctrl_t ctrl,
|
||||||
const char *fname, KBNODE keyblock,struct stats_s *stats,
|
const char *fname, KBNODE keyblock,struct stats_s *stats,
|
||||||
unsigned char **fpr,size_t *fpr_len,
|
unsigned char **fpr,size_t *fpr_len,
|
||||||
unsigned int options,int from_sk);
|
unsigned int options,int from_sk, int silent);
|
||||||
static int import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
static int import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
||||||
struct stats_s *stats, unsigned int options);
|
struct stats_s *stats, int batch,
|
||||||
|
unsigned int options, int for_migration);
|
||||||
static int import_revoke_cert( const char *fname, KBNODE node,
|
static int import_revoke_cert( const char *fname, KBNODE node,
|
||||||
struct stats_s *stats);
|
struct stats_s *stats);
|
||||||
static int chk_self_sigs( const char *fname, KBNODE keyblock,
|
static int chk_self_sigs( const char *fname, KBNODE keyblock,
|
||||||
@ -227,6 +229,7 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
||||||
void *stats_handle, unsigned int options )
|
void *stats_handle, unsigned int options )
|
||||||
@ -293,9 +296,10 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
|
|||||||
while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
|
while( !(rc = read_block( inp, &pending_pkt, &keyblock) )) {
|
||||||
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
|
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
|
||||||
rc = import_one (ctrl, fname, keyblock,
|
rc = import_one (ctrl, fname, keyblock,
|
||||||
stats, fpr, fpr_len, options, 0);
|
stats, fpr, fpr_len, options, 0, 0);
|
||||||
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
|
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
|
||||||
rc = import_secret_one (ctrl, fname, keyblock, stats, options);
|
rc = import_secret_one (ctrl, fname, keyblock, stats,
|
||||||
|
opt.batch, options, 0);
|
||||||
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
|
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
|
||||||
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
|
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
|
||||||
rc = import_revoke_cert( fname, keyblock, stats );
|
rc = import_revoke_cert( fname, keyblock, stats );
|
||||||
@ -320,6 +324,57 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper to migrate secring.gpg to GnuPG 2.1. */
|
||||||
|
gpg_error_t
|
||||||
|
import_old_secring (ctrl_t ctrl, const char *fname)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
iobuf_t inp;
|
||||||
|
PACKET *pending_pkt = NULL;
|
||||||
|
kbnode_t keyblock = NULL; /* Need to initialize because gcc can't
|
||||||
|
grasp the return semantics of
|
||||||
|
read_block. */
|
||||||
|
struct stats_s *stats;
|
||||||
|
|
||||||
|
inp = iobuf_open (fname);
|
||||||
|
if (inp && is_secured_file (iobuf_get_fd (inp)))
|
||||||
|
{
|
||||||
|
iobuf_close (inp);
|
||||||
|
inp = NULL;
|
||||||
|
gpg_err_set_errno (EPERM);
|
||||||
|
}
|
||||||
|
if (!inp)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
getkey_disable_caches();
|
||||||
|
stats = import_new_stats_handle ();
|
||||||
|
while (!(err = read_block (inp, &pending_pkt, &keyblock)))
|
||||||
|
{
|
||||||
|
if (keyblock->pkt->pkttype == PKT_SECRET_KEY)
|
||||||
|
err = import_secret_one (ctrl, fname, keyblock, stats, 1, 0, 1);
|
||||||
|
release_kbnode (keyblock);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
import_release_stats_handle (stats);
|
||||||
|
if (err == -1)
|
||||||
|
err = 0;
|
||||||
|
else if (err && gpg_err_code (err) != G10ERR_INV_KEYRING)
|
||||||
|
log_error (_("error reading '%s': %s\n"), fname, gpg_strerror (err));
|
||||||
|
else if (err)
|
||||||
|
log_error ("import from '%s' failed: %s\n", fname, gpg_strerror (err));
|
||||||
|
|
||||||
|
iobuf_close (inp);
|
||||||
|
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
import_print_stats (void *hd)
|
import_print_stats (void *hd)
|
||||||
{
|
{
|
||||||
@ -771,16 +826,17 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Try to import one keyblock. Return an error only in serious cases, but
|
* Try to import one keyblock. Return an error only in serious cases,
|
||||||
* never for an invalid keyblock. It uses log_error to increase the
|
* but never for an invalid keyblock. It uses log_error to increase
|
||||||
* internal errorcount, so that invalid input can be detected by programs
|
* the internal errorcount, so that invalid input can be detected by
|
||||||
* which called gpg.
|
* programs which called gpg. If SILENT is no messages are printed -
|
||||||
|
* even most error messages are suppressed.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
import_one (ctrl_t ctrl,
|
import_one (ctrl_t ctrl,
|
||||||
const char *fname, KBNODE keyblock, struct stats_s *stats,
|
const char *fname, KBNODE keyblock, struct stats_s *stats,
|
||||||
unsigned char **fpr,size_t *fpr_len,unsigned int options,
|
unsigned char **fpr,size_t *fpr_len,unsigned int options,
|
||||||
int from_sk )
|
int from_sk, int silent)
|
||||||
{
|
{
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
PKT_public_key *pk_orig;
|
PKT_public_key *pk_orig;
|
||||||
@ -804,7 +860,7 @@ import_one (ctrl_t ctrl,
|
|||||||
keyid_from_pk( pk, keyid );
|
keyid_from_pk( pk, keyid );
|
||||||
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
|
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
|
||||||
|
|
||||||
if( opt.verbose && !opt.interactive )
|
if (opt.verbose && !opt.interactive && !silent)
|
||||||
{
|
{
|
||||||
log_info( "pub %s/%s %s ",
|
log_info( "pub %s/%s %s ",
|
||||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
||||||
@ -819,11 +875,12 @@ import_one (ctrl_t ctrl,
|
|||||||
|
|
||||||
if( !uidnode )
|
if( !uidnode )
|
||||||
{
|
{
|
||||||
log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
|
if (!silent)
|
||||||
|
log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt.interactive) {
|
if (opt.interactive && !silent) {
|
||||||
if(is_status_enabled())
|
if(is_status_enabled())
|
||||||
print_import_check (pk, uidnode->pkt->pkt.user_id);
|
print_import_check (pk, uidnode->pkt->pkt.user_id);
|
||||||
merge_keys_and_selfsig (keyblock);
|
merge_keys_and_selfsig (keyblock);
|
||||||
@ -856,7 +913,7 @@ import_one (ctrl_t ctrl,
|
|||||||
return rc== -1? 0:rc;
|
return rc== -1? 0:rc;
|
||||||
|
|
||||||
/* If we allow such a thing, mark unsigned uids as valid */
|
/* If we allow such a thing, mark unsigned uids as valid */
|
||||||
if( opt.allow_non_selfsigned_uid )
|
if( opt.allow_non_selfsigned_uid)
|
||||||
for( node=keyblock; node; node = node->next )
|
for( node=keyblock; node; node = node->next )
|
||||||
if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) )
|
if( node->pkt->pkttype == PKT_USER_ID && !(node->flag & 1) )
|
||||||
{
|
{
|
||||||
@ -869,9 +926,11 @@ import_one (ctrl_t ctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( !delete_inv_parts( fname, keyblock, keyid, options ) ) {
|
if( !delete_inv_parts( fname, keyblock, keyid, options ) ) {
|
||||||
log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk));
|
if (!silent) {
|
||||||
if( !opt.quiet )
|
log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk));
|
||||||
log_info(_("this may be caused by a missing self-signature\n"));
|
if( !opt.quiet )
|
||||||
|
log_info(_("this may be caused by a missing self-signature\n"));
|
||||||
|
}
|
||||||
stats->no_user_id++;
|
stats->no_user_id++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -881,12 +940,13 @@ import_one (ctrl_t ctrl,
|
|||||||
rc = get_pubkey_fast ( pk_orig, keyid );
|
rc = get_pubkey_fast ( pk_orig, keyid );
|
||||||
if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY )
|
if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY )
|
||||||
{
|
{
|
||||||
log_error( _("key %s: public key not found: %s\n"),
|
if (!silent)
|
||||||
keystr(keyid), g10_errstr(rc));
|
log_error (_("key %s: public key not found: %s\n"),
|
||||||
|
keystr(keyid), g10_errstr(rc));
|
||||||
}
|
}
|
||||||
else if ( rc && (opt.import_options&IMPORT_MERGE_ONLY) )
|
else if ( rc && (opt.import_options&IMPORT_MERGE_ONLY) )
|
||||||
{
|
{
|
||||||
if( opt.verbose )
|
if( opt.verbose && !silent )
|
||||||
log_info( _("key %s: new key - skipped\n"), keystr(keyid));
|
log_info( _("key %s: new key - skipped\n"), keystr(keyid));
|
||||||
rc = 0;
|
rc = 0;
|
||||||
stats->skipped_new_keys++;
|
stats->skipped_new_keys++;
|
||||||
@ -896,7 +956,7 @@ import_one (ctrl_t ctrl,
|
|||||||
|
|
||||||
rc = keydb_locate_writable (hd, NULL);
|
rc = keydb_locate_writable (hd, NULL);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
log_error (_("no writable keyring found: %s\n"), g10_errstr (rc));
|
log_error (_("no writable keyring found: %s\n"), g10_errstr (rc));
|
||||||
keydb_release (hd);
|
keydb_release (hd);
|
||||||
return G10ERR_GENERAL;
|
return G10ERR_GENERAL;
|
||||||
}
|
}
|
||||||
@ -921,7 +981,7 @@ import_one (ctrl_t ctrl,
|
|||||||
keydb_release (hd);
|
keydb_release (hd);
|
||||||
|
|
||||||
/* we are ready */
|
/* we are ready */
|
||||||
if( !opt.quiet )
|
if( !opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p=get_user_id_native (keyid);
|
char *p=get_user_id_native (keyid);
|
||||||
log_info( _("key %s: public key \"%s\" imported\n"),
|
log_info( _("key %s: public key \"%s\" imported\n"),
|
||||||
@ -948,7 +1008,8 @@ import_one (ctrl_t ctrl,
|
|||||||
* weird is going on */
|
* weird is going on */
|
||||||
if( cmp_public_keys( pk_orig, pk ) )
|
if( cmp_public_keys( pk_orig, pk ) )
|
||||||
{
|
{
|
||||||
log_error( _("key %s: doesn't match our copy\n"),keystr(keyid));
|
if (!silent)
|
||||||
|
log_error( _("key %s: doesn't match our copy\n"),keystr(keyid));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,7 +1072,7 @@ import_one (ctrl_t ctrl,
|
|||||||
revalidation_mark ();
|
revalidation_mark ();
|
||||||
|
|
||||||
/* we are ready */
|
/* we are ready */
|
||||||
if( !opt.quiet )
|
if( !opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p=get_user_id_native(keyid);
|
char *p=get_user_id_native(keyid);
|
||||||
if( n_uids == 1 )
|
if( n_uids == 1 )
|
||||||
@ -1053,7 +1114,7 @@ import_one (ctrl_t ctrl,
|
|||||||
stats->n_sigs_cleaned +=n_sigs_cleaned;
|
stats->n_sigs_cleaned +=n_sigs_cleaned;
|
||||||
stats->n_uids_cleaned +=n_uids_cleaned;
|
stats->n_uids_cleaned +=n_uids_cleaned;
|
||||||
|
|
||||||
if (is_status_enabled ())
|
if (is_status_enabled () && !silent)
|
||||||
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1062,7 +1123,7 @@ import_one (ctrl_t ctrl,
|
|||||||
if (is_status_enabled ())
|
if (is_status_enabled ())
|
||||||
print_import_ok (pk, 0);
|
print_import_ok (pk, 0);
|
||||||
|
|
||||||
if( !opt.quiet )
|
if( !opt.quiet && !silent)
|
||||||
{
|
{
|
||||||
char *p=get_user_id_native(keyid);
|
char *p=get_user_id_native(keyid);
|
||||||
log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p);
|
log_info( _("key %s: \"%s\" not changed\n"),keystr(keyid),p);
|
||||||
@ -1129,9 +1190,12 @@ import_one (ctrl_t ctrl,
|
|||||||
|
|
||||||
|
|
||||||
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
|
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
|
||||||
function prints diagnostics and returns an error code. */
|
function prints diagnostics and returns an error code. If BATCH is
|
||||||
|
true the secret keys are stored by gpg-agent in the transfer format
|
||||||
|
(i.e. no re-protection and aksing for passphrases). */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
|
||||||
|
int batch)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
void *kek = NULL;
|
void *kek = NULL;
|
||||||
@ -1358,7 +1422,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
|||||||
{
|
{
|
||||||
char *desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_IMPORT, 1);
|
char *desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_IMPORT, 1);
|
||||||
err = agent_import_key (ctrl, desc, &cache_nonce,
|
err = agent_import_key (ctrl, desc, &cache_nonce,
|
||||||
wrappedkey, wrappedkeylen, opt.batch);
|
wrappedkey, wrappedkeylen, batch);
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
}
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -1454,7 +1518,8 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
||||||
struct stats_s *stats, unsigned int options)
|
struct stats_s *stats, int batch, unsigned int options,
|
||||||
|
int for_migration)
|
||||||
{
|
{
|
||||||
PKT_public_key *pk;
|
PKT_public_key *pk;
|
||||||
struct seckey_info *ski;
|
struct seckey_info *ski;
|
||||||
@ -1475,7 +1540,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
|||||||
keyid_from_pk (pk, keyid);
|
keyid_from_pk (pk, keyid);
|
||||||
uidnode = find_next_kbnode (keyblock, PKT_USER_ID);
|
uidnode = find_next_kbnode (keyblock, PKT_USER_ID);
|
||||||
|
|
||||||
if (opt.verbose)
|
if (opt.verbose && !for_migration)
|
||||||
{
|
{
|
||||||
log_info ("sec %s/%s %s ",
|
log_info ("sec %s/%s %s ",
|
||||||
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
|
||||||
@ -1489,13 +1554,15 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
|||||||
|
|
||||||
if ((options & IMPORT_NO_SECKEY))
|
if ((options & IMPORT_NO_SECKEY))
|
||||||
{
|
{
|
||||||
log_error (_("importing secret keys not allowed\n"));
|
if (!for_migration)
|
||||||
|
log_error (_("importing secret keys not allowed\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uidnode)
|
if (!uidnode)
|
||||||
{
|
{
|
||||||
log_error( _("key %s: no user ID\n"), keystr_from_pk (pk));
|
if (!for_migration)
|
||||||
|
log_error( _("key %s: no user ID\n"), keystr_from_pk (pk));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1511,8 +1578,9 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
|||||||
cipher algorithm (only checks the primary key, though). */
|
cipher algorithm (only checks the primary key, though). */
|
||||||
if (ski->algo > 110)
|
if (ski->algo > 110)
|
||||||
{
|
{
|
||||||
log_error (_("key %s: secret key with invalid cipher %d"
|
if (!for_migration)
|
||||||
" - skipped\n"), keystr_from_pk (pk), ski->algo);
|
log_error (_("key %s: secret key with invalid cipher %d"
|
||||||
|
" - skipped\n"), keystr_from_pk (pk), ski->algo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1542,7 +1610,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
|||||||
public key block, and below we will output another one for
|
public key block, and below we will output another one for
|
||||||
the secret keys. FIXME? */
|
the secret keys. FIXME? */
|
||||||
import_one (ctrl, fname, pub_keyblock, stats,
|
import_one (ctrl, fname, pub_keyblock, stats,
|
||||||
NULL, NULL, options, 1);
|
NULL, NULL, options, 1, for_migration);
|
||||||
|
|
||||||
/* Fixme: We should check for an invalid keyblock and
|
/* Fixme: We should check for an invalid keyblock and
|
||||||
cancel the secret key import in this case. */
|
cancel the secret key import in this case. */
|
||||||
@ -1564,7 +1632,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
nr_prev = stats->secret_imported;
|
nr_prev = stats->secret_imported;
|
||||||
if (!transfer_secret_keys (ctrl, stats, keyblock))
|
if (!transfer_secret_keys (ctrl, stats, keyblock, batch))
|
||||||
{
|
{
|
||||||
int status = 16;
|
int status = 16;
|
||||||
if (!opt.quiet)
|
if (!opt.quiet)
|
||||||
|
@ -290,6 +290,7 @@ int import_keys_stream (ctrl_t ctrl, iobuf_t inp, void *stats_hd,
|
|||||||
int import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle,
|
int import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle,
|
||||||
unsigned char **fpr, size_t *fpr_len,
|
unsigned char **fpr, size_t *fpr_len,
|
||||||
unsigned int options);
|
unsigned int options);
|
||||||
|
gpg_error_t import_old_secring (ctrl_t ctrl, const char *fname);
|
||||||
void *import_new_stats_handle (void);
|
void *import_new_stats_handle (void);
|
||||||
void import_release_stats_handle (void *p);
|
void import_release_stats_handle (void *p);
|
||||||
void import_print_stats (void *hd);
|
void import_print_stats (void *hd);
|
||||||
@ -379,4 +380,8 @@ int card_store_subkey (KBNODE node, int use);
|
|||||||
|
|
||||||
#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
|
#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
|
||||||
|
|
||||||
|
/*-- migrate.c --*/
|
||||||
|
void migrate_secring (ctrl_t ctrl);
|
||||||
|
|
||||||
|
|
||||||
#endif /*G10_MAIN_H*/
|
#endif /*G10_MAIN_H*/
|
||||||
|
94
g10/migrate.c
Normal file
94
g10/migrate.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* migrate.c - Migrate from earlier GnupG versions.
|
||||||
|
* Copyright (C) 2014 Werner Koch
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "gpg.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "keydb.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_DOSISH_SYSTEM
|
||||||
|
# define V21_MIGRATION_FNAME "gpg-v21-migrated"
|
||||||
|
#else
|
||||||
|
# define V21_MIGRATION_FNAME ".gpg-v21-migrated"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether a default secring.gpg from GnuPG < 2.1 exists and
|
||||||
|
import it if not yet done. */
|
||||||
|
void
|
||||||
|
migrate_secring (ctrl_t ctrl)
|
||||||
|
{
|
||||||
|
dotlock_t lockhd = NULL;
|
||||||
|
char *secring = NULL;
|
||||||
|
char *flagfile = NULL;
|
||||||
|
|
||||||
|
secring = make_filename (opt.homedir, "secring" EXTSEP_S "gpg", NULL);
|
||||||
|
if (access (secring, F_OK))
|
||||||
|
goto leave; /* Does not exist or is not readable. */
|
||||||
|
flagfile = make_filename (opt.homedir, V21_MIGRATION_FNAME, NULL);
|
||||||
|
if (!access (flagfile, F_OK))
|
||||||
|
goto leave; /* Does exist - fine. */
|
||||||
|
|
||||||
|
log_info ("starting migration from earlier GnuPG versions\n");
|
||||||
|
|
||||||
|
lockhd = dotlock_create (flagfile, 0);
|
||||||
|
if (!lockhd)
|
||||||
|
{
|
||||||
|
log_error ("can't allocate lock for '%s': %s\n",
|
||||||
|
flagfile, gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (dotlock_take (lockhd, -1))
|
||||||
|
{
|
||||||
|
log_error ("can't lock '%s': %s\n",
|
||||||
|
flagfile, gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
dotlock_destroy (lockhd);
|
||||||
|
lockhd = NULL;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info ("porting secret keys from '%s' to gpg-agent\n", secring);
|
||||||
|
if (!import_old_secring (ctrl, secring))
|
||||||
|
{
|
||||||
|
FILE *fp = fopen (flagfile, "w");
|
||||||
|
if (!fp || fclose (fp))
|
||||||
|
log_error ("error creating flag file '%s': %s\n",
|
||||||
|
flagfile, gpg_strerror (gpg_error_from_syserror ()));
|
||||||
|
else
|
||||||
|
log_info ("migration succeeded\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
if (lockhd)
|
||||||
|
{
|
||||||
|
dotlock_release (lockhd);
|
||||||
|
dotlock_destroy (lockhd);
|
||||||
|
}
|
||||||
|
xfree (flagfile);
|
||||||
|
xfree (secring);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user