diff --git a/dirmngr/dns-stuff.c b/dirmngr/dns-stuff.c index c80ee1dfa..21e5610a3 100644 --- a/dirmngr/dns-stuff.c +++ b/dirmngr/dns-stuff.c @@ -403,6 +403,20 @@ is_ip_address (const char *name) } +/* Return true if NAME is an onion address. */ +int +is_onion_address (const char *name) +{ + size_t len; + + len = name? strlen (name) : 0; + if (len < 8 || strcmp (name + len - 6, ".onion")) + return 0; + /* Note that we require at least 2 characters before the suffix. */ + return 1; /* Yes. */ +} + + #ifdef USE_ADNS /* Init ADNS and store the new state at R_STATE. Returns 0 on success; prints an error message and returns an error code on diff --git a/dirmngr/dns-stuff.h b/dirmngr/dns-stuff.h index c3effad83..515a859b1 100644 --- a/dirmngr/dns-stuff.h +++ b/dirmngr/dns-stuff.h @@ -110,6 +110,9 @@ gpg_error_t resolve_dns_addr (const struct sockaddr *addr, int addrlen, /* Return true if NAME is a numerical IP address. */ int is_ip_address (const char *name); +/* Return true if NAME is an onion address. */ +int is_onion_address (const char *name); + /* Get the canonical name for NAME. */ gpg_error_t get_dns_cname (const char *name, char **r_cname); diff --git a/dirmngr/http.c b/dirmngr/http.c index 1a7c1ff17..9e2ba90f8 100644 --- a/dirmngr/http.c +++ b/dirmngr/http.c @@ -2212,6 +2212,32 @@ connect_server (const char *server, unsigned short port, init_sockets (); #endif /*Windows*/ + /* Onion addresses require special treatment. */ + if (is_onion_address (server)) + { +#ifdef ASSUAN_SOCK_TOR + + my_unprotect (); + sock = assuan_sock_connect_byname (server, port, 0, NULL, + ASSUAN_SOCK_TOR); + my_protect (); + + if (sock == ASSUAN_INVALID_FD) + { + if (errno == EHOSTUNREACH) + *r_host_not_found = 1; + log_error ("can't connect to '%s': %s\n", server, strerror (errno)); + } + return sock; + +#else /*!ASSUAN_SOCK_TOR*/ + + gpg_err_set_errno (ENETUNREACH); + return -1; /* Out of core. */ + +#endif /*!HASSUAN_SOCK_TOR*/ + } + #ifdef USE_DNS_SRV /* Do the SRV thing */ if (srvtag) diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 340b012ad..a6587271c 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -80,6 +80,7 @@ struct hostinfo_s int poolidx; /* Index into POOL with the used host. -1 if not set. */ unsigned int v4:1; /* Host supports AF_INET. */ unsigned int v6:1; /* Host supports AF_INET6. */ + unsigned int onion:1;/* NAME is an onion (Tor HS) address. */ unsigned int dead:1; /* Host is currently unresponsive. */ time_t died_at; /* The time the host was marked dead. If this is 0 the host has been manually marked dead. */ @@ -124,6 +125,7 @@ create_new_hostinfo (const char *name) hi->lastfail = (time_t)(-1); hi->v4 = 0; hi->v6 = 0; + hi->onion = 0; hi->dead = 0; hi->died_at = 0; hi->cname = NULL; @@ -267,7 +269,15 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, /* See whether the host is in our table. */ idx = find_hostinfo (name); - if (idx == -1) + if (idx == -1 && is_onion_address (name)) + { + idx = create_new_hostinfo (name); + if (idx == -1) + return gpg_error_from_syserror (); + hi = hosttable[idx]; + hi->onion = 1; + } + else if (idx == -1) { /* We never saw this host. Allocate a new entry. */ dns_addrinfo_t aibuf, ai; @@ -512,6 +522,11 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, *r_httpflags |= HTTP_FLAG_IGNORE_IPv4; if (!hi->v6) *r_httpflags |= HTTP_FLAG_IGNORE_IPv6; + + /* Note that we do not set the HTTP_FLAG_FORCE_TOR for onion + addresses because the http module detects this itself. This + also allows us to use an onion address without Tor mode being + enabled. */ } *r_host = xtrystrdup (hi->name); @@ -683,7 +698,9 @@ ks_hkp_print_hosttable (ctrl_t ctrl) else diedstr = died = NULL; err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n", - idx, hi->v6? "6":" ", hi->v4? "4":" ", + idx, + hi->onion? "O" : hi->v6? "6":" ", + hi->v4? "4":" ", hi->dead? "d":" ", hi->name, hi->v6addr? " v6=":"",