diff --git a/common/wireaddr.h b/common/wireaddr.h index a76215c36..7e07e9eef 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -15,6 +15,14 @@ struct sockaddr_in6; struct sockaddr_in; struct sockaddr_un; +/* BOLT #1: + * + * The default TCP port is 9735. This corresponds to hexadecimal + * `0x2607`, the Unicode code point for LIGHTNING. + */ +#define DEFAULT_PORT 9735 + + /* BOLT #7: * * The following `address descriptor` types are defined: diff --git a/gossipd/Makefile b/gossipd/Makefile index 5a83ada50..8f44fc7f2 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -19,6 +19,7 @@ LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \ gossipd/handshake.h \ gossipd/netaddress.h \ gossipd/routing.h \ + gossipd/tor_autoservice.h \ gossipd/tor.h \ gossipd/broadcast.h LIGHTNINGD_GOSSIP_SRC := $(LIGHTNINGD_GOSSIP_HEADERS:.h=.c) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index c6ae03841..23e5975b5 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -149,6 +150,11 @@ struct daemon { struct addrinfo *proxyaddr; bool use_proxy_always; + + bool tor_autoservice; + struct wireaddr *tor_serviceaddr; + char *tor_password; + }; /* Peers we're trying to reach. */ @@ -1748,7 +1754,8 @@ static struct io_plan *gossip_init(struct daemon_conn *master, &daemon->proposed_listen_announce, daemon->rgb, daemon->alias, &update_channel_interval, &daemon->reconnect, &proxyaddr, &daemon->use_proxy_always, - &dev_allow_localhost)) { + &dev_allow_localhost, &daemon->tor_autoservice, + &daemon->tor_serviceaddr, &daemon->tor_password)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); } /* Prune time is twice update time */ @@ -1784,9 +1791,17 @@ static struct io_plan *gossip_activate(struct daemon_conn *master, if (!fromwire_gossipctl_activate(msg, &listen)) master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg); - if (listen) + if (listen) { binding = setup_listeners(tmpctx, daemon); - else + if (daemon->tor_autoservice) { + struct wireaddr *tor; + tor = tor_autoservice(tmpctx, + daemon->tor_serviceaddr, + daemon->tor_password, + binding); + add_announcable(daemon, tor); + } + } else binding = NULL; /* If we only advertize Tor addresses, force everything through proxy diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 5822e8b26..7dc3c762b 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -23,6 +23,11 @@ gossipctl_init,,num_tor_proxyaddrs,u16 gossipctl_init,,tor_proxyaddr,num_tor_proxyaddrs*struct wireaddr gossipctl_init,,use_tor_proxy_always,bool gossipctl_init,,dev_allow_localhost,bool +gossipctl_init,,tor_autoservice,bool +# This is 0 or 1. +gossipctl_init,,num_tor_serviceaddrs,u16 +gossipctl_init,,tor_serviceaddr,num_tor_serviceaddrs*struct wireaddr +gossipctl_init,,tor_password,wirestring # Activate the gossip daemon, so others can connect. gossipctl_activate,3025 diff --git a/lightningd/tor.c b/gossipd/tor_autoservice.c similarity index 51% rename from lightningd/tor.c rename to gossipd/tor_autoservice.c index cc6e16af8..8afc66a61 100644 --- a/lightningd/tor.c +++ b/gossipd/tor_autoservice.c @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -32,28 +32,30 @@ static void *buf_resize(void *buf, size_t len) return buf; } -static void tor_send_cmd(struct lightningd *ld, - struct rbuf *rbuf, const char *cmd) +static void tor_send_cmd(struct rbuf *rbuf, const char *cmd) { - log_io(ld->log, LOG_IO_OUT, "torcontrol", cmd, strlen(cmd)); + status_io(LOG_IO_OUT, "torcontrol", cmd, strlen(cmd)); if (!write_all(rbuf->fd, cmd, strlen(cmd))) - err(1, "Writing '%s' to Tor socket", cmd); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Writing '%s' to Tor socket", cmd); - log_io(ld->log, LOG_IO_OUT, "torcontrol", "\r\n", 2); + status_io(LOG_IO_OUT, "torcontrol", "\r\n", 2); if (!write_all(rbuf->fd, "\r\n", 2)) - err(1, "Writing CRLF to Tor socket"); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Writing CRLF to Tor socket"); } -static char *tor_response_line(struct lightningd *ld, struct rbuf *rbuf) +static char *tor_response_line(struct rbuf *rbuf) { char *line; while ((line = rbuf_read_str(rbuf, '\n', buf_resize)) != NULL) { - log_io(ld->log, LOG_IO_IN, "torcontrol", line, strlen(line)); + status_io(LOG_IO_IN, "torcontrol", line, strlen(line)); /* Weird response */ if (!strstarts(line, "250")) - errx(1, "Tor returned '%s'", line); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor returned '%s'", line); /* Last line */ if (strstarts(line, "250 ")) @@ -64,23 +66,27 @@ static char *tor_response_line(struct lightningd *ld, struct rbuf *rbuf) return NULL; } -static void discard_remaining_response(struct lightningd *ld, struct rbuf *rbuf) +static void discard_remaining_response(struct rbuf *rbuf) { - while (tor_response_line(ld, rbuf)); + while (tor_response_line(rbuf)); } -static void make_onion(struct lightningd *ld, struct rbuf *rbuf) +static struct wireaddr *make_onion(const tal_t *ctx, + struct rbuf *rbuf, + const struct wireaddr *local) { char *line; + struct wireaddr *onion; //V3 tor after 3.3.3.aplha FIXME: TODO SAIBATO //sprintf((char *)reach->buffer,"ADD_ONION NEW:ED25519-V3 Port=9735,127.0.0.1:9735\r\n"); - tor_send_cmd(ld, rbuf, - tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,127.0.0.1:%d Flags=DiscardPK,Detach", - ld->portnum, ld->portnum)); + tor_send_cmd(rbuf, + tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,%s Flags=DiscardPK,Detach", + /* FIXME: We *could* allow user to set Tor port */ + DEFAULT_PORT, fmt_wireaddr(tmpctx, local))); - while ((line = tor_response_line(ld, rbuf)) != NULL) { - size_t n; + while ((line = tor_response_line(rbuf)) != NULL) { + const char *name; if (!strstarts(line, "ServiceID=")) continue; @@ -89,17 +95,16 @@ static void make_onion(struct lightningd *ld, struct rbuf *rbuf) if (strchr(line, '\r')) *strchr(line, '\r') = '\0'; - n = tal_count(ld->proposed_wireaddr); - tal_resize(&ld->proposed_wireaddr, n + 1); - tal_resize(&ld->proposed_listen_announce, n + 1); - parse_wireaddr_internal(tal_fmt(tmpctx, "%s.onion", line), - &ld->proposed_wireaddr[n], - ld->portnum, false, false, NULL); - ld->proposed_listen_announce[n] = ADDR_ANNOUNCE; - discard_remaining_response(ld, rbuf); - return; + name = tal_fmt(tmpctx, "%s.onion", line); + onion = tal(ctx, struct wireaddr); + if (!parse_wireaddr(name, onion, 0, false, NULL)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor gave bad onion name '%s'", name); + discard_remaining_response(rbuf); + return onion; } - errx(1, "Tor didn't give us a ServiceID"); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor didn't give us a ServiceID"); } /* https://gitweb.torproject.org/torspec.git/tree/control-spec.txt: @@ -111,32 +116,32 @@ static void make_onion(struct lightningd *ld, struct rbuf *rbuf) * ReplyText = XXXX * StatusCode = 3DIGIT */ -static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf) +static void negotiate_auth(struct rbuf *rbuf, const char *tor_password) { char *line; char *cookiefile = NULL; int cookiefileerrno; - tor_send_cmd(ld, rbuf, "PROTOCOLINFO 1"); + tor_send_cmd(rbuf, "PROTOCOLINFO 1"); - while ((line = tor_response_line(ld, rbuf)) != NULL) { + while ((line = tor_response_line(rbuf)) != NULL) { const char *p; if (!strstarts(line, "AUTH METHODS=")) continue; if (strstr(line, "NULL")) { - discard_remaining_response(ld, rbuf); - tor_send_cmd(ld, rbuf, "AUTHENTICATE"); - discard_remaining_response(ld, rbuf); + discard_remaining_response(rbuf); + tor_send_cmd(rbuf, "AUTHENTICATE"); + discard_remaining_response(rbuf); return; } else if (strstr(line, "HASHEDPASSWORD") - && strlen(ld->tor_service_password)) { - discard_remaining_response(ld, rbuf); - tor_send_cmd(ld, rbuf, + && strlen(tor_password)) { + discard_remaining_response(rbuf); + tor_send_cmd(rbuf, tal_fmt(tmpctx, "AUTHENTICATE \"%s\"", - ld->tor_service_password)); - discard_remaining_response(ld, rbuf); + tor_password)); + discard_remaining_response(rbuf); return; } else if ((p = strstr(line, "COOKIEFILE=\"")) != NULL) { char *contents, *end; @@ -144,7 +149,9 @@ static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf) p += strlen("COOKIEFILE=\""); end = strstr(p, "\""); if (!end) - errx(1, "Tor protocolinfo bad line '%s'", line); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor protocolinfo bad line '%s'", + line); *end = '\0'; /* If we can't access this, try other methods */ @@ -152,44 +159,59 @@ static void negotiate_auth(struct lightningd *ld, struct rbuf *rbuf) contents = grab_file(tmpctx, p); if (!contents) { cookiefileerrno = errno; - fprintf(stderr, "No cookies for me!\n"); continue; } - discard_remaining_response(ld, rbuf); - tor_send_cmd(ld, rbuf, + discard_remaining_response(rbuf); + tor_send_cmd(rbuf, tal_fmt(tmpctx, "AUTHENTICATE %s", tal_hexstr(tmpctx, contents, tal_len(contents)-1))); - discard_remaining_response(ld, rbuf); + discard_remaining_response(rbuf); return; } } /* Now report if we tried cookie file and it failed */ - if (cookiefile) { - errno = cookiefileerrno; - err(1, "Could not open Tor cookie file '%s'", cookiefile); - } + if (cookiefile) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Could not open Tor cookie file '%s': %s", + cookiefile, strerror(cookiefileerrno)); - errx(1, "Tor protocolinfo did not give auth"); + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Tor protocolinfo did not give auth"); } -void tor_init(struct lightningd *ld) +/* We need to have a bound address we can tell Tor to connect to */ +static const struct wireaddr * +find_local_address(const struct wireaddr_internal *bindings) +{ + for (size_t i = 0; i < tal_count(bindings); i++) { + if (bindings[i].itype != ADDR_INTERNAL_WIREADDR) + continue; + if (bindings[i].u.wireaddr.type != ADDR_TYPE_IPV4 + && bindings[i].u.wireaddr.type != ADDR_TYPE_IPV6) + continue; + return &bindings[i].u.wireaddr; + } + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "No local address found to tell Tor to connect to"); +} + +struct wireaddr *tor_autoservice(const tal_t *ctx, + const struct wireaddr *tor_serviceaddr, + const char *tor_password, + const struct wireaddr_internal *bindings) { int fd; + const struct wireaddr *laddr; + struct wireaddr *onion; struct addrinfo *ai_tor; struct rbuf rbuf; char *buffer; - if (!ld->config.tor_enable_auto_hidden_service) - return; - - /* FIXME: Need better way to convert wireaddr to addrinfo... */ - if (getaddrinfo(fmt_wireaddr_without_port(ld, ld->tor_serviceaddr), - tal_fmt(tmpctx, "%d", ld->tor_serviceaddr->port), NULL, - &ai_tor) != 0) - errx(1, "getaddrinfo failed for Tor service"); + laddr = find_local_address(bindings); + ai_tor = wireaddr_to_addrinfo(tmpctx, tor_serviceaddr); fd = socket(ai_tor->ai_family, SOCK_STREAM, 0); if (fd < 0) @@ -201,8 +223,8 @@ void tor_init(struct lightningd *ld) buffer = tal_arr(tmpctx, char, rbuf_good_size(fd)); rbuf_init(&rbuf, fd, buffer, tal_len(buffer)); - negotiate_auth(ld, &rbuf); - make_onion(ld, &rbuf); + negotiate_auth(&rbuf, tor_password); + onion = make_onion(ctx, &rbuf, laddr); /*on the other hand we can stay connected until ln finish to keep onion alive and then vanish */ //because when we run with Detach flag as we now do every start of LN creates a new addr while the old @@ -210,4 +232,6 @@ void tor_init(struct lightningd *ld) //read_partial to keep it open until LN drops //FIXME: SAIBATO we might not want to close this conn close(fd); + + return onion; } diff --git a/gossipd/tor_autoservice.h b/gossipd/tor_autoservice.h new file mode 100644 index 000000000..d792df4c6 --- /dev/null +++ b/gossipd/tor_autoservice.h @@ -0,0 +1,14 @@ +#ifndef LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H +#define LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H +#include "config.h" +#include +#include +#include +#include + +struct wireaddr *tor_autoservice(const tal_t *ctx, + const struct wireaddr *tor_serviceaddr, + const char *tor_password, + const struct wireaddr_internal *bindings); + +#endif /* LIGHTNING_GOSSIPD_TOR_AUTOSERVICE_H */ diff --git a/lightningd/Makefile b/lightningd/Makefile index 6ecd5bebc..101d906f7 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -76,7 +76,6 @@ LIGHTNINGD_SRC := \ lightningd/peer_control.c \ lightningd/peer_htlcs.c \ lightningd/subd.c \ - lightningd/tor.c \ lightningd/watch.c # Source files without corresponding headers diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 1f20d95b9..b623b919e 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -227,7 +227,10 @@ void gossip_init(struct lightningd *ld) listen_announce, ld->rgb, ld->alias, ld->config.channel_update_interval, ld->reconnect, ld->proxyaddr, ld->use_proxy_always, - allow_localhost); + allow_localhost, + ld->config.tor_enable_auto_hidden_service, + ld->tor_serviceaddr, + ld->tor_service_password ? ld->tor_service_password : ""); subd_send_msg(ld->gossip, msg); } diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 2d8cbfb36..f30b4314b 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -316,9 +315,6 @@ int main(int argc, char *argv[]) /* Ignore SIGPIPE: we look at our write return values*/ signal(SIGPIPE, SIG_IGN); - /* tor support */ - tor_init(ld); - /* Make sure we can reach other daemons, and versions match. */ test_daemons(ld); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index cc5a6408b..856fd0a04 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -12,13 +12,6 @@ #include #include -/* BOLT #1: - * - * The default TCP port is 9735. This corresponds to hexadecimal - * `0x2607`, the Unicode code point for LIGHTNING. - */ -#define DEFAULT_PORT 9735 - /* Various adjustable things. */ struct config { /* How long do we want them to lock up their funds? (blocks) */ diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index e05fcfcdd..3f5e3152c 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -104,9 +104,6 @@ void subd_shutdown(struct subd *subd UNNEEDED, unsigned int seconds UNNEEDED) /* Generated stub for timer_expired */ void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED) { fprintf(stderr, "timer_expired called!\n"); abort(); } -/* Generated stub for tor_init */ -void tor_init(struct lightningd *ld UNNEEDED) -{ fprintf(stderr, "tor_init called!\n"); abort(); } /* Generated stub for txfilter_add_derkey */ void txfilter_add_derkey(struct txfilter *filter UNNEEDED, const u8 derkey[PUBKEY_DER_LEN]) diff --git a/lightningd/tor.h b/lightningd/tor.h deleted file mode 100644 index eb735a67d..000000000 --- a/lightningd/tor.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef LIGHTNING_LIGHTNINGD_TOR_H -#define LIGHTNING_LIGHTNINGD_TOR_H -#include "config.h" -#include -#include -#include -#include -#include - -void tor_init(struct lightningd *ld); -#endif /* LIGHTNING_LIGHTNINGD_TOR_H */