* tdbio.h, tdbio.c (tdbio_read_record, tdbio_write_record): Store trust
[gnupg.git] / g10 / getkey.c
index a123f5f..ffd5042 100644 (file)
@@ -374,8 +374,8 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
 /* Get a public key and store it into the allocated pk.  This function
    differs from get_pubkey() in that it does not do a check of the key
    to avoid recursion.  It should be used only in very certain cases.  */
-static int
-get_pubkey_direct (PKT_public_key *pk, u32 *keyid)
+int
+get_pubkey_fast (PKT_public_key *pk, u32 *keyid)
 {
   int rc = 0;
   KEYDB_HANDLE hd;
@@ -417,7 +417,10 @@ get_pubkey_direct (PKT_public_key *pk, u32 *keyid)
            ||  keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY );
   copy_public_key (pk, keyblock->pkt->pkt.public_key );
   release_kbnode (keyblock);
-  cache_public_key (pk);
+
+  /* Not caching key here since it won't have all of the fields
+     properly set. */
+
   return 0;
 }
 
@@ -903,6 +906,54 @@ get_pubkey_byfprint( PKT_public_key *pk,
     return rc;
 }
 
+
+/* Get a public key and store it into the allocated pk.  This function
+   differs from get_pubkey_byfprint() in that it does not do a check
+   of the key to avoid recursion.  It should be used only in very
+   certain cases.  PK may be NULL to check just for the existance of
+   the key. */
+int
+get_pubkey_byfprint_fast (PKT_public_key *pk,
+                          const byte *fprint, size_t fprint_len)
+{
+  int rc = 0;
+  KEYDB_HANDLE hd;
+  KBNODE keyblock;
+  byte fprbuf[MAX_FINGERPRINT_LEN];
+  int i;
+  
+  for (i=0; i < MAX_FINGERPRINT_LEN && i < fprint_len; i++)
+    fprbuf[i] = fprint[i];
+  while (i < MAX_FINGERPRINT_LEN) 
+    fprbuf[i++] = 0;
+
+  hd = keydb_new (0);
+  rc = keydb_search_fpr (hd, fprbuf);
+  if (rc == -1)
+    {
+      keydb_release (hd);
+      return G10ERR_NO_PUBKEY;
+    }
+  rc = keydb_get_keyblock (hd, &keyblock);
+  keydb_release (hd);
+  if (rc) 
+    {
+      log_error ("keydb_get_keyblock failed: %s\n", g10_errstr(rc));
+      return G10ERR_NO_PUBKEY;
+    }
+  
+  assert ( keyblock->pkt->pkttype == PKT_PUBLIC_KEY
+           ||  keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY );
+  if (pk)
+    copy_public_key (pk, keyblock->pkt->pkt.public_key );
+  release_kbnode (keyblock);
+
+  /* Not caching key here since it won't have all of the fields
+     properly set. */
+
+  return 0;
+}
+
 /****************
  * Search for a key with the given fingerprint and return the
  * complete keyblock which may have more than only this key.
@@ -1521,7 +1572,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked )
                        trusted key is still valid - if it has been
                        revoked or the user should also renmove the
                        ultimate trust flag.  */
-                   if(get_pubkey_direct(ultimate_pk,sig->keyid)==0 &&
+                   if(get_pubkey_fast(ultimate_pk,sig->keyid)==0 &&
                       check_key_signature(keyblock,k,NULL)==0 &&
                       get_ownertrust(ultimate_pk)==TRUST_ULTIMATE)
                      {
@@ -1784,21 +1835,6 @@ merge_selfsigs( KBNODE keyblock )
     }
 
     merge_selfsigs_main ( keyblock, &revoked );
-    main_pk = keyblock->pkt->pkt.public_key;
-    if ( revoked ) {
-        /* if the primary key has been revoked we better set the revoke
-         * flag on that key and all subkeys */
-        for(k=keyblock; k; k = k->next ) {
-            if ( k->pkt->pkttype == PKT_PUBLIC_KEY
-                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
-                PKT_public_key *pk = k->pkt->pkt.public_key;
-                pk->is_revoked = 1;
-                pk->main_keyid[0] = main_pk->main_keyid[0];
-                pk->main_keyid[1] = main_pk->main_keyid[1];
-            }
-       }
-        return;
-    }
 
     /* now merge in the data from each of the subkeys */
     for(k=keyblock; k; k = k->next ) {
@@ -1807,12 +1843,25 @@ merge_selfsigs( KBNODE keyblock )
         }
     }
 
