mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
dirmngr: Switch to an onion address if Tor is running.
* dirmngr/dirmngr.h (opt): Turn field 'keyserver' into an strlist. * dirmngr/dirmngr.c (parse_rereadable_options): Allow multiple --keyserver options. * dirmngr/server.c (server_local_s): Add field 'tor_state'. (release_uri_item_list): New. (release_ctrl_keyservers): Use it. (start_command_handler): Release list of keyservers. (is_tor_running): New. (cmd_getinfo): Re-implement "tor" subcommand using new fucntion. (ensure_keyserver): Rewrite. * g10/dirmngr-conf.skel: Add two keyserver options. -- This feature is independent of --use-tor and automagically uses Tor if available. The dirmngr.conf file needs to specify two keyservers to make this work. For new installations this is done using the skeleton file. This feature requires the Libassuan 2.4.2 to work. This patch also fixes a memory leak of opt.keyserver en passant. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
17ac843871
commit
28e2513721
@ -541,8 +541,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
|
|||||||
}
|
}
|
||||||
FREE_STRLIST (opt.ignored_cert_extensions);
|
FREE_STRLIST (opt.ignored_cert_extensions);
|
||||||
http_register_tls_ca (NULL);
|
http_register_tls_ca (NULL);
|
||||||
xfree (opt.keyserver);
|
FREE_STRLIST (opt.keyserver);
|
||||||
opt.keyserver = NULL;
|
|
||||||
/* Note: We do not allow resetting of opt.use_tor at runtime. */
|
/* Note: We do not allow resetting of opt.use_tor at runtime. */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -622,8 +621,8 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
|
|||||||
case oUseTor: opt.use_tor = 1; break;
|
case oUseTor: opt.use_tor = 1; break;
|
||||||
|
|
||||||
case oKeyServer:
|
case oKeyServer:
|
||||||
xfree (opt.keyserver);
|
if (*pargs->r.ret_str)
|
||||||
opt.keyserver = *pargs->r.ret_str? xtrystrdup (pargs->r.ret_str) : NULL;
|
add_to_strlist (&opt.keyserver, pargs->r.ret_str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oNameServer:
|
case oNameServer:
|
||||||
|
@ -131,7 +131,7 @@ struct
|
|||||||
unsigned int ocsp_current_period; /* Seconds a response is considered
|
unsigned int ocsp_current_period; /* Seconds a response is considered
|
||||||
current after nextUpdate. */
|
current after nextUpdate. */
|
||||||
|
|
||||||
char *keyserver; /* Malloced string with the default keyserver. */
|
strlist_t keyserver; /* List of default keyservers. */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
|
|
||||||
|
144
dirmngr/server.c
144
dirmngr/server.c
@ -91,6 +91,9 @@ struct server_local_s
|
|||||||
/* If this flag is set to true this dirmngr process will be
|
/* If this flag is set to true this dirmngr process will be
|
||||||
terminated after the end of this session. */
|
terminated after the end of this session. */
|
||||||
int stopme;
|
int stopme;
|
||||||
|
|
||||||
|
/* State variable private to is_tor_running. */
|
||||||
|
int tor_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -120,6 +123,18 @@ get_ldapservers_from_ctrl (ctrl_t ctrl)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release an uri_item_t list. */
|
||||||
|
static void
|
||||||
|
release_uri_item_list (uri_item_t list)
|
||||||
|
{
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
uri_item_t tmp = list->next;
|
||||||
|
http_release_parsed_uri (list->parsed_uri);
|
||||||
|
xfree (list);
|
||||||
|
list = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Release all configured keyserver info from CTRL. */
|
/* Release all configured keyserver info from CTRL. */
|
||||||
void
|
void
|
||||||
@ -128,13 +143,8 @@ release_ctrl_keyservers (ctrl_t ctrl)
|
|||||||
if (! ctrl->server_local)
|
if (! ctrl->server_local)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (ctrl->server_local->keyservers)
|
release_uri_item_list (ctrl->server_local->keyservers);
|
||||||
{
|
ctrl->server_local->keyservers = NULL;
|
||||||
uri_item_t tmp = ctrl->server_local->keyservers->next;
|
|
||||||
http_release_parsed_uri (ctrl->server_local->keyservers->parsed_uri);
|
|
||||||
xfree (ctrl->server_local->keyservers);
|
|
||||||
ctrl->server_local->keyservers = tmp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -335,6 +345,38 @@ skip_options (char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This fucntion returns true if a Tor server is running. The sattus
|
||||||
|
is cached for the current conenction. */
|
||||||
|
static int
|
||||||
|
is_tor_running (ctrl_t ctrl)
|
||||||
|
{
|
||||||
|
#if ASSUAN_VERSION_NUMBER >= 0x020402
|
||||||
|
/* Check whether we can connect to the proxy. We use a
|
||||||
|
special feature introduced with libassuan 2.4.2. */
|
||||||
|
|
||||||
|
if (!ctrl || !ctrl->server_local)
|
||||||
|
return 0; /* Ooops. */
|
||||||
|
|
||||||
|
if (!ctrl->server_local->tor_state)
|
||||||
|
{
|
||||||
|
assuan_fd_t sock;
|
||||||
|
|
||||||
|
sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
|
||||||
|
if (sock == ASSUAN_INVALID_FD)
|
||||||
|
ctrl->server_local->tor_state = -1; /* Not running. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assuan_sock_close (sock);
|
||||||
|
ctrl->server_local->tor_state = 1; /* Running. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ctrl->server_local->tor_state > 0);
|
||||||
|
#else /* Libassuan < 2.4.2 */
|
||||||
|
return 0; /* We don't know. */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return an error if the assuan context does not belong to the owner
|
/* Return an error if the assuan context does not belong to the owner
|
||||||
of the process or to root. On error FAILTEXT is set as Assuan
|
of the process or to root. On error FAILTEXT is set as Assuan
|
||||||
error string. */
|
error string. */
|
||||||
@ -1710,15 +1752,74 @@ ensure_keyserver (ctrl_t ctrl)
|
|||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
uri_item_t item;
|
uri_item_t item;
|
||||||
|
uri_item_t onion_items = NULL;
|
||||||
|
uri_item_t plain_items = NULL;
|
||||||
|
uri_item_t ui;
|
||||||
|
strlist_t sl;
|
||||||
|
|
||||||
if (ctrl->server_local->keyservers)
|
if (ctrl->server_local->keyservers)
|
||||||
return 0; /* Already set for this session. */
|
return 0; /* Already set for this session. */
|
||||||
if (!opt.keyserver)
|
if (!opt.keyserver)
|
||||||
return 0; /* No global option set. */
|
return 0; /* No global option set. */
|
||||||
|
|
||||||
err = make_keyserver_item (opt.keyserver, &item);
|
for (sl = opt.keyserver; sl; sl = sl->next)
|
||||||
if (!err)
|
{
|
||||||
ctrl->server_local->keyservers = item;
|
err = make_keyserver_item (sl->d, &item);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
if (item->parsed_uri->onion)
|
||||||
|
{
|
||||||
|
item->next = onion_items;
|
||||||
|
onion_items = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item->next = plain_items;
|
||||||
|
plain_items = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decide which to use. Note that the sesssion has no keyservers
|
||||||
|
yet set. */
|
||||||
|
if (onion_items && !onion_items->next && plain_items && !plain_items->next)
|
||||||
|
{
|
||||||
|
/* If there is just one onion and one plain keyserver given, we take
|
||||||
|
only one depending on whether Tor is running or not. */
|
||||||
|
if (is_tor_running (ctrl))
|
||||||
|
{
|
||||||
|
ctrl->server_local->keyservers = onion_items;
|
||||||
|
onion_items = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctrl->server_local->keyservers = plain_items;
|
||||||
|
plain_items = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!is_tor_running (ctrl))
|
||||||
|
{
|
||||||
|
/* Tor is not running. It does not make sense to add Onion
|
||||||
|
addresses. */
|
||||||
|
ctrl->server_local->keyservers = plain_items;
|
||||||
|
plain_items = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In all other cases add all keyservers. */
|
||||||
|
ctrl->server_local->keyservers = onion_items;
|
||||||
|
onion_items = NULL;
|
||||||
|
for (ui = ctrl->server_local->keyservers; ui && ui->next; ui = ui->next)
|
||||||
|
;
|
||||||
|
if (ui)
|
||||||
|
ui->next = plain_items;
|
||||||
|
else
|
||||||
|
ctrl->server_local->keyservers = plain_items;
|
||||||
|
plain_items = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
release_uri_item_list (onion_items);
|
||||||
|
release_uri_item_list (plain_items);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2093,6 +2194,7 @@ static const char hlp_getinfo[] =
|
|||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
cmd_getinfo (assuan_context_t ctx, char *line)
|
cmd_getinfo (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
|
|
||||||
if (!strcmp (line, "version"))
|
if (!strcmp (line, "version"))
|
||||||
@ -2123,24 +2225,11 @@ cmd_getinfo (assuan_context_t ctx, char *line)
|
|||||||
{
|
{
|
||||||
if (opt.use_tor)
|
if (opt.use_tor)
|
||||||
{
|
{
|
||||||
#if ASSUAN_VERSION_NUMBER >= 0x020402
|
if (!is_tor_running (ctrl))
|
||||||
/* Check whether we can connect to the proxy. We use a
|
err = assuan_write_status (ctx, "NO_TOR", "Tor not running");
|
||||||
special feature introduced with libassuan 2.4.2. */
|
|
||||||
assuan_fd_t sock = assuan_sock_connect_byname (NULL, 0, 0, NULL,
|
|
||||||
ASSUAN_SOCK_TOR);
|
|
||||||
if (sock == ASSUAN_INVALID_FD)
|
|
||||||
{
|
|
||||||
err = assuan_write_status
|
|
||||||
(ctx, "NO_TOR",
|
|
||||||
errno == ECONNREFUSED? "Tor not running" : strerror (errno));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
err = 0;
|
||||||
assuan_sock_close (sock);
|
|
||||||
err = 0;
|
|
||||||
}
|
|
||||||
if (!err)
|
if (!err)
|
||||||
#endif /* Libassuan >= 2.4.2 */
|
|
||||||
assuan_set_okay_line (ctx, "- Tor mode is enabled");
|
assuan_set_okay_line (ctx, "- Tor mode is enabled");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2398,6 +2487,7 @@ start_command_handler (assuan_fd_t fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if USE_LDAP
|
#if USE_LDAP
|
||||||
ldap_wrapper_connection_cleanup (ctrl);
|
ldap_wrapper_connection_cleanup (ctrl);
|
||||||
|
|
||||||
@ -2405,6 +2495,8 @@ start_command_handler (assuan_fd_t fd)
|
|||||||
#endif /*USE_LDAP*/
|
#endif /*USE_LDAP*/
|
||||||
ctrl->server_local->ldapservers = NULL;
|
ctrl->server_local->ldapservers = NULL;
|
||||||
|
|
||||||
|
release_ctrl_keyservers (ctrl);
|
||||||
|
|
||||||
ctrl->server_local->assuan_ctx = NULL;
|
ctrl->server_local->assuan_ctx = NULL;
|
||||||
assuan_release (ctx);
|
assuan_release (ctx);
|
||||||
|
|
||||||
|
@ -263,6 +263,11 @@ need to send keys to more than one server. The keyserver
|
|||||||
@code{hkp://keys.gnupg.net} uses round robin DNS to give a different
|
@code{hkp://keys.gnupg.net} uses round robin DNS to give a different
|
||||||
keyserver each time you use it.
|
keyserver each time you use it.
|
||||||
|
|
||||||
|
If exactly two keyservers are configured and only one is a Tor hidden
|
||||||
|
service (.onion), Dirmngr selects the keyserver to use depending on
|
||||||
|
whether Tor is locally running or not. The check for a running Tor is
|
||||||
|
done for each new connection.
|
||||||
|
|
||||||
|
|
||||||
@item --nameserver @var{ipaddr}
|
@item --nameserver @var{ipaddr}
|
||||||
@opindex nameserver
|
@opindex nameserver
|
||||||
|
@ -49,7 +49,12 @@
|
|||||||
# servers via DNS round-robin. hkp://keys.gnupg.net is an example of
|
# servers via DNS round-robin. hkp://keys.gnupg.net is an example of
|
||||||
# such a "server", which spreads the load over a number of physical
|
# such a "server", which spreads the load over a number of physical
|
||||||
# servers.
|
# servers.
|
||||||
|
#
|
||||||
|
# If exactly two keyservers are configured and only one is a Tor hidden
|
||||||
|
# service, Dirmngr selects the keyserver to use depending on whether
|
||||||
|
# Tor is locally running or not (on a per session base).
|
||||||
|
|
||||||
|
keyserver hkp://dyh2j3qyrirn43iw.onion
|
||||||
keyserver hkp://keys.gnupg.net
|
keyserver hkp://keys.gnupg.net
|
||||||
|
|
||||||
# --hkp-cacert FILENAME
|
# --hkp-cacert FILENAME
|
||||||
|
Loading…
x
Reference in New Issue
Block a user