diff --git a/g10/import.c b/g10/import.c index e3c8c37b4..d22c8f457 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1394,38 +1394,69 @@ apply_meta_data (kbnode_t keyblock, int origin, const char *url) { if (is_deleted_kbnode (node)) ; - else if (node->pkt->pkttype == PKT_PUBLIC_KEY - && (origin == KEYORG_WKD || origin == KEYORG_DANE)) + else if (node->pkt->pkttype == PKT_PUBLIC_KEY) { - /* For WKD and DANE we insert origin information also for - * the key but we don't record the URL because we have have - * no use for that: An update using a keyserver has higher - * precedence and will thus update this origin info. For - * refresh using WKD or DANE we need to go via the User ID - * anyway. Recall that we are only inserting a new key. */ PKT_public_key *pk = node->pkt->pkt.public_key; - pk->keyorg = origin; - pk->keyupdate = curtime; + if (origin == KEYORG_WKD || origin == KEYORG_DANE) + { + /* For WKD and DANE we insert origin information also + * for the key but we don't record the URL because we + * have have no use for that: An update using a + * keyserver has higher precedence and will thus update + * this origin info. For refresh using WKD or DANE we + * need to go via the User ID anyway. Recall that we + * are only inserting a new key. */ + pk->keyorg = origin; + pk->keyupdate = curtime; + } + else if (origin == KEYORG_KS && url) + { + /* If the key was retrieved from a keyserver using a + * fingerprint request we add the meta information. + * Note that the use of a fingerprint needs to be + * enforced by the caller of the import function. This + * is commonly triggered by verifying a modern signature + * which has an Issuer Fingerprint signature + * subpacket. */ + pk->keyorg = origin; + pk->keyupdate = curtime; + pk->updateurl = xtrystrdup (url); + if (!pk->updateurl) + return gpg_error_from_syserror (); + } } - else if (node->pkt->pkttype == PKT_USER_ID - && (origin == KEYORG_WKD || origin == KEYORG_DANE)) + else if (node->pkt->pkttype == PKT_USER_ID) { - /* We insert origin information on a UID only when we - * received them via the Web Key Directory or a DANE record. - * The key we receive here from the WKD has been filtered to - * contain only the user ID as looked up in the WKD. For a - * DANE origin we this should also be the case. Thus we - * will see here only one user id. */ PKT_user_id *uid = node->pkt->pkt.user_id; - uid->keyorg = origin; - uid->keyupdate = curtime; - if (url) + if (origin == KEYORG_WKD || origin == KEYORG_DANE) { - uid->updateurl = xtrystrdup (url); - if (!uid->updateurl) - return gpg_error_from_syserror (); + /* We insert origin information on a UID only when we + * received them via the Web Key Directory or a DANE + * record. The key we receive here from the WKD has + * been filtered to contain only the user ID as looked + * up in the WKD. For a DANE origin we this should also + * be the case. Thus we will see here only one user + * id. */ + uid->keyorg = origin; + uid->keyupdate = curtime; + if (url) + { + uid->updateurl = xtrystrdup (url); + if (!uid->updateurl) + return gpg_error_from_syserror (); + } + } + else if (origin == KEYORG_KS && url) + { + /* If the key was retrieved from a keyserver using a + * fingerprint request we mark that also in the user ID. + * However we do not store the keyserver URL in the UID. + * A later update (merge) from a more trusted source + * will replace this info. */ + uid->keyorg = origin; + uid->keyupdate = curtime; } } } diff --git a/g10/keyserver.c b/g10/keyserver.c index 9586448fa..4d2a2c873 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1590,11 +1590,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, { gpg_error_t err = 0; char **pattern; - int idx, npat; + int idx, npat, npat_fpr; estream_t datastream; char *source = NULL; size_t linelen; /* Estimated linelen for KS_GET. */ size_t n; + int only_fprs; #define MAX_KS_GET_LINELEN 950 /* Somewhat lower than the real limit. */ @@ -1613,7 +1614,7 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, but we are sure that R_NDESC_USED has been updated. This avoids a possible indefinite loop. */ linelen = 17; /* "KS_GET --quick --" */ - for (npat=idx=0; idx < ndesc; idx++) + for (npat=npat_fpr=0, idx=0; idx < ndesc; idx++) { int quiet = 0; @@ -1635,6 +1636,8 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, desc[idx].mode == KEYDB_SEARCH_MODE_FPR20? 20 : 16, pattern[npat]+2); npat++; + if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20) + npat_fpr++; } } else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID) @@ -1716,6 +1719,8 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, this is different from NPAT. */ *r_ndesc_used = idx; + only_fprs = (npat && npat == npat_fpr); + err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, quick, &datastream, &source); for (idx=0; idx < npat; idx++) @@ -1747,7 +1752,8 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc, (opt.keyserver_options.import_options | IMPORT_NO_SECKEY), keyserver_retrieval_screener, &screenerarg, - 0 /* FIXME? */, NULL); + only_fprs? KEYORG_KS : 0, + source); } es_fclose (datastream); xfree (source);