mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Store key origin info for new DANE and WKD retrieved keys.
* g10/import.c (apply_meta_data): Remove arg 'merge'. Add arg 'url'. Implement WKD and DANE key origin. (import_keys_internal): Add arg 'url' and change all callers. (import_keys_es_stream): Ditto. (import): Ditto. (import_one): Ditto. * g10/keylist.c (list_keyblock_print): Fix update URL printing. * g10/call-dirmngr.c (gpg_dirmngr_wkd_get): Add arg 'r_url' to return the SOURCE. Pass ks_status_cb to assuan_transact. * g10/keyserver.c (keyserver_import_wkd): Get that URL and pass it to the import function. -- Note that this only for new keys. Merging this info will be added soon. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
f6f0dd4d5e
commit
e7068bf92e
@ -41,7 +41,8 @@
|
||||
#include "call-dirmngr.h"
|
||||
|
||||
|
||||
/* Parameter structure used to gather status info. */
|
||||
/* Parameter structure used to gather status info. Note that it is
|
||||
* also used for WKD requests. */
|
||||
struct ks_status_parm_s
|
||||
{
|
||||
const char *keyword; /* Look for this keyword or NULL for "SOURCE". */
|
||||
@ -368,7 +369,7 @@ clear_context_flags (ctrl_t ctrl, assuan_context_t ctx)
|
||||
|
||||
|
||||
|
||||
/* Status callback for ks_list, ks_get and ks_search. */
|
||||
/* Status callback for ks_list, ks_get, ks_search, and wkd_get */
|
||||
static gpg_error_t
|
||||
ks_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
@ -1317,17 +1318,24 @@ gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
|
||||
|
||||
/* Ask the dirmngr to retrieve a key via the Web Key Directory
|
||||
* protocol. If QUICK is set the dirmngr is advised to use a shorter
|
||||
* timeout. On success a new estream with the key is stored at R_KEY.
|
||||
* timeout. On success a new estream with the key stored at R_KEY and the
|
||||
* url of the lookup (if any) stored at R_URL. Note that
|
||||
*/
|
||||
gpg_error_t
|
||||
gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
|
||||
gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
|
||||
estream_t *r_key, char **r_url)
|
||||
{
|
||||
gpg_error_t err;
|
||||
assuan_context_t ctx;
|
||||
struct dns_cert_parm_s parm;
|
||||
struct ks_status_parm_s stparm = { NULL };
|
||||
struct dns_cert_parm_s parm = { NULL };
|
||||
char *line = NULL;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
if (r_key)
|
||||
*r_key = NULL;
|
||||
|
||||
if (r_url)
|
||||
*r_url = NULL;
|
||||
|
||||
err = open_context (ctrl, &ctx);
|
||||
if (err)
|
||||
@ -1352,7 +1360,7 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
|
||||
goto leave;
|
||||
}
|
||||
err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
|
||||
NULL, NULL, NULL, &parm);
|
||||
NULL, NULL, ks_status_cb, &stparm);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
@ -1363,7 +1371,14 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick, estream_t *r_key)
|
||||
parm.memfp = NULL;
|
||||
}
|
||||
|
||||
if (r_url)
|
||||
{
|
||||
*r_url = stparm.source;
|
||||
stparm.source = NULL;
|
||||
}
|
||||
|
||||
leave:
|
||||
xfree (stparm.source);
|
||||
xfree (parm.fpr);
|
||||
xfree (parm.url);
|
||||
es_fclose (parm.memfp);
|
||||
|
@ -41,7 +41,7 @@ gpg_error_t gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid,
|
||||
unsigned char **r_fpr, size_t *r_fprlen,
|
||||
char **r_url);
|
||||
gpg_error_t gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
|
||||
estream_t *r_key);
|
||||
estream_t *r_key, char **r_url);
|
||||
|
||||
|
||||
#endif /*GNUPG_G10_CALL_DIRMNGR_H*/
|
||||
|
@ -4515,7 +4515,7 @@ main (int argc, char **argv)
|
||||
opt.import_options |= IMPORT_FAST; /* fall through */
|
||||
case aImport:
|
||||
import_keys (ctrl, argc? argv:NULL, argc, NULL,
|
||||
opt.import_options, opt.key_origin);
|
||||
opt.import_options, opt.key_origin, NULL);
|
||||
break;
|
||||
|
||||
/* TODO: There are a number of command that use this same
|
||||
|
81
g10/import.c
81
g10/import.c
@ -97,7 +97,8 @@ struct import_filter_s import_filter;
|
||||
static int import (ctrl_t ctrl,
|
||||
IOBUF inp, const char* fname, struct import_stats_s *stats,
|
||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||
import_screener_t screener, void *screener_arg, int origin);
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin, const char *url);
|
||||
static int read_block (IOBUF a, int with_meta,
|
||||
PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys);
|
||||
static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
|
||||
@ -107,7 +108,7 @@ static int import_one (ctrl_t ctrl,
|
||||
unsigned char **fpr, size_t *fpr_len,
|
||||
unsigned int options, int from_sk, int silent,
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin);
|
||||
int origin, const char *url);
|
||||
static int import_secret_one (ctrl_t ctrl, kbnode_t keyblock,
|
||||
struct import_stats_s *stats, int batch,
|
||||
unsigned int options, int for_migration,
|
||||
@ -432,7 +433,7 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
|
||||
unsigned char **fpr, size_t *fpr_len,
|
||||
unsigned int options,
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin)
|
||||
int origin, const char *url)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
@ -444,7 +445,7 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
|
||||
if (inp)
|
||||
{
|
||||
rc = import (ctrl, inp, "[stream]", stats, fpr, fpr_len, options,
|
||||
screener, screener_arg, origin);
|
||||
screener, screener_arg, origin, url);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -469,7 +470,7 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
|
||||
else
|
||||
{
|
||||
rc = import (ctrl, inp2, fname, stats, fpr, fpr_len, options,
|
||||
screener, screener_arg, origin);
|
||||
screener, screener_arg, origin, url);
|
||||
iobuf_close (inp2);
|
||||
/* Must invalidate that ugly cache to actually close it. */
|
||||
iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char*)fname);
|
||||
@ -503,10 +504,11 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
|
||||
|
||||
void
|
||||
import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
||||
import_stats_t stats_handle, unsigned int options, int origin)
|
||||
import_stats_t stats_handle, unsigned int options,
|
||||
int origin, const char *url)
|
||||
{
|
||||
import_keys_internal (ctrl, NULL, fnames, nnames, stats_handle,
|
||||
NULL, NULL, options, NULL, NULL, origin);
|
||||
NULL, NULL, options, NULL, NULL, origin, url);
|
||||
}
|
||||
|
||||
|
||||
@ -516,7 +518,7 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp,
|
||||
unsigned char **fpr, size_t *fpr_len,
|
||||
unsigned int options,
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin)
|
||||
int origin, const char *url)
|
||||
{
|
||||
int rc;
|
||||
iobuf_t inp;
|
||||
@ -531,7 +533,7 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp,
|
||||
|
||||
rc = import_keys_internal (ctrl, inp, NULL, 0, stats_handle,
|
||||
fpr, fpr_len, options,
|
||||
screener, screener_arg, origin);
|
||||
screener, screener_arg, origin, url);
|
||||
|
||||
iobuf_close (inp);
|
||||
return rc;
|
||||
@ -541,7 +543,8 @@ import_keys_es_stream (ctrl_t ctrl, estream_t fp,
|
||||
static int
|
||||
import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
|
||||
unsigned char **fpr,size_t *fpr_len, unsigned int options,
|
||||
import_screener_t screener, void *screener_arg, int origin)
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin, const char *url)
|
||||
{
|
||||
PACKET *pending_pkt = NULL;
|
||||
kbnode_t keyblock = NULL; /* Need to initialize because gcc can't
|
||||
@ -569,7 +572,7 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
|
||||
if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
|
||||
rc = import_one (ctrl, keyblock,
|
||||
stats, fpr, fpr_len, options, 0, 0,
|
||||
screener, screener_arg, origin);
|
||||
screener, screener_arg, origin, url);
|
||||
else if (keyblock->pkt->pkttype == PKT_SECRET_KEY)
|
||||
rc = import_secret_one (ctrl, keyblock, stats,
|
||||
opt.batch, options, 0,
|
||||
@ -1379,11 +1382,53 @@ apply_drop_sig_filter (ctrl_t ctrl, kbnode_t keyblock, recsel_expr_t selector)
|
||||
|
||||
|
||||
/* Apply meta data to KEYBLOCK. This sets the origin of the key to
|
||||
* ORIGIN. If MERGE is true KEYBLOCK has been updated and the meta
|
||||
* data is merged and not simply inserted. */
|
||||
* ORIGIN and the updateurl to URL. Note that this function is only
|
||||
* used for a new key, that is not when we are merging keys. */
|
||||
static gpg_error_t
|
||||
apply_meta_data (kbnode_t keyblock, int merge, int origin)
|
||||
apply_meta_data (kbnode_t keyblock, int origin, const char *url)
|
||||
{
|
||||
kbnode_t node;
|
||||
u32 curtime = make_timestamp ();
|
||||
|
||||
for (node = keyblock; node; node = node->next)
|
||||
{
|
||||
if (is_deleted_kbnode (node))
|
||||
;
|
||||
else if (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
&& (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. */
|
||||
PKT_public_key *pk = node->pkt->pkt.public_key;
|
||||
|
||||
pk->keyorg = origin;
|
||||
pk->keyupdate = curtime;
|
||||
}
|
||||
else if (node->pkt->pkttype == PKT_USER_ID
|
||||
&& (origin == KEYORG_WKD || origin == KEYORG_DANE))
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
uid->updateurl = xtrystrdup (url);
|
||||
if (!uid->updateurl)
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1395,7 +1440,7 @@ apply_meta_data (kbnode_t keyblock, int merge, int origin)
|
||||
* the internal errorcount, so that invalid input can be detected by
|
||||
* programs which called gpg. If SILENT is no messages are printed -
|
||||
* even most error messages are suppressed. ORIGIN is the origin of
|
||||
* the key (0 for unknown).
|
||||
* the key (0 for unknown) and URL the corresponding URL.
|
||||
*/
|
||||
static int
|
||||
import_one (ctrl_t ctrl,
|
||||
@ -1403,7 +1448,7 @@ import_one (ctrl_t ctrl,
|
||||
unsigned char **fpr, size_t *fpr_len, unsigned int options,
|
||||
int from_sk, int silent,
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin)
|
||||
int origin, const char *url)
|
||||
{
|
||||
PKT_public_key *pk;
|
||||
PKT_public_key *pk_orig = NULL;
|
||||
@ -1627,7 +1672,7 @@ import_one (ctrl_t ctrl,
|
||||
* and thus the address of KEYBLOCK won't change. */
|
||||
if ( !(options & IMPORT_RESTORE) )
|
||||
{
|
||||
rc = apply_meta_data (keyblock, 0, origin);
|
||||
rc = apply_meta_data (keyblock, origin, url);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("apply_meta_data failed: %s\n", gpg_strerror (rc));
|
||||
@ -2313,7 +2358,7 @@ import_secret_one (ctrl_t ctrl, kbnode_t keyblock,
|
||||
the secret keys. FIXME? */
|
||||
import_one (ctrl, pub_keyblock, stats,
|
||||
NULL, NULL, options, 1, for_migration,
|
||||
screener, screener_arg, 0);
|
||||
screener, screener_arg, 0, NULL);
|
||||
|
||||
/* Fixme: We should check for an invalid keyblock and
|
||||
cancel the secret key import in this case. */
|
||||
|
@ -1012,9 +1012,9 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
|
||||
key_origin_string (uid->keyorg),
|
||||
mk_datestr (updatestr, sizeof updatestr,
|
||||
uid->keyupdate),
|
||||
pk->updateurl? "url=":"");
|
||||
if (pk->updateurl)
|
||||
print_utf8_string (es_stdout, pk->updateurl);
|
||||
uid->updateurl? "url=":"");
|
||||
if (uid->updateurl)
|
||||
print_utf8_string (es_stdout, uid->updateurl);
|
||||
es_putc ('\n', es_stdout);
|
||||
}
|
||||
|
||||
|
@ -1747,7 +1747,7 @@ 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? */);
|
||||
0 /* FIXME? */, NULL);
|
||||
}
|
||||
es_fclose (datastream);
|
||||
xfree (source);
|
||||
@ -1878,7 +1878,7 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist, int origin)
|
||||
stats_handle = import_new_stats_handle();
|
||||
import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
|
||||
opt.keyserver_options.import_options,
|
||||
NULL, NULL, origin);
|
||||
NULL, NULL, origin, NULL);
|
||||
|
||||
import_print_stats (stats_handle);
|
||||
import_release_stats_handle (stats_handle);
|
||||
@ -1945,7 +1945,7 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
|
||||
if (!err)
|
||||
err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
|
||||
IMPORT_NO_SECKEY,
|
||||
NULL, NULL, KEYORG_DANE);
|
||||
NULL, NULL, KEYORG_DANE, NULL);
|
||||
restore_import_filter (save_filt);
|
||||
}
|
||||
}
|
||||
@ -1954,7 +1954,7 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
|
||||
err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
|
||||
(opt.keyserver_options.import_options
|
||||
| IMPORT_NO_SECKEY),
|
||||
NULL, NULL, 0);
|
||||
NULL, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
opt.no_armor=armor_status;
|
||||
@ -2043,6 +2043,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
gpg_error_t err;
|
||||
char *mbox;
|
||||
estream_t key;
|
||||
char *url = NULL;
|
||||
|
||||
/* We want to work on the mbox. That is what dirmngr will do anyway
|
||||
* and we need the mbox for the import filter anyway. */
|
||||
@ -2055,7 +2056,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpg_dirmngr_wkd_get (ctrl, mbox, quick, &key);
|
||||
err = gpg_dirmngr_wkd_get (ctrl, mbox, quick, &key, &url);
|
||||
if (err)
|
||||
;
|
||||
else if (key)
|
||||
@ -2078,7 +2079,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
if (!err)
|
||||
err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
|
||||
IMPORT_NO_SECKEY,
|
||||
NULL, NULL, KEYORG_WKD);
|
||||
NULL, NULL, KEYORG_WKD, url);
|
||||
|
||||
}
|
||||
|
||||
@ -2089,6 +2090,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
xfree (url);
|
||||
xfree (mbox);
|
||||
return err;
|
||||
}
|
||||
|
@ -352,13 +352,14 @@ void restore_import_filter (import_filter_t filt);
|
||||
gpg_error_t read_key_from_file (ctrl_t ctrl, const char *fname,
|
||||
kbnode_t *r_keyblock);
|
||||
void import_keys (ctrl_t ctrl, char **fnames, int nnames,
|
||||
import_stats_t stats_hd, unsigned int options, int origin);
|
||||
import_stats_t stats_hd, unsigned int options,
|
||||
int origin, const char *url);
|
||||
int import_keys_es_stream (ctrl_t ctrl, estream_t fp,
|
||||
import_stats_t stats_handle,
|
||||
unsigned char **fpr, size_t *fpr_len,
|
||||
unsigned int options,
|
||||
import_screener_t screener, void *screener_arg,
|
||||
int origin);
|
||||
int origin, const char *url);
|
||||
gpg_error_t import_old_secring (ctrl_t ctrl, const char *fname);
|
||||
import_stats_t import_new_stats_handle (void);
|
||||
void import_release_stats_handle (import_stats_t hd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user