gpgv,w32: Fix --status-fd.
[gnupg.git] / g10 / getkey.c
index 648c230..163ab80 100644 (file)
@@ -1143,7 +1143,7 @@ key_byname (GETKEY_CTX *retctx, strlist_t namelist,
 
 /* Find a public key identified by NAME.
  *
 
 /* Find a public key identified by NAME.
  *
- * If name appears to be a valid valid RFC822 mailbox (i.e., email
+ * If name appears to be a valid RFC822 mailbox (i.e., email
  * address) and auto key lookup is enabled (no_akl == 0), then the
  * specified auto key lookup methods (--auto-key-lookup) are used to
  * import the key into the local keyring.  Otherwise, just the local
  * address) and auto key lookup is enabled (no_akl == 0), then the
  * specified auto key lookup methods (--auto-key-lookup) are used to
  * import the key into the local keyring.  Otherwise, just the local
@@ -1541,9 +1541,9 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
       if (! match)
         continue;
 
       if (! match)
         continue;
 
-      new->uid = uid;
+      new->uid = scopy_user_id (uid);
       new->validity =
       new->validity =
-        get_validity (ctrl, &new->key, uid, NULL, 0) & TRUST_MASK;
+        get_validity (ctrl, new_keyblock, &new->key, uid, NULL, 0) & TRUST_MASK;
       new->valid = 1;
 
       if (! old->valid)
       new->valid = 1;
 
       if (! old->valid)
@@ -1577,45 +1577,50 @@ get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
   int rc;
   struct getkey_ctx_s *ctx = NULL;
 
   int rc;
   struct getkey_ctx_s *ctx = NULL;
 
+  if (retctx)
+    *retctx = NULL;
+
   rc = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
                           NULL, include_unusable, no_akl);
   if (rc)
     {
       if (ctx)
         getkey_end (ctx);
   rc = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
                           NULL, include_unusable, no_akl);
   if (rc)
     {
       if (ctx)
         getkey_end (ctx);
-      if (retctx)
-        *retctx = NULL;
       return rc;
     }
 
       return rc;
     }
 
-  if (is_valid_mailbox (name))
+  if (is_valid_mailbox (name) && ctx)
     {
       /* Rank results and return only the most relevant key.  */
       struct pubkey_cmp_cookie best = { 0 }, new;
     {
       /* Rank results and return only the most relevant key.  */
       struct pubkey_cmp_cookie best = { 0 }, new;
-      while (getkey_next (ctx, &new.key, NULL) == 0)
+      KBNODE new_keyblock;
+      while (getkey_next (ctx, &new.key, &new_keyblock) == 0)
         {
         {
-          KBNODE new_keyblock = get_pubkeyblock (pk_keyid (&new.key));
           int diff = pubkey_cmp (ctrl, name, &best, &new, new_keyblock);
           release_kbnode (new_keyblock);
           if (diff < 0)
             {
               /* New key is better.  */
               release_public_key_parts (&best.key);
           int diff = pubkey_cmp (ctrl, name, &best, &new, new_keyblock);
           release_kbnode (new_keyblock);
           if (diff < 0)
             {
               /* New key is better.  */
               release_public_key_parts (&best.key);
+              free_user_id (best.uid);
               best = new;
             }
           else if (diff > 0)
             {
               /* Old key is better.  */
               release_public_key_parts (&new.key);
               best = new;
             }
           else if (diff > 0)
             {
               /* Old key is better.  */
               release_public_key_parts (&new.key);
+              free_user_id (new.uid);
             }
           else
             {
               /* A tie.  Keep the old key.  */
               release_public_key_parts (&new.key);
             }
           else
             {
               /* A tie.  Keep the old key.  */
               release_public_key_parts (&new.key);
+              free_user_id (new.uid);
             }
         }
       getkey_end (ctx);
       ctx = NULL;
             }
         }
       getkey_end (ctx);
       ctx = NULL;
+      free_user_id (best.uid);
 
       if (best.valid)
         {
 
       if (best.valid)
         {
@@ -2158,6 +2163,7 @@ gpg_error_t
 getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
 {
   int rc; /* Fixme:  Make sure this is proper gpg_error */
 getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
 {
   int rc; /* Fixme:  Make sure this is proper gpg_error */
+  KBNODE keyblock = NULL;
   KBNODE found_key = NULL;
 
   /* We need to disable the caching so that for an exact key search we
   KBNODE found_key = NULL;
 
   /* We need to disable the caching so that for an exact key search we
@@ -2166,11 +2172,18 @@ getkey_next (getkey_ctx_t ctx, PKT_public_key *pk, kbnode_t *ret_keyblock)
      used without respecting the current file pointer!  */
   keydb_disable_caching (ctx->kr_handle);
 
      used without respecting the current file pointer!  */
   keydb_disable_caching (ctx->kr_handle);
 
-  rc = lookup (ctx, ret_keyblock, &found_key, ctx->want_secret);
+  /* FOUND_KEY is only valid as long as RET_KEYBLOCK is.  If the
+   * caller wants PK, but not RET_KEYBLOCK, we need hand in our own
+   * keyblock.  */
+  if (pk && ret_keyblock == NULL)
+      ret_keyblock = &keyblock;
+
+  rc = lookup (ctx, ret_keyblock, pk ? &found_key : NULL, ctx->want_secret);
   if (!rc && pk)
     {
       log_assert (found_key);
       pk_from_block (pk, NULL, found_key);
   if (!rc && pk)
     {
       log_assert (found_key);
       pk_from_block (pk, NULL, found_key);
+      release_kbnode (keyblock);
     }
 
   return rc;
     }
 
   return rc;
@@ -3324,6 +3337,9 @@ merge_selfsigs (KBNODE keyblock)
  * in CTX.  If so, return the node of an appropriate key or subkey.
  * Otherwise, return NULL if there was no appropriate key.
  *
  * in CTX.  If so, return the node of an appropriate key or subkey.
  * Otherwise, return NULL if there was no appropriate key.
  *
+ * Note that we do not return a reference, i.e. the result must not be
+ * freed using 'release_kbnode'.
+ *
  * In case the primary key is not required, select a suitable subkey.
  * We need the primary key if PUBKEY_USAGE_CERT is set in REQ_USAGE or
  * we are in PGP6 or PGP7 mode and PUBKEY_USAGE_SIG is set in
  * In case the primary key is not required, select a suitable subkey.
  * We need the primary key if PUBKEY_USAGE_CERT is set in REQ_USAGE or
  * we are in PGP6 or PGP7 mode and PUBKEY_USAGE_SIG is set in
@@ -3584,8 +3600,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
   if (latest_key)
     {
       pk = latest_key->pkt->pkt.public_key;
   if (latest_key)
     {
       pk = latest_key->pkt->pkt.public_key;
-      if (pk->user_id)
-       free_user_id (pk->user_id);
+      free_user_id (pk->user_id);
       pk->user_id = scopy_user_id (foundu);
     }
 
       pk->user_id = scopy_user_id (foundu);
     }
 
@@ -3643,7 +3658,12 @@ print_status_key_considered (kbnode_t keyblock, unsigned int flags)
    all of the self-signed data into the keys, subkeys and user id
    packets (see the merge_selfsigs for details).
 
    all of the self-signed data into the keys, subkeys and user id
    packets (see the merge_selfsigs for details).
 
-   On success the key's keyblock is stored at *RET_KEYBLOCK.  */
+   On success the key's keyblock is stored at *RET_KEYBLOCK, and the
+   specific subkey is stored at *RET_FOUND_KEY.  Note that we do not
+   return a reference in *RET_FOUND_KEY, i.e. the result must not be
+   freed using 'release_kbnode', and it is only valid until
+   *RET_KEYBLOCK is deallocated.  Therefore, if RET_FOUND_KEY is not
+   NULL, then RET_KEYBLOCK must not be NULL.  */
 static int
 lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
        int want_secret)
 static int
 lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
        int want_secret)
@@ -3654,6 +3674,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
   KBNODE found_key = NULL;
   unsigned int infoflags;
 
   KBNODE found_key = NULL;
   unsigned int infoflags;
 
+  log_assert (ret_found_key == NULL || ret_keyblock != NULL);
   if (ret_keyblock)
     *ret_keyblock = NULL;
 
   if (ret_keyblock)
     *ret_keyblock = NULL;
 
@@ -3715,8 +3736,10 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, kbnode_t *ret_found_key,
   if (!rc)
     {
       if (ret_keyblock)
   if (!rc)
     {
       if (ret_keyblock)
-        *ret_keyblock = keyblock; /* Return the keyblock.  */
-      keyblock = NULL;
+        {
+          *ret_keyblock = keyblock; /* Return the keyblock.  */
+          keyblock = NULL;
+        }
     }
   else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key)
     rc = want_secret? GPG_ERR_UNUSABLE_SECKEY : GPG_ERR_UNUSABLE_PUBKEY;
     }
   else if (gpg_err_code (rc) == GPG_ERR_NOT_FOUND && no_suitable_key)
     rc = want_secret? GPG_ERR_UNUSABLE_SECKEY : GPG_ERR_UNUSABLE_PUBKEY;
@@ -4130,10 +4153,8 @@ parse_auto_key_locate (char *options)
        akl->type = AKL_LDAP;
       else if (ascii_strcasecmp (tok, "keyserver") == 0)
        akl->type = AKL_KEYSERVER;
        akl->type = AKL_LDAP;
       else if (ascii_strcasecmp (tok, "keyserver") == 0)
        akl->type = AKL_KEYSERVER;
-#ifdef USE_DNS_CERT
       else if (ascii_strcasecmp (tok, "cert") == 0)
        akl->type = AKL_CERT;
       else if (ascii_strcasecmp (tok, "cert") == 0)
        akl->type = AKL_CERT;
-#endif
       else if (ascii_strcasecmp (tok, "pka") == 0)
        akl->type = AKL_PKA;
       else if (ascii_strcasecmp (tok, "dane") == 0)
       else if (ascii_strcasecmp (tok, "pka") == 0)
        akl->type = AKL_PKA;
       else if (ascii_strcasecmp (tok, "dane") == 0)