Imported Upstream version 2.1.12
[platform/upstream/gpg2.git] / g10 / import.c
index 048b136..6707797 100644 (file)
@@ -23,7 +23,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 
 #include "gpg.h"
 #include "options.h"
@@ -40,7 +39,7 @@
 #include "call-agent.h"
 #include "../common/membuf.h"
 
-struct stats_s
+struct import_stats_s
 {
   ulong count;
   ulong no_user_id;
@@ -62,23 +61,24 @@ struct stats_s
 
 
 static int import (ctrl_t ctrl,
-                   IOBUF inp, const char* fname, struct stats_s *stats,
+                   IOBUF inp, const char* fname, struct import_stats_s *stats,
                   unsigned char **fpr, size_t *fpr_len, unsigned int options,
                   import_screener_t screener, void *screener_arg);
 static int read_block (IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root,
                        int *r_v3keys);
 static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
 static int import_one (ctrl_t ctrl,
-                       const char *fname, kbnode_t keyblock,struct stats_s *stats,
+                       const char *fname, kbnode_t keyblock,
+                       struct import_stats_s *stats,
                        unsigned char **fpr, size_t *fpr_len,
                        unsigned int options, int from_sk, int silent,
                        import_screener_t screener, void *screener_arg);
 static int import_secret_one (ctrl_t ctrl, const char *fname, kbnode_t keyblock,
-                              struct stats_s *stats, int batch,
+                              struct import_stats_s *stats, int batch,
                               unsigned int options, int for_migration,
                               import_screener_t screener, void *screener_arg);
 static int import_revoke_cert( const char *fname, kbnode_t node,
-                               struct stats_s *stats);
+                               struct import_stats_s *stats);
 static int chk_self_sigs (const char *fname, kbnode_t keyblock,
                          PKT_public_key *pk, u32 *keyid, int *non_self );
 static int delete_inv_parts (const char *fname, kbnode_t keyblock,
@@ -137,15 +137,15 @@ parse_import_options(char *str,unsigned int *options,int noisy)
 }
 
 
-void *
+import_stats_t
 import_new_stats_handle (void)
 {
-  return xmalloc_clear ( sizeof (struct stats_s) );
+  return xmalloc_clear ( sizeof (struct import_stats_s) );
 }
 
 
 void
-import_release_stats_handle (void *p)
+import_release_stats_handle (import_stats_t p)
 {
   xfree (p);
 }
@@ -183,13 +183,14 @@ import_release_stats_handle (void *p)
  */
 static int
 import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
-                     void *stats_handle, unsigned char **fpr, size_t *fpr_len,
+                     import_stats_t stats_handle,
+                      unsigned char **fpr, size_t *fpr_len,
                      unsigned int options,
                       import_screener_t screener, void *screener_arg)
 {
   int i;
   int rc = 0;
-  struct stats_s *stats = stats_handle;
+  struct import_stats_s *stats = stats_handle;
 
   if (!stats)
     stats = import_new_stats_handle ();
@@ -256,14 +257,14 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
 
 void
 import_keys (ctrl_t ctrl, char **fnames, int nnames,
-            void *stats_handle, unsigned int options )
+            import_stats_t stats_handle, unsigned int options )
 {
   import_keys_internal (ctrl, NULL, fnames, nnames, stats_handle,
                         NULL, NULL, options, NULL, NULL);
 }
 
 int
