mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
dirmngr: Fix HKP host selection code.
* dirmngr/server.c (cmd_keyserver): Add option --resolve and change --print-hosttable to --hosttable. * dirmngr/ks-action.c (ks_printf_help): New. (ks_action_resolve): New. * dirmngr/ks-engine-hkp.c (select_random_host): Fix selection. (ks_hkp_print_hosttable): Print to assuan stream. (map_host): Remove debug code. Add arg FORCE_SELECT. Return numeric IP addr if it can't be resolved. (make_host_part): Add arg FORCE_SELECT; change callers to pass false. (ks_hkp_resolve): New. -- The new options for the keyserver command are useful for debugging. For example: $ tools/gpg-connect-agent -S /usr/local/var/run/gnupg/S.dirmngr \ 'keyserver hkp://keys.gnupg.net' \ 'keyserver http://http-keys.gnupg.net' \ 'keyserver --resolve --hosttable' /bye yields: OK OK S # http://astrath.net:80 S # http://2001:41d0:1:e673::1:11371 S # hosttable (idx, ipv4, ipv6, dead, name): S # 0 http-keys.gnupg.net S # . --> 10 11 12 1 5 8 7 4* 2 9 6 3 S # 1 4 37.250.168.245.bredband.tre.se S # 2 4 6 keys.exosphere.de S # 3 4 6 poseidon.muc.drweb-av.de S # 4 4 astrath.net S # 5 4 79.143.214.216 S # 6 4 openpgp.andrew.kvalhe.im S # 7 4 app.aaiedu.hr S # 8 4 6 alita.karotte.org S # 9 4 6 keyserver.bau5net.com S # 10 4 194.94.127.122 S # 11 6 2001:4d88:1ffc:477::7 S # 12 6 2a00:1280:8000:2:1:8:0:1 S # 13 keys.gnupg.net S # . --> 23 28* 30 17 22 8 7 27 25 14 21 20 19 29 [...] S # 14 4 hufu.ki.iif.hu S # 15 4 pks.ms.mff.cuni.cz S # 16 4 pgpkeys.co.uk S # 17 4 80-239-156-219.customer.teliacarrier.com S # 18 4 srv01.secure-u.de S # 19 4 mallos.xs4all.nl S # 20 4 kronecker.scientia.net S # 21 4 keyserver.ut.mephi.ru S # 22 4 89-68-150-88.dynamic.chello.pl S # 23 6 2001:1608:21:6:84:200:66:125 S # 24 6 sks.es.net S # 25 6 gstueve-1-pt.tunnel.tserv13.ash1.ipv6.he.net S # 26 6 sks.mrball.net S # 27 6 gozer.rediris.es S # 28 6 2001:41d0:1:e673::1 S # 29 6 oteiza.siccegge.de S # 30 6 2403:4200:401:10::13 S # 31 6 statler.serviz.fr OK
This commit is contained in:
parent
f30d8b0188
commit
3c35b46a32
@ -1,5 +1,6 @@
|
||||
/* ks-action.c - OpenPGP keyserver actions
|
||||
* Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2011, 2014 Werner Koch
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -57,6 +58,25 @@ ks_print_help (ctrl_t ctrl, const char *text)
|
||||
}
|
||||
|
||||
|
||||
/* Called by the engine's help functions to print the actual help. */
|
||||
gpg_error_t
|
||||
ks_printf_help (ctrl_t ctrl, const char *format, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
gpg_error_t err;
|
||||
char *buf;
|
||||
|
||||
va_start (arg_ptr, format);
|
||||
buf = es_vasprintf (format, arg_ptr);
|
||||
err = buf? 0 : gpg_error_from_syserror ();
|
||||
va_end (arg_ptr);
|
||||
if (!err)
|
||||
err = dirmngr_status_help (ctrl, buf);
|
||||
es_free (buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Run the help command for the engine responsible for URI. */
|
||||
gpg_error_t
|
||||
ks_action_help (ctrl_t ctrl, const char *url)
|
||||
@ -94,6 +114,32 @@ ks_action_help (ctrl_t ctrl, const char *url)
|
||||
}
|
||||
|
||||
|
||||
/* Resolve all host names. This is useful for looking at the status
|
||||
of configured keyservers. */
|
||||
gpg_error_t
|
||||
ks_action_resolve (ctrl_t ctrl)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
int any = 0;
|
||||
uri_item_t uri;
|
||||
|
||||
for (uri = ctrl->keyservers; !err && uri; uri = uri->next)
|
||||
{
|
||||
if (uri->parsed_uri->is_http)
|
||||
{
|
||||
any = 1;
|
||||
err = ks_hkp_resolve (ctrl, uri->parsed_uri);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any)
|
||||
err = gpg_error (GPG_ERR_NO_KEYSERVER);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Search all configured keyservers for keys matching PATTERNS and
|
||||
write the result to the provided output stream. */
|
||||
gpg_error_t
|
||||
@ -193,7 +239,7 @@ ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
|
||||
}
|
||||
|
||||
|
||||
/* Retrive keys from URL and write the result to the provided output
|
||||
/* Retrieve keys from URL and write the result to the provided output
|
||||
stream OUTFP. */
|
||||
gpg_error_t
|
||||
ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#define DIRMNGR_KS_ACTION_H 1
|
||||
|
||||
gpg_error_t ks_action_help (ctrl_t ctrl, const char *url);
|
||||
gpg_error_t ks_action_resolve (ctrl_t ctrl);
|
||||
gpg_error_t ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp);
|
||||
gpg_error_t ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp);
|
||||
gpg_error_t ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* ks-engine-hkp.c - HKP keyserver engine
|
||||
* Copyright (C) 2011, 2012 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2011, 2012, 2014 Werner Koch
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -94,6 +95,7 @@ create_new_hostinfo (const char *name)
|
||||
hi->lastfail = (time_t)(-1);
|
||||
hi->v4 = 0;
|
||||
hi->v6 = 0;
|
||||
hi->dead = 0;
|
||||
|
||||
/* Add it to the hosttable. */
|
||||
for (idx=0; idx < hosttable_size; idx++)
|
||||
@ -161,8 +163,8 @@ select_random_host (int *table)
|
||||
size_t tblsize;
|
||||
int pidx, idx;
|
||||
|
||||
/* We create a new table so that we select only from currently alive
|
||||
hosts. */
|
||||
/* We create a new table so that we randomly select only from
|
||||
currently alive hosts. */
|
||||
for (idx=0, tblsize=0; (pidx = table[idx]) != -1; idx++)
|
||||
if (hosttable[pidx] && !hosttable[pidx]->dead)
|
||||
tblsize++;
|
||||
@ -179,7 +181,7 @@ select_random_host (int *table)
|
||||
if (tblsize == 1) /* Save a get_uint_nonce. */
|
||||
pidx = tbl[0];
|
||||
else
|
||||
pidx = get_uint_nonce () % tblsize;
|
||||
pidx = tbl[get_uint_nonce () % tblsize];
|
||||
|
||||
xfree (tbl);
|
||||
return pidx;
|
||||
@ -190,9 +192,10 @@ select_random_host (int *table)
|
||||
allows us to manage round robin DNS names. We use our own strategy
|
||||
to choose one of the hosts. For example we skip those hosts which
|
||||
failed for some time and we stick to one host for a time
|
||||
independent of DNS retry times. */
|
||||
independent of DNS retry times. If FORCE_RESELECT is true a new
|
||||
host is always selected. */
|
||||
static char *
|
||||
map_host (const char *name)
|
||||
map_host (const char *name, int force_reselect)
|
||||
{
|
||||
hostinfo_t hi;
|
||||
int idx;
|
||||
@ -241,12 +244,13 @@ map_host (const char *name)
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
log_printhex ("getaddrinfo returned", ai->ai_addr,ai->ai_addrlen);
|
||||
if ((ec=getnameinfo (ai->ai_addr, ai->ai_addrlen,
|
||||
tmphost, sizeof tmphost,
|
||||
NULL, 0, NI_NAMEREQD)))
|
||||
log_info ("getnameinfo failed while checking '%s': %s\n",
|
||||
name, gai_strerror (ec));
|
||||
NULL, 0, 0)))
|
||||
{
|
||||
log_info ("getnameinfo failed while checking '%s': %s\n",
|
||||
name, gai_strerror (ec));
|
||||
}
|
||||
else if (refidx+1 >= reftblsize)
|
||||
{
|
||||
log_error ("getnameinfo returned for '%s': '%s'"
|
||||
@ -266,7 +270,7 @@ map_host (const char *name)
|
||||
|
||||
for (i=0; i < refidx; i++)
|
||||
if (reftbl[i] == tmpidx)
|
||||
break;
|
||||
break;
|
||||
if (!(i < refidx) && tmpidx != idx)
|
||||
reftbl[refidx++] = tmpidx;
|
||||
}
|
||||
@ -319,8 +323,10 @@ map_host (const char *name)
|
||||
{
|
||||
/* If the currently selected host is now marked dead, force a
|
||||
re-selection . */
|
||||
if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
|
||||
&& hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
|
||||
if (force_reselect)
|
||||
hi->poolidx = -1;
|
||||
else if (hi->poolidx >= 0 && hi->poolidx < hosttable_size
|
||||
&& hosttable[hi->poolidx] && hosttable[hi->poolidx]->dead)
|
||||
hi->poolidx = -1;
|
||||
|
||||
/* Select a host if needed. */
|
||||
@ -369,33 +375,48 @@ mark_host_dead (const char *name)
|
||||
|
||||
|
||||
/* Debug function to print the entire hosttable. */
|
||||
void
|
||||
ks_hkp_print_hosttable (void)
|
||||
gpg_error_t
|
||||
ks_hkp_print_hosttable (ctrl_t ctrl)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int idx, idx2;
|
||||
hostinfo_t hi;
|
||||
membuf_t mb;
|
||||
char *p;
|
||||
|
||||
err = ks_print_help (ctrl, "hosttable (idx, ipv4, ipv6, dead, name):");
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (idx=0; idx < hosttable_size; idx++)
|
||||
if ((hi=hosttable[idx]))
|
||||
{
|
||||
log_info ("hosttable %3d %s %s %s %s\n",
|
||||
idx, hi->v4? "4":" ", hi->v6? "6":" ",
|
||||
hi->dead? "d":" ", hi->name);
|
||||
err = ks_printf_help (ctrl, "%3d %s %s %s %s\n",
|
||||
idx, hi->v4? "4":" ", hi->v6? "6":" ",
|
||||
hi->dead? "d":" ", hi->name);
|
||||
if (err)
|
||||
return err;
|
||||
if (hi->pool)
|
||||
{
|
||||
log_info (" -->");
|
||||
init_membuf (&mb, 256);
|
||||
put_membuf_printf (&mb, " . -->");
|
||||
for (idx2=0; hi->pool[idx2] != -1; idx2++)
|
||||
{
|
||||
log_printf (" %d", hi->pool[idx2]);
|
||||
if (hi->poolidx == idx2)
|
||||
log_printf ("*");
|
||||
put_membuf_printf (&mb, " %d", hi->pool[idx2]);
|
||||
if (hi->poolidx == hi->pool[idx2])
|
||||
put_membuf_printf (&mb, "*");
|
||||
}
|
||||
log_printf ("\n");
|
||||
/* for (idx2=0; hi->pool[idx2] != -1; idx2++) */
|
||||
/* log_info (" (%s)\n", */
|
||||
/* hosttable[hi->pool[idx2]]->name); */
|
||||
put_membuf( &mb, "", 1);
|
||||
p = get_membuf (&mb, NULL);
|
||||
if (!p)
|
||||
return gpg_error_from_syserror ();
|
||||
err = ks_print_help (ctrl, p);
|
||||
xfree (p);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -425,7 +446,8 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
|
||||
PORT. Returns an allocated string or NULL on failure and sets
|
||||
ERRNO. */
|
||||
static char *
|
||||
make_host_part (const char *scheme, const char *host, unsigned short port)
|
||||
make_host_part (const char *scheme, const char *host, unsigned short port,
|
||||
int force_reselect)
|
||||
{
|
||||
char portstr[10];
|
||||
char *hostname;
|
||||
@ -449,7 +471,7 @@ make_host_part (const char *scheme, const char *host, unsigned short port)
|
||||
/*fixme_do_srv_lookup ()*/
|
||||
}
|
||||
|
||||
hostname = map_host (host);
|
||||
hostname = map_host (host, force_reselect);
|
||||
if (!hostname)
|
||||
return NULL;
|
||||
|
||||
@ -459,6 +481,32 @@ make_host_part (const char *scheme, const char *host, unsigned short port)
|
||||
}
|
||||
|
||||
|
||||
/* Resolve all known keyserver names and update the hosttable. This
|
||||
is mainly useful for debugging because the resolving is anyway done
|
||||
on demand. */
|
||||
gpg_error_t
|
||||
ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char *hostport = NULL;
|
||||
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port, 1);
|
||||
if (!hostport)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
err = ks_printf_help (ctrl, "%s://%s:%hu: resolve failed: %s",
|
||||
uri->scheme, uri->host, uri->port,
|
||||
gpg_strerror (err));
|
||||
}
|
||||
else
|
||||
{
|
||||
err = ks_printf_help (ctrl, "%s", hostport);
|
||||
xfree (hostport);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Send an HTTP request. On success returns an estream object at
|
||||
R_FP. HOSTPORTSTR is only used for diagnostics. If POST_CB is not
|
||||
NULL a post request is used and that callback is called to allow
|
||||
@ -636,7 +684,6 @@ armor_data (char **r_string, const void *data, size_t datalen)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Search the keyserver identified by URI for keys matching PATTERN.
|
||||
On success R_FP has an open stream to read the data. */
|
||||
@ -694,7 +741,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
{
|
||||
char *searchkey;
|
||||
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port);
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port, 0);
|
||||
if (!hostport)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
@ -725,7 +772,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Start reading the response. */
|
||||
/* Peek at the response. */
|
||||
{
|
||||
int c = es_getc (fp);
|
||||
if (c == -1)
|
||||
@ -736,8 +783,8 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
}
|
||||
if (c == '<')
|
||||
{
|
||||
/* The document begins with a '<', assume it's a HTML
|
||||
response, which we don't support. */
|
||||
/* The document begins with a '<': Assume a HTML response,
|
||||
which we don't support. */
|
||||
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
|
||||
goto leave;
|
||||
}
|
||||
@ -800,7 +847,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
|
||||
}
|
||||
|
||||
/* Build the request string. */
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port);
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port, 0);
|
||||
if (!hostport)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
@ -892,7 +939,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
|
||||
armored = NULL;
|
||||
|
||||
/* Build the request string. */
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port);
|
||||
hostport = make_host_part (uri->scheme, uri->host, uri->port, 0);
|
||||
if (!hostport)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
|
@ -25,9 +25,12 @@
|
||||
|
||||
/*-- ks-action.c --*/
|
||||
gpg_error_t ks_print_help (ctrl_t ctrl, const char *text);
|
||||
gpg_error_t ks_printf_help (ctrl_t ctrl, const char *format,
|
||||
...) _ESTREAM_GCC_A_PRINTF(2,3);
|
||||
|
||||
/*-- ks-engine-hkp.c --*/
|
||||
void ks_hkp_print_hosttable (void);
|
||||
gpg_error_t ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri);
|
||||
gpg_error_t ks_hkp_print_hosttable (ctrl_t ctrl);
|
||||
gpg_error_t ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri);
|
||||
gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
|
||||
estream_t *r_fp);
|
||||
|
@ -1,15 +1,16 @@
|
||||
/* dirmngr.c - LDAP access
|
||||
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011 g10 Code GmbH
|
||||
/* server.c - LDAP and Keyserver access server
|
||||
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011 g10 Code GmbH
|
||||
* Copyright (C) 2014 Werner Koch
|
||||
*
|
||||
* This file is part of DirMngr.
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* DirMngr is free software; you can redistribute it and/or modify
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* DirMngr is distributed in the hope that it will be useful,
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
@ -120,6 +121,7 @@ release_ctrl_keyservers (ctrl_t ctrl)
|
||||
/* Helper to print a message while leaving a command. */
|
||||
static gpg_error_t
|
||||
leave_cmd (assuan_context_t ctx, gpg_error_t err)
|
||||
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
@ -1374,14 +1376,15 @@ static gpg_error_t
|
||||
cmd_keyserver (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
int clear_flag, add_flag, help_flag, host_flag;
|
||||
gpg_error_t err = 0;
|
||||
int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
|
||||
uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
|
||||
is always initialized. */
|
||||
|
||||
clear_flag = has_option (line, "--clear");
|
||||
help_flag = has_option (line, "--help");
|
||||
host_flag = has_option (line, "--print-hosttable");
|
||||
resolve_flag = has_option (line, "--resolve");
|
||||
host_flag = has_option (line, "--hosttable");
|
||||
line = skip_options (line);
|
||||
add_flag = !!*line;
|
||||
|
||||
@ -1391,12 +1394,21 @@ cmd_keyserver (assuan_context_t ctx, char *line)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (resolve_flag)
|
||||
{
|
||||
err = ks_action_resolve (ctrl);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (host_flag)
|
||||
{
|
||||
ks_hkp_print_hosttable ();
|
||||
err = 0;
|
||||
goto leave;
|
||||
err = ks_hkp_print_hosttable (ctrl);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
if (resolve_flag || host_flag)
|
||||
goto leave;
|
||||
|
||||
if (add_flag)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user