summaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/getkey.c')
-rw-r--r--g10/getkey.c97
1 files changed, 69 insertions, 28 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 4642174..20b717b 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -767,9 +767,11 @@ get_seckey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid)
if (!err)
{
- err = agent_probe_secret_key (/*ctrl*/NULL, pk);
- if (err)
- release_public_key_parts (pk);
+ if (!agent_probe_secret_key (/*ctrl*/NULL, pk))
+ {
+ release_public_key_parts (pk);
+ err = gpg_error (GPG_ERR_NO_SECKEY);
+ }
}
return err;
@@ -1794,7 +1796,8 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
*
* This function returns 0 on success. Otherwise, an error code is
* returned. In particular, GPG_ERR_NO_PUBKEY is returned if the key
- * is not found.
+ * is not found. If R_KEYBLOCK is not NULL and a key was found the
+ * keyblock is stored there; otherwiese NULL is stored there.
*
* The self-signed data has already been merged into the public key
* using merge_selfsigs. The caller must release the content of PK by
@@ -1802,13 +1805,17 @@ get_best_pubkey_byname (ctrl_t ctrl, enum get_pubkey_modes mode,
* free_public_key).
*/
gpg_error_t
-get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
+get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname,
+ kbnode_t *r_keyblock)
{
gpg_error_t err;
kbnode_t keyblock;
kbnode_t found_key;
unsigned int infoflags;
+ if (r_keyblock)
+ *r_keyblock = NULL;
+
err = read_key_from_file_or_buffer (ctrl, fname, NULL, 0, &keyblock);
if (!err)
{
@@ -1823,7 +1830,10 @@ get_pubkey_fromfile (ctrl_t ctrl, PKT_public_key *pk, const char *fname)
err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
}
- release_kbnode (keyblock);
+ if (!err && r_keyblock)
+ *r_keyblock = keyblock;
+ else
+ release_kbnode (keyblock);
return err;
}
@@ -1885,12 +1895,12 @@ get_pubkey_from_buffer (ctrl_t ctrl, PKT_public_key *pkbuf,
* returned public key may be a subkey rather than the primary key.
* Note: The self-signed data has already been merged into the public
* key using merge_selfsigs. Free *PK by calling
- * release_public_key_parts (or, if PK was allocated using xfree, you
+ * release_public_key_parts (or, if PK was allocated using xmalloc, you
* can use free_public_key, which calls release_public_key_parts(PK)
* and then xfree(PK)).
*
* If PK->REQ_USAGE is set, it is used to filter the search results.
- * (Thus, if PK is not NULL, PK->REQ_USAGE must be valid!!!) See the
+ * Thus, if PK is not NULL, PK->REQ_USAGE must be valid! See the
* documentation for finish_lookup to understand exactly how this is
* used.
*
@@ -2149,10 +2159,12 @@ parse_def_secret_key (ctrl_t ctrl)
continue;
}
- err = agent_probe_secret_key (ctrl, pk);
- if (! err)
- /* This is a valid key. */
- break;
+ if (agent_probe_secret_key (ctrl, pk))
+ {
+ /* This is a valid key. */
+ err = 0;
+ break;
+ }
}
while ((node = find_next_kbnode (node, PKT_PUBLIC_SUBKEY)));
@@ -2491,7 +2503,8 @@ merge_keys_and_selfsig (ctrl_t ctrl, kbnode_t keyblock)
}
-static int
+/* This function parses the key flags and returns PUBKEY_USAGE_ flags. */
+unsigned int
parse_key_usage (PKT_signature * sig)
{
int key_usage = 0;
@@ -2531,11 +2544,29 @@ parse_key_usage (PKT_signature * sig)
flags &= ~0x20;
}
+ if ((flags & 0x80))
+ {
+ key_usage |= PUBKEY_USAGE_GROUP;
+ flags &= ~0x80;
+ }
+
if (flags)
key_usage |= PUBKEY_USAGE_UNKNOWN;
+ n--;
+ p++;
+ if (n)
+ {
+ flags = *p;
+ if ((flags & 0x04))
+ key_usage |= PUBKEY_USAGE_RENC;
+ if ((flags & 0x08))
+ key_usage |= PUBKEY_USAGE_TIME;
+ }
+
if (!key_usage)
key_usage |= PUBKEY_USAGE_NONE;
+
}
else if (p) /* Key flags of length zero. */
key_usage |= PUBKEY_USAGE_NONE;
@@ -2763,7 +2794,7 @@ merge_selfsigs_main (ctrl_t ctrl, kbnode_t keyblock, int *r_revoked,
* and there was no way to change it, so we start with the one
* from the key packet. We do not support v3 keys anymore but
* we keep the code in case a future key versions introduces a
- * hadr expire time again. */
+ * hard expire time again. */
key_expire = pk->max_expiredate;
key_expire_seen = 1;
}
@@ -3669,21 +3700,31 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
/* For an exact match mark the primary or subkey that matched the
- low-level search criteria. */
- if (want_exact)
+ * low-level search criteria. Use this loop also to sort our keys
+ * found using an ADSK fingerprint. */
+ for (k = keyblock; k; k = k->next)
{
- for (k = keyblock; k; k = k->next)
- {
- if ((k->flag & 1))
- {
- log_assert (k->pkt->pkttype == PKT_PUBLIC_KEY
- || k->pkt->pkttype == PKT_PUBLIC_SUBKEY);
- foundk = k;
+ if ((k->flag & 1) && (k->pkt->pkttype == PKT_PUBLIC_KEY
+ || k->pkt->pkttype == PKT_PUBLIC_SUBKEY))
+ {
+ if (want_exact)
+ {
+ if (DBG_LOOKUP)
+ log_debug ("finish_lookup: exact search requested and found\n");
+ foundk = k;
pk = k->pkt->pkt.public_key;
pk->flags.exact = 1;
- break;
- }
- }
+ break;
+ }
+ else if ((k->pkt->pkt.public_key->pubkey_usage == PUBKEY_USAGE_RENC))
+ {
+ if (DBG_LOOKUP)
+ log_debug ("finish_lookup: found via ADSK - not selected\n");
+ if (r_flags)
+ *r_flags |= LOOKUP_NOT_SELECTED;
+ return NULL; /* Not found. */
+ }
+ }
}
/* Get the user id that matched that low-level search criteria. */
@@ -3779,7 +3820,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact,
continue;
}
- if (want_secret && agent_probe_secret_key (NULL, pk))
+ if (want_secret && !agent_probe_secret_key (NULL, pk))
{
if (DBG_LOOKUP)
log_debug ("\tno secret key\n");
@@ -4528,7 +4569,7 @@ have_secret_key_with_kid (u32 *keyid)
log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
- if (!agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
+ if (agent_probe_secret_key (NULL, node->pkt->pkt.public_key))
result = 1; /* Secret key available. */
else
result = 0;