diff options
Diffstat (limited to 'g10/getkey.c')
-rw-r--r-- | g10/getkey.c | 97 |
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; |