-import_keys_stream (ctrl_t ctrl, IOBUF inp, void *stats_handle,
+import_keys_stream (ctrl_t ctrl, IOBUF inp, import_stats_t stats_handle,
                    unsigned char **fpr, size_t *fpr_len, unsigned int options)
 {
   return import_keys_internal (ctrl, inp, NULL, 0, stats_handle,
@@ -273,7 +274,8 @@ import_keys_stream (ctrl_t ctrl, IOBUF inp, void *stats_handle,
 
 /* Variant of import_keys_stream reading from an estream_t.  */
 int
-import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle,
+import_keys_es_stream (ctrl_t ctrl, estream_t fp,
+                       import_stats_t stats_handle,
                        unsigned char **fpr, size_t *fpr_len,
                        unsigned int options,
                        import_screener_t screener, void *screener_arg)
@@ -299,7 +301,7 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp, void *stats_handle,
 
 
 static int
-import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
+import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
        unsigned char **fpr,size_t *fpr_len, unsigned int options,
        import_screener_t screener, void *screener_arg)
 {
@@ -350,7 +352,6 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
             && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
         {
           stats->not_imported++;
-          rc = 0;
         }
       else if (rc)
         break;
@@ -378,7 +379,7 @@ import_old_secring (ctrl_t ctrl, const char *fname)
   kbnode_t keyblock = NULL;  /* Need to initialize because gcc can't
                                 grasp the return semantics of
                                 read_block. */
-  struct stats_s *stats;
+  struct import_stats_s *stats;
   int v3keys;
 
   inp = iobuf_open (fname);
@@ -422,10 +423,8 @@ import_old_secring (ctrl_t ctrl, const char *fname)
 
 
 void
-import_print_stats (void *hd)
+import_print_stats (import_stats_t stats)
 {
-  struct stats_s *stats = hd;
-
   if (!opt.quiet)
     {
       log_info(_("Total number processed: %lu\n"),
@@ -798,7 +797,6 @@ print_import_check (PKT_public_key * pk, PKT_user_id * id)
   for (i = 0; i < n; i++, pos += 2)
     sprintf (buf+pos, "%02X", fpr[i]);
   strcat (buf, " ");
-  pos += 1;
   strcat (buf, id->name);
   write_status_text (STATUS_IMPORT_CHECK, buf);
   xfree (buf);
@@ -932,7 +930,7 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
  */
 static int
 import_one (ctrl_t ctrl,
-            const char *fname, kbnode_t keyblock, struct stats_s *stats,
+            const char *fname, kbnode_t keyblock, struct import_stats_s *stats,
            unsigned char **fpr, size_t *fpr_len, unsigned int options,
            int from_sk, int silent,
             import_screener_t screener, void *screener_arg)
@@ -1071,7 +1069,11 @@ import_one (ctrl_t ctrl,
     }
   else if (rc )  /* Insert this key. */
     {
-      KEYDB_HANDLE hd = keydb_new ();
+      KEYDB_HANDLE hd;
+
+      hd = keydb_new ();
+      if (!hd)
+        return gpg_error_from_syserror ();
 
       rc = keydb_locate_writable (hd);
       if (rc)
@@ -1136,6 +1138,11 @@ import_one (ctrl_t ctrl,
       /* Now read the original keyblock again so that we can use
          that handle for updating the keyblock.  */
       hd = keydb_new ();
+      if (!hd)
+        {
+          rc = gpg_error_from_syserror ();
+          goto leave;
+        }
       keydb_disable_caching (hd);
       rc = keydb_search_fpr (hd, fpr2);
       if (rc )
@@ -1271,7 +1278,7 @@ import_one (ctrl_t ctrl,
         {
           xfree (*fpr);
           /* Note that we need to compare against 0 here because
-             COUNT gets only incremented after returning form this
+             COUNT gets only incremented after returning from this
              function.  */
           if (!stats->count)
             *fpr = fingerprint_from_pk (pk, NULL, fpr_len);
@@ -1308,9 +1315,9 @@ import_one (ctrl_t ctrl,
    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,
-                      int batch)
+gpg_error_t
+transfer_secret_keys (ctrl_t ctrl, struct import_stats_s *stats,
+                      kbnode_t sec_keyblock, int batch, int force)
 {
   gpg_error_t err = 0;
   void *kek = NULL;
@@ -1331,6 +1338,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
   unsigned char *wrappedkey = NULL;
   size_t wrappedkeylen;
   char *cache_nonce = NULL;
+  int stub_key_skipped = 0;
 
   /* Get the current KEK.  */
   err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@@ -1378,8 +1386,11 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
       if (!ski)
         BUG ();
 
-      stats->count++;
-      stats->secret_read++;
+      if (stats)
+        {
+          stats->count++;
+          stats->secret_read++;
+        }
 
       /* We ignore stub keys.  The way we handle them in other parts
          of the code is by asking the agent whether any secret key is
@@ -1391,7 +1402,10 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
          has been inserted and a stub key is in turn generated by the
          agent.  */
       if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002)
-        continue;
+        {
+          stub_key_skipped = 1;
+          continue;
+        }
 
       /* Convert our internal secret key object into an S-expression.  */
       nskey = pubkey_get_nskey (pk->pubkey_algo);
@@ -1539,7 +1553,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, batch);
+                                wrappedkey, wrappedkeylen, batch, force);
         xfree (desc);
       }
       if (!err)
@@ -1547,7 +1561,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
           if (opt.verbose)
             log_info (_("key %s: secret key imported\n"),
                       keystr_from_pk_with_sub (main_pk, pk));
-          stats->secret_imported++;
+          if (stats)
+            stats->secret_imported++;
         }
       else if ( gpg_err_code (err) == GPG_ERR_EEXIST )
         {
@@ -1555,7 +1570,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
             log_info (_("key %s: secret key already exists\n"),
                       keystr_from_pk_with_sub (main_pk, pk));
           err = 0;
-          stats->secret_dups++;
+          if (stats)
+            stats->secret_dups++;
         }
       else
         {
@@ -1568,6 +1584,10 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock,
         }
     }
 
+  if (!err && stub_key_skipped)
+    /* We need to notify user how to migrate stub keys.  */
+    err = gpg_error (GPG_ERR_NOT_PROCESSED);
+
  leave:
   gcry_sexp_release (curve);
   xfree (cache_nonce);
@@ -1630,12 +1650,12 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
 /****************
  * Ditto for secret keys.  Handling is simpler than for public keys.
  * We allow secret key importing only when allow is true, this is so
- * that a secret key can not be imported accidently and thereby tampering
+ * that a secret key can not be imported accidentally and thereby tampering
  * with the trust calculation.
  */
 static int
 import_secret_one (ctrl_t ctrl, const char *fname, kbnode_t keyblock,
-                   struct stats_s *stats, int batch, unsigned int options,
+                   struct import_stats_s *stats, int batch, unsigned int options,
                    int for_migration,
                    import_screener_t screener, void *screener_arg)
 {
@@ -1757,8 +1777,27 @@ import_secret_one (ctrl_t ctrl, const char *fname, kbnode_t keyblock,
                        keystr_from_pk (pk));
           else
             {
+              gpg_error_t err;
+
              nr_prev = stats->secret_imported;
-              if (!transfer_secret_keys (ctrl, stats, keyblock, batch))
+              err = transfer_secret_keys (ctrl, stats, keyblock, batch, 0);
+              if (gpg_err_code (err) == GPG_ERR_NOT_PROCESSED)
+                {
+                  /* TRANSLATORS: For smartcard, each private key on
+                     host has a reference (stub) to a smartcard and
+                     actual private key data is stored on the card.  A
+                     single smartcard can have up to three private key
+                     data.  Importing private key stub is always
+                     skipped in 2.1, and it returns
+                     GPG_ERR_NOT_PROCESSED.  Instead, user should be
+                     suggested to run 'gpg --card-status', then,
+                     references to a card will be automatically
+                     created again.  */
+                  log_info (_("To migrate '%s', with each smartcard, "
+                              "run: %s\n"), "secring.gpg", "gpg --card-status");
+                  err = 0;
+                }
+              if (!err)
                 {
                  int status = 16;
                   if (!opt.quiet)
@@ -1783,7 +1822,8 @@ import_secret_one (ctrl_t ctrl, const char *fname, kbnode_t keyblock,
  * Import a revocation certificate; this is a single signature packet.
  */
 static int
-import_revoke_cert( const char *fname, kbnode_t node, struct stats_s *stats )
+import_revoke_cert (const char *fname, kbnode_t node,
+                    struct import_stats_s *stats)
 {
   PKT_public_key *pk = NULL;
   kbnode_t onode;
@@ -1794,9 +1834,9 @@ import_revoke_cert( const char *fname, kbnode_t node, struct stats_s *stats )
 
   (void)fname;
 
-  assert( !node->next );
-  assert( node->pkt->pkttype == PKT_SIGNATURE );
-  assert( node->pkt->pkt.signature->sig_class == 0x20 );
+  log_assert (!node->next );
+  log_assert (node->pkt->pkttype == PKT_SIGNATURE );
+  log_assert (node->pkt->pkt.signature->sig_class == 0x20 );
 
   keyid[0] = node->pkt->pkt.signature->keyid[0];
   keyid[1] = node->pkt->pkt.signature->keyid[1];
@@ -1819,6 +1859,12 @@ import_revoke_cert( const char *fname, kbnode_t node, struct stats_s *stats )
 
   /* Read the original keyblock. */
   hd = keydb_new ();
+  if (!hd)
+    {
+      rc = gpg_error_from_syserror ();
+      goto leave;
+    }
+
   {
     byte afp[MAX_FINGERPRINT_LEN];
     size_t an;
@@ -2424,9 +2470,9 @@ revocation_present (ctrl_t ctrl, kbnode_t keyblock)
                          char *tempkeystr=xstrdup(keystr_from_pk(pk));
 
                          /* No, so try and get it */
-                         if(opt.keyserver
-                            && (opt.keyserver_options.options
-                                & KEYSERVER_AUTO_KEY_RETRIEVE))
+                         if ((opt.keyserver_options.options
+                               & KEYSERVER_AUTO_KEY_RETRIEVE)
+                              && keyserver_any_configured (ctrl))
                            {
                              log_info(_("WARNING: key %s may be revoked:"
                                         " fetching revocation key %s\n"),
@@ -2673,7 +2719,7 @@ append_uid (kbnode_t keyblock, kbnode_t node, int *n_sigs,
   (void)fname;
   (void)keyid;
 
-  assert(node->pkt->pkttype == PKT_USER_ID );
+  log_assert (node->pkt->pkttype == PKT_USER_ID );
 
   /* find the position */
   for (n = keyblock; n; n_where = n, n = n->next)
@@ -2726,8 +2772,8 @@ merge_sigs (kbnode_t dst, kbnode_t src, int *n_sigs,
   (void)fname;
   (void)keyid;
 
-  assert(dst->pkt->pkttype == PKT_USER_ID );
-  assert(src->pkt->pkttype == PKT_USER_ID );
+  log_assert (dst->pkt->pkttype == PKT_USER_ID);
+  log_assert (src->pkt->pkttype == PKT_USER_ID);
 
   for (n=src->next; n && n->pkt->pkttype != PKT_USER_ID; n = n->next)
     {
@@ -2774,8 +2820,8 @@ merge_keysigs (kbnode_t dst, kbnode_t src, int *n_sigs,
   (void)fname;
   (void)keyid;
 
-  assert (dst->pkt->pkttype == PKT_PUBLIC_SUBKEY
-          || dst->pkt->pkttype == PKT_SECRET_SUBKEY);
+  log_assert (dst->pkt->pkttype == PKT_PUBLIC_SUBKEY
+              || dst->pkt->pkttype == PKT_SECRET_SUBKEY);
 
   for (n=src->next; n ; n = n->next)
     {
@@ -2835,8 +2881,8 @@ append_key (kbnode_t keyblock, kbnode_t node, int *n_sigs,
   (void)fname;
   (void)keyid;
 
-  assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
-          || node->pkt->pkttype == PKT_SECRET_SUBKEY );
+  log_assert (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+              || node->pkt->pkttype == PKT_SECRET_SUBKEY);
 
   while (node)
     {