diff options
author | Werner Koch <[email protected]> | 2010-04-21 16:26:17 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2010-04-21 16:26:17 +0000 |
commit | a1412b05debe693e6aabaf2c2c337bc33f7dfd41 (patch) | |
tree | 214dc8928b73aaa385d69eaa180164318ff0bb93 /g10/getkey.c | |
parent | Disable card support for now (diff) | |
download | gnupg-a1412b05debe693e6aabaf2c2c337bc33f7dfd41.tar.gz gnupg-a1412b05debe693e6aabaf2c2c337bc33f7dfd41.zip |
More changes on the way to remove secring.gpg.
Diffstat (limited to 'g10/getkey.c')
-rw-r--r-- | g10/getkey.c | 326 |
1 files changed, 142 insertions, 184 deletions
diff --git a/g10/getkey.c b/g10/getkey.c index 78d5a1eb5..4929974a3 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -35,6 +35,7 @@ #include "trustdb.h" #include "i18n.h" #include "keyserver-internal.h" +#include "call-agent.h" #define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE #define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE @@ -325,18 +326,6 @@ pk_from_block (GETKEY_CTX ctx, PKT_public_key * pk, KBNODE keyblock) copy_public_key (pk, a->pkt->pkt.public_key); } -static void -sk_from_block (GETKEY_CTX ctx, PKT_secret_key * sk, KBNODE keyblock) -{ - KBNODE a = ctx->found_key ? ctx->found_key : keyblock; - - assert (a->pkt->pkttype == PKT_SECRET_KEY - || a->pkt->pkttype == PKT_SECRET_SUBKEY); - - copy_secret_key (sk, a->pkt->pkt.secret_key); -} - - /* Get a public key and store it into the allocated pk can be called * with PK set to NULL to just read it into some internal * structures. */ @@ -378,7 +367,7 @@ get_pubkey (PKT_public_key * pk, u32 * keyid) memset (&ctx, 0, sizeof ctx); ctx.exact = 1; /* Use the key ID exactly as given. */ ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; ctx.items[0].u.kid[0] = keyid[0]; @@ -437,7 +426,7 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid) } #endif - hd = keydb_new (0); + hd = keydb_new (); rc = keydb_search_kid (hd, keyid); if (rc == -1) { @@ -480,7 +469,7 @@ get_pubkeyblock (u32 * keyid) memset (&ctx, 0, sizeof ctx); /* No need to set exact here because we want the entire block. */ ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; ctx.items[0].u.kid[0] = keyid[0]; @@ -494,67 +483,43 @@ get_pubkeyblock (u32 * keyid) -/**************** - * Get a secret key and store it into sk +/* + * Get a public key and store it into PK. This functions check that a + * corresponding secret key is available. With no secret key it does + * not succeeed. */ -int -get_seckey (PKT_secret_key * sk, u32 * keyid) +gpg_error_t +get_seckey (PKT_public_key *pk, u32 *keyid) { - int rc; + gpg_error_t err; struct getkey_ctx_s ctx; - KBNODE kb = NULL; + kbnode_t keyblock = NULL; memset (&ctx, 0, sizeof ctx); ctx.exact = 1; /* Use the key ID exactly as given. */ ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = KEYDB_SEARCH_MODE_LONG_KID; ctx.items[0].u.kid[0] = keyid[0]; ctx.items[0].u.kid[1] = keyid[1]; - ctx.req_algo = sk->req_algo; - ctx.req_usage = sk->req_usage; - rc = lookup (&ctx, &kb, 1); - if (!rc) + ctx.req_algo = pk->req_algo; + ctx.req_usage = pk->req_usage; + err = lookup (&ctx, &keyblock, 1); + if (!err) { - sk_from_block (&ctx, sk, kb); + pk_from_block (&ctx, pk, keyblock); } - get_seckey_end (&ctx); - release_kbnode (kb); - - if (!rc) - { - /* Check the secret key (this may prompt for a passprase to - * unlock the secret key. */ - /* rc = check_secret_key (sk, 0); */ - } - - return rc; -} + get_pubkey_end (&ctx); + release_kbnode (keyblock); + if (!err) + err = agent_probe_secret_key (/*ctrl*/NULL, pk); -/* Check whether the secret key is available. This is just a fast - * check and does not tell us whether the secret key is valid. It - * merely tells other whether there is some secret key. - * Returns: - * 0 := key is available - * G10ERR_NO_SECKEY := key not availabe - */ -int -seckey_available (u32 * keyid) -{ - int rc; - KEYDB_HANDLE hd = keydb_new (1); - - rc = keydb_search_kid (hd, keyid); - if (rc == -1) - rc = G10ERR_NO_SECKEY; - keydb_release (hd); - return rc; + return err; } - static int skip_unusable (void *dummy, u32 * keyid, PKT_user_id * uid) { @@ -599,16 +564,15 @@ leave: } -/* Try to get the pubkey by the userid. This function looks for the +/* Try to get the pubkey by the userid. This function looks for the * first pubkey certificate which has the given name in a user_id. If - * pk/sk has the pubkey algo set, the function will only return a - * pubkey with that algo. If namelist is NULL, the first key is - * returned. The caller should provide storage for either the pk or - * the sk. If ret_kb is not NULL the function will return the - * keyblock there. */ + * PK has the pubkey algo set, the function will only return a pubkey + * with that algo. If NAMELIST is NULL, the first key is returned. + * The caller should provide storage for the PK. If RET_KB is not + * NULL the function will return the keyblock there. */ static int -key_byname (GETKEY_CTX * retctx, strlist_t namelist, - PKT_public_key * pk, PKT_secret_key * sk, +key_byname (GETKEY_CTX *retctx, strlist_t namelist, + PKT_public_key *pk, int want_secret, int include_unusable, KBNODE * ret_kb, KEYDB_HANDLE * ret_kdbhd) { @@ -618,8 +582,6 @@ key_byname (GETKEY_CTX * retctx, strlist_t namelist, GETKEY_CTX ctx; KBNODE help_kb = NULL; - /* FIXME: Eventually remove the SK argument. */ - if (retctx) { /* Reset the returned context in case of error. */ @@ -671,7 +633,7 @@ key_byname (GETKEY_CTX * retctx, strlist_t namelist, } ctx->want_secret = want_secret; - ctx->kr_handle = keydb_new (0); + ctx->kr_handle = keydb_new (); if (!ret_kb) ret_kb = &help_kb; @@ -680,11 +642,7 @@ key_byname (GETKEY_CTX * retctx, strlist_t namelist, ctx->req_algo = pk->req_algo; ctx->req_usage = pk->req_usage; } - else if (sk) /* FIXME: We should remove this. */ - { - ctx->req_algo = sk->req_algo; - ctx->req_usage = sk->req_usage; - } + rc = lookup (ctx, ret_kb, want_secret); if (!rc && pk) { @@ -771,7 +729,7 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk, else { add_to_strlist (&namelist, name); - rc = key_byname (retctx, namelist, pk, NULL, 0, + rc = key_byname (retctx, namelist, pk, 0, include_unusable, ret_keyblock, ret_kdbhd); } @@ -805,7 +763,7 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk, } add_to_strlist (&namelist, name); rc = key_byname (anylocalfirst ? retctx : NULL, - namelist, pk, NULL, 0, + namelist, pk, 0, include_unusable, ret_keyblock, ret_kdbhd); break; @@ -904,7 +862,7 @@ get_pubkey_byname (GETKEY_CTX * retctx, PKT_public_key * pk, *retctx = NULL; } rc = key_byname (anylocalfirst ? retctx : NULL, - namelist, pk, NULL, 0, + namelist, pk, 0, include_unusable, ret_keyblock, ret_kdbhd); } if (!rc) @@ -943,7 +901,7 @@ int get_pubkey_bynames (GETKEY_CTX * retctx, PKT_public_key * pk, strlist_t names, KBNODE * ret_keyblock) { - return key_byname (retctx, names, pk, NULL, 0, 1, ret_keyblock, NULL); + return key_byname (retctx, names, pk, 0, 1, ret_keyblock, NULL); } int @@ -991,7 +949,7 @@ get_pubkey_byfprint (PKT_public_key * pk, memset (&ctx, 0, sizeof ctx); ctx.exact = 1; ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16 : KEYDB_SEARCH_MODE_FPR20; @@ -1028,7 +986,7 @@ get_pubkey_byfprint_fast (PKT_public_key * pk, while (i < MAX_FINGERPRINT_LEN) fprbuf[i++] = 0; - hd = keydb_new (0); + hd = keydb_new (); rc = keydb_search_fpr (hd, fprbuf); if (rc == -1) { @@ -1070,7 +1028,7 @@ get_keyblock_byfprint (KBNODE * ret_keyblock, const byte * fprint, memset (&ctx, 0, sizeof ctx); ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (0); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = (fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16 @@ -1086,15 +1044,15 @@ get_keyblock_byfprint (KBNODE * ret_keyblock, const byte * fprint, } -/* Get a secret key by name and store it into sk. - * If NAME is NULL use the default key. */ -static int -get_seckey_byname2 (GETKEY_CTX * retctx, - PKT_secret_key * sk, const char *name, int unprotect, - KBNODE * retblock) +/* Get a secret key by NAME and store it into PK. If NAME is NULL use + * the default key. This functions checks that a corresponding secret + * key is available. With no secret key it does not succeeed. */ +gpg_error_t +get_seckey_byname (PKT_public_key *pk, const char *name) { + gpg_error_t err; strlist_t namelist = NULL; - int rc, include_unusable = 1; + int include_unusable = 1; /* If we have no name, try to use the default secret key. If we have no default, we'll use the first usable one. */ @@ -1106,110 +1064,73 @@ get_seckey_byname2 (GETKEY_CTX * retctx, else include_unusable = 0; - rc = key_byname (retctx, namelist, NULL, sk, 1, include_unusable, - retblock, NULL); + err = key_byname (NULL, namelist, pk, 1, include_unusable, NULL, NULL); free_strlist (namelist); - /* if (!rc && unprotect) */ - /* rc = check_secret_key (sk, 0); */ - - return rc; -} - -int -get_seckey_byname (PKT_secret_key * sk, const char *name, int unlock) -{ - return get_seckey_byname2 (NULL, sk, name, unlock, NULL); -} - - -int -get_seckey_bynames (GETKEY_CTX * retctx, PKT_secret_key * sk, - strlist_t names, KBNODE * ret_keyblock) -{ - return key_byname (retctx, names, NULL, sk, 1, 1, ret_keyblock, NULL); -} - - -int -get_seckey_next (GETKEY_CTX ctx, PKT_secret_key * sk, KBNODE * ret_keyblock) -{ - int rc; - - rc = lookup (ctx, ret_keyblock, 1); - if (!rc && sk && ret_keyblock) - sk_from_block (ctx, sk, *ret_keyblock); - - return rc; + return err; } -void -get_seckey_end (GETKEY_CTX ctx) -{ - get_pubkey_end (ctx); -} - /* Search for a key with the given fingerprint. * FIXME: - * We should replace this with the _byname function. Thiscsan be done + * We should replace this with the _byname function. This can be done * by creating a userID conforming to the unified fingerprint style. */ -int -get_seckey_byfprint (PKT_secret_key * sk, - const byte * fprint, size_t fprint_len) +gpg_error_t +get_seckey_byfprint (PKT_public_key *pk, const byte * fprint, size_t fprint_len) { - int rc; + gpg_error_t err; if (fprint_len == 20 || fprint_len == 16) { struct getkey_ctx_s ctx; - KBNODE kb = NULL; + kbnode_t kb = NULL; memset (&ctx, 0, sizeof ctx); ctx.exact = 1; ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16 : KEYDB_SEARCH_MODE_FPR20; memcpy (ctx.items[0].u.fpr, fprint, fprint_len); - rc = lookup (&ctx, &kb, 1); - if (!rc && sk) - sk_from_block (&ctx, sk, kb); + err = lookup (&ctx, &kb, 1); + if (!err && pk) + pk_from_block (&ctx, pk, kb); release_kbnode (kb); - get_seckey_end (&ctx); + get_pubkey_end (&ctx); } else - rc = G10ERR_GENERAL; /* Oops */ - return rc; + err = gpg_error (GPG_ERR_BUG); + return err; } /* Search for a secret key with the given fingerprint and return the - complete keyblock which may have more than only this key. */ -int -get_seckeyblock_byfprint (KBNODE * ret_keyblock, const byte * fprint, - size_t fprint_len) + complete keyblock which may have more than only this key. Return + an error if no corresponding secret key is available. */ +gpg_error_t +get_seckeyblock_byfprint (kbnode_t *ret_keyblock, + const byte *fprint, size_t fprint_len) { - int rc; + gpg_error_t err; struct getkey_ctx_s ctx; if (fprint_len != 20 && fprint_len == 16) - return G10ERR_GENERAL; /* Oops */ + return gpg_error (GPG_ERR_BUG); memset (&ctx, 0, sizeof ctx); ctx.not_allocated = 1; - ctx.kr_handle = keydb_new (1); + ctx.kr_handle = keydb_new (); ctx.nitems = 1; ctx.items[0].mode = (fprint_len == 16 ? KEYDB_SEARCH_MODE_FPR16 : KEYDB_SEARCH_MODE_FPR20); memcpy (ctx.items[0].u.fpr, fprint, fprint_len); - rc = lookup (&ctx, ret_keyblock, 1); - get_seckey_end (&ctx); + err = lookup (&ctx, ret_keyblock, 1); + get_pubkey_end (&ctx); - return rc; + return err; } @@ -1220,7 +1141,7 @@ gpg_error_t getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk, strlist_t names, int want_secret, kbnode_t *ret_keyblock) { - return key_byname (retctx, names, pk, NULL, want_secret, 1, + return key_byname (retctx, names, pk, want_secret, 1, ret_keyblock, NULL); } @@ -1238,7 +1159,7 @@ getkey_bynames (getkey_ctx_t *retctx, PKT_public_key *pk, * * FIXME: Explain what is up with unusable keys. * - * FIXME: We also have the get_pubkey_byname fucntion which has a + * FIXME: We also have the get_pubkey_byname function which has a * different semantic. Should be merged with this one. */ gpg_error_t @@ -1256,7 +1177,7 @@ getkey_byname (getkey_ctx_t *retctx, PKT_public_key *pk, else with_unusable = 0; - err = key_byname (retctx, namelist, pk, NULL, want_secret, with_unusable, + err = key_byname (retctx, namelist, pk, want_secret, with_unusable, ret_keyblock, NULL); /* FIXME: Check that we really return GPG_ERR_NO_SECKEY if @@ -2538,7 +2459,7 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret) goto skip; } - if (want_secret && have_secret_key (ctx->keyblock)) + if (want_secret && !have_any_secret_key (NULL, ctx->keyblock)) goto skip; /* No secret key available. */ /* Warning: node flag bits 0 and 1 should be preserved by @@ -2586,9 +2507,7 @@ found: /**************** * FIXME: Replace by the generic function * It does not work as it is right now - it is used at - * 2 places: a) to get the key for an anonyous recipient - * b) to get the ultimately trusted keys. - * The a) usage might have some problems. + * one place: to get the key for an anonymous recipient. * * set with_subkeys true to include subkeys * set with_spm true to include secret-parts-missing keys @@ -2606,6 +2525,10 @@ int enum_secret_keys (void **context, PKT_secret_key * sk, int with_subkeys, int with_spm) { + log_debug ("FIXME: Anonymous recipient does not yet work\n"); + return -1; +#if 0 + int rc = 0; struct { @@ -2622,7 +2545,7 @@ enum_secret_keys (void **context, PKT_secret_key * sk, /* Make a new context. */ c = xmalloc_clear (sizeof *c); *context = c; - c->hd = keydb_new (1); + c->hd = keydb_new (1); /*FIXME*/ c->first = 1; c->keyblock = NULL; c->node = NULL; @@ -2676,6 +2599,7 @@ enum_secret_keys (void **context, PKT_secret_key * sk, while (!rc); return rc; /* Error. */ +#endif } @@ -2893,37 +2817,71 @@ parse_auto_key_locate (char *options) } -/* Return 0 if a secret key is available for the key described by - KEYBLOCK. FIXME: How do we handel subkeys? */ -gpg_error_t -have_secret_key (kbnode_t keyblock) +/* Return true if a secret key or secret subkey is available for one + of the public keys in KEYBLOCK. */ +int +have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) { - gpg_error_t err; - unsigned char fpr[MAX_FINGERPRINT_LEN]; - size_t fprlen; - KEYDB_HANDLE kdh; + kbnode_t node; - if (!keyblock || keyblock->pkt->pkttype != PKT_PUBLIC_KEY) - return gpg_error (GPG_ERR_NO_PUBKEY); /* Should not happen. */ - - fingerprint_from_pk (keyblock->pkt->pkt.public_key, fpr, &fprlen); - while (fprlen < MAX_FINGERPRINT_LEN) - fpr[fprlen++] = 0; - - /* FIXME: Always allocating a new handle is too slow. However this - entire implementation is anyway a temporary solution until we can - ask gpg-agent for the secret key. */ - kdh = keydb_new (1); - if (!kdh) - return gpg_error (GPG_ERR_GENERAL); + for (node = keyblock; node; node = node->next) + if ((node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + && !agent_probe_secret_key (ctrl, node->pkt->pkt.public_key)) + return 1; + return 0; +} - err = keydb_search_fpr (kdh, fpr); - if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF) - err = gpg_error (GPG_ERR_NO_SECKEY); - keydb_release (kdh); +/* Return true if a secret key is available for the public key with + * the given KEYID. This is just a fast check and does not tell us + * whether the secret key is valid. It merely tells os whether there + * is some secret key. */ +int +have_secret_key_with_kid (u32 *keyid) +{ + gpg_error_t err; + KEYDB_HANDLE kdbhd; + KEYDB_SEARCH_DESC desc; + kbnode_t keyblock; + kbnode_t node; + int result = 0; + + kdbhd = keydb_new (); + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_LONG_KID; + desc.u.kid[0] = keyid[0]; + desc.u.kid[1] = keyid[1]; + while (!result && !(err = keydb_search (kdbhd, &desc, 1))) + { + desc.mode = KEYDB_SEARCH_MODE_NEXT; + err = keydb_get_keyblock (kdbhd, &keyblock); + if (err) + { + log_error (_("error reading keyblock: %s\n"), g10_errstr (err)); + break; + } - return err; + for (node = keyblock; node; node = node->next) + { + /* Bit 0 of the flags is set if the search found the key + using that key or subkey. */ + if ((node->flag & 1)) + { + assert (node->pkt->pkttype == PKT_PUBLIC_KEY + || node->pkt->pkttype == PKT_PUBLIC_SUBKEY); + + if (!agent_probe_secret_key (NULL, node->pkt->pkt.public_key)) + { + result = 1; + break; + } + } + } + release_kbnode (keyblock); + } + keydb_release (kdbhd); + return result; } |