[git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-438-g9c9e26d

by Werner Koch cvs at cvs.gnupg.org
Thu Jun 5 12:08:05 CEST 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  9c9e26d41e7d65711da8dbf1afa452254749621c (commit)
       via  4f0625889b768eabdec52696bf15059a9e8d9c02 (commit)
      from  09a2d4ec74d352dcb4f006aab60b07bc4f5f1a37 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9c9e26d41e7d65711da8dbf1afa452254749621c
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jun 5 12:03:27 2014 +0200

    gpg: Require confirmation for --gen-key with experimental curves.
    
    * g10/keygen.c (ask_curve): Add arg both.  Require confirmation for
    Curve25519.

diff --git a/g10/keygen.c b/g10/keygen.c
index 5c898cc..af54c3f 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -2088,9 +2088,9 @@ ask_keysize (int algo, unsigned int primary_keysize)
 
 /* Ask for the curve.  ALGO is the selected algorithm which this
    function may adjust.  Returns a malloced string with the name of
-   the curve.  */
+   the curve.  BOTH tells that gpg creates a primary and subkey. */
 static char *
-ask_curve (int *algo)
+ask_curve (int *algo, int both)
 {
   struct {
     const char *name;
@@ -2119,6 +2119,7 @@ ask_curve (int *algo)
 
   tty_printf (_("Please select which elliptic curve you want:\n"));
 
+ again:
   keyparms = NULL;
   for (idx=0; idx < DIM(curves); idx++)
     {
@@ -2140,6 +2141,19 @@ ask_curve (int *algo)
         continue;
       if (!gcry_pk_get_curve (keyparms, 0, NULL))
         continue;
+      if (both && curves[idx].fix_curve)
+        {
+          /* Both Curve 25519 keys are to be created.  Check that
+             Libgcrypt also supports the real Curve25519.  */
+          gcry_sexp_release (keyparms);
+          rc = gcry_sexp_build (&keyparms, NULL,
+                                "(public-key(ecc(curve %s)))",
+                                 curves[idx].name);
+          if (rc)
+            continue;
+          if (!gcry_pk_get_curve (keyparms, 0, NULL))
+            continue;
+        }
 
       curves[idx].available = 1;
       tty_printf ("   (%d) %s\n", idx + 1,
@@ -2178,10 +2192,16 @@ ask_curve (int *algo)
       else
         {
           if (curves[idx].fix_curve)
-            log_info ("WARNING: Curve25519 is an experimental algorithm and"
-                      " not yet specified by OpenPGP.  The current"
-                      " implementation may change with the next GnuPG release"
-                      " and thus rendering the key unusable!\n");
+            {
+              log_info ("WARNING: Curve25519 is an experimental algorithm"
+                        " and not yet standardized.\n");
+              log_info ("         The key format will eventually change"
+                        " and render this key unusable!\n\n");
+
+              if (!cpr_get_answer_is_yes("experimental_curve.override",
+                                         "Use this curve anyway? (y/N) ")  )
+                goto again;
+            }
 
           /* If the user selected a signing algorithm and Curve25519
              we need to update the algo and and the curve name.  */
@@ -3485,7 +3505,7 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo);
+              curve = ask_curve (&algo, both);
               r = xmalloc_clear( sizeof *r + 20 );
               r->key = pKEYTYPE;
               sprintf( r->u.value, "%d", algo);
@@ -3551,12 +3571,12 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno,
       else /* Create only a single key.  */
         {
           /* For ECC we need to ask for the curve before storing the
-             algo becuase ask_curve may change the algo.  */
+             algo because ask_curve may change the algo.  */
           if (algo == PUBKEY_ALGO_ECDSA
               || algo == PUBKEY_ALGO_EDDSA
               || algo == PUBKEY_ALGO_ECDH)
             {
-              curve = ask_curve (&algo);
+              curve = ask_curve (&algo, 0);
               nbits = 0;
               r = xmalloc_clear (sizeof *r + strlen (curve));
               r->key = pKEYCURVE;
@@ -4086,7 +4106,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock)
   else if (algo == PUBKEY_ALGO_ECDSA
            || algo == PUBKEY_ALGO_EDDSA
            || algo == PUBKEY_ALGO_ECDH)
-    curve = ask_curve (&algo);
+    curve = ask_curve (&algo, 0);
   else
     nbits = ask_keysize (algo, 0);
 

commit 4f0625889b768eabdec52696bf15059a9e8d9c02
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Jun 5 11:19:59 2014 +0200

    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.

diff --git a/README b/README
index c64a14e..fd20d40 100644
--- a/README
+++ b/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
 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
-store directory "~/.gnupg/private-keys-v1.d/".
-
-To migrate your existing keys you need to run the command
-
-  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.
+store directory "~/.gnupg/private-keys-v1.d/".  The first time gpg
+needs a secret key it checks whether a "secring.gpg" exists and
+copies them to the new store.  The old secring.gpg is kept for use by
+older versions of gpg.
 
 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
@@ -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
 work.
 
-The Dirmngr is now part of GnuPG proper.  Thus there is no more need
-to install the separate dirmngr package.  The directroy layout of
-Dirmngr changed to make use of the GnuPG directories; for example you
-use /etc/gnupg/trusted-certs and /var/lib/gnupg/extra-certs.  Dirmngr
-needs to be started as a system daemon.
+The Dirmngr is now part of GnuPG proper and also used to access
+OpenPGP keyservers.  The directroy layout of Dirmngr changed to make
+use of the GnuPG directories.  Dirmngr is started by gpg or gpgsm as
+needed needed. There is no more need to install a separate dirmngr
+package.
 
 
 
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 71a3107..c8fae3a 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -3042,18 +3042,33 @@ files; They all live in in the current home directory (@pxref{option
 
 
 @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
   The public keyring.  You should backup this file.
 
   @item ~/.gnupg/pubring.gpg.lock
   The lock file for the public keyring.
 
+ at 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}.
+ at end ifset
+
+  @item ~/.gnupg/secring.gpg
+ at ifclear gpgtwoone
+  The secret keyring.  You should backup this file.
+ at end ifclear
+ at 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.
+ at end ifset
+
   @item ~/.gnupg/trustdb.gpg
   The trust database.  There is no need to backup this file; it is better
   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
   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
   The skeleton options file.
 
diff --git a/g10/Makefile.am b/g10/Makefile.am
index ba68648..0ae4ef7 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -110,6 +110,7 @@ gpg2_SOURCES  = gpg.c		\
 	      dearmor.c 	\
 	      import.c		\
 	      export.c		\
+	      migrate.c         \
 	      delkey.c		\
 	      keygen.c          \
 	      helptext.c        \
diff --git a/g10/gpg.c b/g10/gpg.c
index bd4ca40..47cc851 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -3594,6 +3594,43 @@ main (int argc, char **argv)
         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 )
       {
       case aServer:
diff --git a/g10/import.c b/g10/import.c
index 2b219a2..774a727 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1,6 +1,7 @@
 /* import.c - import a key into our key storage.
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  *               2007, 2010, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2014  Werner Koch
  *
  * 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,
                        const char *fname, KBNODE keyblock,struct stats_s *stats,
                        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,
-                              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,
                                struct stats_s *stats);
 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;
 }
 
+
 void
 import_keys (ctrl_t ctrl, char **fnames, int nnames,
 	     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) )) {
 	if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
           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 )
-          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
 		 && keyblock->pkt->pkt.signature->sig_class == 0x20 )
 	    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
 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
- * never for an invalid keyblock.  It uses log_error to increase the
- * internal errorcount, so that invalid input can be detected by programs
- * which called gpg.
+ * Try to import one keyblock. Return an error only in serious cases,
+ * but never for an invalid keyblock.  It uses log_error to increase
+ * the internal errorcount, so that invalid input can be detected by
+ * programs which called gpg.  If SILENT is no messages are printed -
+ * even most error messages are suppressed.
  */
 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 )
+	    int from_sk, int silent)
 {
     PKT_public_key *pk;
     PKT_public_key *pk_orig;
@@ -804,7 +860,7 @@ import_one (ctrl_t ctrl,
     keyid_from_pk( pk, keyid );
     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  ",
 		  pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
@@ -819,11 +875,12 @@ import_one (ctrl_t ctrl,
 
     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;
       }
 
-    if (opt.interactive) {
+    if (opt.interactive && !silent) {
         if(is_status_enabled())
 	  print_import_check (pk, uidnode->pkt->pkt.user_id);
 	merge_keys_and_selfsig (keyblock);
@@ -856,7 +913,7 @@ import_one (ctrl_t ctrl,
 	return rc== -1? 0:rc;
 
     /* 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 )
 	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 ) ) {
-        log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk));
-	if( !opt.quiet )
-	  log_info(_("this may be caused by a missing self-signature\n"));
+        if (!silent) {
+           log_error( _("key %s: no valid user IDs\n"), keystr_from_pk(pk));
+           if( !opt.quiet )
+	      log_info(_("this may be caused by a missing self-signature\n"));
+        }
 	stats->no_user_id++;
 	return 0;
     }
@@ -881,12 +940,13 @@ import_one (ctrl_t ctrl,
     rc = get_pubkey_fast ( pk_orig, keyid );
     if( rc && rc != G10ERR_NO_PUBKEY && rc != G10ERR_UNU_PUBKEY )
       {
-	log_error( _("key %s: public key not found: %s\n"),
-		   keystr(keyid), g10_errstr(rc));
+        if (!silent)
+          log_error (_("key %s: public key not found: %s\n"),
+                     keystr(keyid), g10_errstr(rc));
       }
     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));
 	rc = 0;
 	stats->skipped_new_keys++;
@@ -896,7 +956,7 @@ import_one (ctrl_t ctrl,
 
         rc = keydb_locate_writable (hd, NULL);
 	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);
 	    return G10ERR_GENERAL;
 	}
@@ -921,7 +981,7 @@ import_one (ctrl_t ctrl,
         keydb_release (hd);
 
 	/* we are ready */
-	if( !opt.quiet )
+	if( !opt.quiet && !silent)
 	  {
 	    char *p=get_user_id_native (keyid);
 	    log_info( _("key %s: public key \"%s\" imported\n"),
@@ -948,7 +1008,8 @@ import_one (ctrl_t ctrl,
 	 * weird is going on */
 	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;
 	  }
 
@@ -1011,7 +1072,7 @@ import_one (ctrl_t ctrl,
 	      revalidation_mark ();
 
 	    /* we are ready */
-	    if( !opt.quiet )
+	    if( !opt.quiet && !silent)
 	      {
 	        char *p=get_user_id_native(keyid);
 		if( n_uids == 1 )
@@ -1053,7 +1114,7 @@ import_one (ctrl_t ctrl,
 	    stats->n_sigs_cleaned +=n_sigs_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)));
 	}
 	else
@@ -1062,7 +1123,7 @@ import_one (ctrl_t ctrl,
             if (is_status_enabled ())
 	      print_import_ok (pk, 0);
 
-	    if( !opt.quiet )
+	    if( !opt.quiet && !silent)
 	      {
 		char *p=get_user_id_native(keyid);
 		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
-   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
-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;
   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);
         err = agent_import_key (ctrl, desc, &cache_nonce,
-                                wrappedkey, wrappedkeylen, opt.batch);
+                                wrappedkey, wrappedkeylen, batch);
         xfree (desc);
       }
       if (!err)
@@ -1454,7 +1518,8 @@ sec_to_pub_keyblock (kbnode_t sec_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)
 {
   PKT_public_key *pk;
   struct seckey_info *ski;
@@ -1475,7 +1540,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
   keyid_from_pk (pk, keyid);
   uidnode = find_next_kbnode (keyblock, PKT_USER_ID);
 
-  if (opt.verbose)
+  if (opt.verbose && !for_migration)
     {
       log_info ("sec  %s/%s %s   ",
                 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))
     {
-      log_error (_("importing secret keys not allowed\n"));
+      if (!for_migration)
+        log_error (_("importing secret keys not allowed\n"));
       return 0;
     }
 
   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;
     }
 
@@ -1511,8 +1578,9 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
      cipher algorithm (only checks the primary key, though).  */
   if (ski->algo > 110)
     {
-      log_error (_("key %s: secret key with invalid cipher %d"
-                   " - skipped\n"), keystr_from_pk (pk), ski->algo);
+      if (!for_migration)
+        log_error (_("key %s: secret key with invalid cipher %d"
+                     " - skipped\n"), keystr_from_pk (pk), ski->algo);
       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
 	 the secret keys.  FIXME?  */
       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
 	 cancel the secret key import in this case.  */
@@ -1564,7 +1632,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
           else
             {
 	      nr_prev = stats->secret_imported;
-              if (!transfer_secret_keys (ctrl, stats, keyblock))
+              if (!transfer_secret_keys (ctrl, stats, keyblock, batch))
                 {
 		  int status = 16;
                   if (!opt.quiet)
diff --git a/g10/main.h b/g10/main.h
index 2802cb5..97c6612 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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,
                            unsigned char **fpr, size_t *fpr_len,
                            unsigned int options);
+gpg_error_t import_old_secring (ctrl_t ctrl, const char *fname);
 void *import_new_stats_handle (void);
 void import_release_stats_handle (void *p);
 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))
 
+/*-- migrate.c --*/
+void migrate_secring (ctrl_t ctrl);
+
+
 #endif /*G10_MAIN_H*/
diff --git a/g10/migrate.c b/g10/migrate.c
new file mode 100644
index 0000000..9a21cfe
--- /dev/null
+++ b/g10/migrate.c
@@ -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);
+}

-----------------------------------------------------------------------

Summary of changes:
 README          |   29 ++++--------
 doc/gpg.texi    |   30 +++++++++---
 g10/Makefile.am |    1 +
 g10/gpg.c       |   37 +++++++++++++++
 g10/import.c    |  140 +++++++++++++++++++++++++++++++++++++++++--------------
 g10/keygen.c    |   40 ++++++++++++----
 g10/main.h      |    5 ++
 g10/migrate.c   |   94 +++++++++++++++++++++++++++++++++++++
 8 files changed, 304 insertions(+), 72 deletions(-)
 create mode 100644 g10/migrate.c


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list