-    /* If the main key is not valid, then the subkeys aren't either,
-       even if they have binding sigs. */
-    if(!main_pk->is_valid)
-      for(k=keyblock; k; k=k->next)
-       if(k->pkt->pkttype==PKT_PUBLIC_SUBKEY)
-         k->pkt->pkt.public_key->is_valid=0;
+    main_pk = keyblock->pkt->pkt.public_key;
+    if ( revoked || main_pk->has_expired || !main_pk->is_valid ) {
+        /* if the primary key is revoked, expired, or invalid we
+         * better set the appropriate flags on that key and all
+         * subkeys */
+        for(k=keyblock; k; k = k->next ) {
+            if ( k->pkt->pkttype == PKT_PUBLIC_KEY
+                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
+                PKT_public_key *pk = k->pkt->pkt.public_key;
+               if(!main_pk->is_valid)
+                 pk->is_valid = 0;
+               if(revoked)
+                 pk->is_revoked = 1;
+                if(main_pk->has_expired)
+                 pk->has_expired = main_pk->has_expired;
+            }
+       }
+       return;
+    }
 
     /* set the preference list of all keys to those of the primary real
      * user ID.  Note: we use these preferences when we don't know by
@@ -2007,7 +2056,8 @@ finish_lookup (GETKEY_CTX ctx)
     unsigned int req_usage = ( ctx->req_usage & USAGE_MASK );
     /* Request the primary if we're certifying another key, and also
        if signing data while --pgp6 or --pgp7 is on since pgp 6 and 7
-       do not understand signatures made by a signing subkey. */
+       do not understand signatures made by a signing subkey.  PGP 8
+       does. */
     int req_prim = (ctx->req_usage & PUBKEY_USAGE_CERT) ||
       ((opt.pgp6 || opt.pgp7) && (ctx->req_usage & PUBKEY_USAGE_SIG));
     u32 latest_date;
@@ -2283,6 +2333,9 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
  *                   b) to get the ultimately trusted keys.
  *        The a) usage might have some problems.
  *
+ * set with_subkeys true to include subkeys
+ * set with_spm true to include secret-parts-missing keys
+ *
  * Enumerate all primary secret keys.  Caller must use these procedure:
  *  1) create a void pointer and initialize it to NULL
  *  2) pass this void pointer by reference to this function
@@ -2293,7 +2346,8 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
  *     so that can free it's context.
  */
 int
-enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
+enum_secret_keys( void **context, PKT_secret_key *sk,
+                 int with_subkeys, int with_spm )
 {
     int rc=0;
     struct {
@@ -2328,9 +2382,11 @@ enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
     do {
         /* get the next secret key from the current keyblock */
         for (; c->node; c->node = c->node->next) {
-            if (c->node->pkt->pkttype == PKT_SECRET_KEY
+            if ((c->node->pkt->pkttype == PKT_SECRET_KEY
                 || (with_subkeys
-                    && c->node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
+                    && c->node->pkt->pkttype == PKT_SECRET_SUBKEY) )
+               && !(c->node->pkt->pkt.secret_key->protect.s2k.mode==1001
+                    && !with_spm)) {
                 copy_secret_key (sk, c->node->pkt->pkt.secret_key );
                 c->node = c->node->next;
                 return 0; /* found */