Skip to content

Commit

Permalink
Initial TOR v2/v3 support.
Browse files Browse the repository at this point in the history
This is a rebased and combined patch for Tor support.  It is extensively
reworked in the following patches, but the basis remains Saibato's work,
so it seemed fairest to begin with this.

Minor changes:
1. Use --announce-addr instead of --tor-external.
2. I also reverted some whitespace and unrelated changes from the patch.
3. Removed unnecessary ';' after } in functions.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
Saibato authored and rustyrussell committed May 10, 2018
1 parent 855d0b9 commit 877f63e
Show file tree
Hide file tree
Showing 24 changed files with 921 additions and 9 deletions.
1 change: 1 addition & 0 deletions channeld/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ALL_GEN_HEADERS += $(LIGHTNINGD_CHANNEL_HEADERS_GEN)

# Common source we use.
CHANNELD_COMMON_OBJS := \
common/base32.o \
common/bip32.o \
common/channel_config.o \
common/crypto_state.o \
Expand Down
1 change: 1 addition & 0 deletions closingd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ $(LIGHTNINGD_CLOSING_OBJS): $(LIGHTNINGD_HEADERS)

# Common source we use.
CLOSINGD_COMMON_OBJS := \
common/base32.o \
common/close_tx.o \
common/crypto_state.o \
common/crypto_sync.o \
Expand Down
2 changes: 2 additions & 0 deletions common/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
COMMON_SRC_NOGEN := \
common/base32.c \
common/bech32.c \
common/bech32_util.c \
common/bip32.c \
Expand Down Expand Up @@ -41,6 +42,7 @@ COMMON_SRC_NOGEN := \
common/timeout.c \
common/type_to_string.c \
common/utils.c \
common/tor.c \
common/utxo.c \
common/version.c \
common/wallet_tx.c \
Expand Down
63 changes: 63 additions & 0 deletions common/base32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <common/base32.h>
#include <sys/types.h>

/* This is a rework of what i found on the Net about base32
*
* so Orum (shallot) and Markus Gutschke (Google.inc) should be mentioned here
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#define BASE32DATA "abcdefghijklmnopqrstuvwxyz234567"

char *b32_encode(char *dst, u8 * src, u8 ver)
{
u16 byte = 0, poff = 0;
for (; byte < ((ver == 2) ? 16 : 56); poff += 5) {
if (poff > 7) {
poff -= 8;
src++;
}
dst[byte++] =
BASE32DATA[(htobe16(*(u16 *) src) >> (11 - poff)) & (u16)
0x001F];
}
dst[byte] = 0;
return dst;
}

//FIXME quiknditry

void b32_decode(u8 * dst, u8 * src, u8 ver)
{
int rem = 0;
int i;
u8 *p = src;
int buf;
u8 ch;
for (i = 0; i < ((ver == 2) ? 16 : 56); p++) {
ch = *p;
buf <<= 5;
if ((ch >= 'a' && ch <= 'z')) {
ch = (ch & 0x1F) - 1;
} else if (ch != '.') {
ch -= '2' - 0x1A;
} else return;
buf = buf | ch;
rem = rem + 5;
if (rem >= 8) {
dst[i++] = buf >> (rem - 8);
rem -= 8;
}
}
}
10 changes: 10 additions & 0 deletions common/base32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef LIGHTNING_COMMON_BASE32_H
#define LIGHTNING_COMMON_BASE32_H
#include "config.h"
#include <ccan/short_types/short_types.h>


char *b32_encode(char *dst, u8 * src, u8 ver);
void b32_decode(u8 * dst, u8 * src, u8 ver);

#endif /* LIGHTNING_COMMON_BASE32_H */
13 changes: 13 additions & 0 deletions common/test/run-ip_port_parsing.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "../common/base32.c"
#include "../common/wireaddr.c"

#include <stdio.h>
Expand Down Expand Up @@ -102,6 +103,18 @@ int main(void)

assert(parse_wireaddr("[::ffff:127.0.0.1]:49150", &addr, 1, NULL));
assert(addr.port == 49150);

assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion:49150", &addr, 1, NULL));
assert(addr.port == 49150);

assert(parse_wireaddr("4ruvswpqec5i2gogopxl4vm5bruzknbvbylov2awbo4rxiq4cimdldad.onion", &addr, 1, NULL));
assert(addr.port == 1);

assert(parse_wireaddr("odpzvneidqdf5hdq.onion:49150", &addr, 1, NULL));
assert(addr.port == 49150);

assert(parse_wireaddr("odpzvneidqdf5hdq.onion.onion", &addr, 1, NULL));
assert(addr.port == 1);
tal_free(tmpctx);
return 0;
}
254 changes: 254 additions & 0 deletions common/tor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#include <arpa/inet.h>
#include <assert.h>
#include <ccan/err/err.h>
#include <ccan/io/io.h>
#include <ccan/str/hex/hex.h>
#include <ccan/tal/str/str.h>
#include <common/tor.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <common/wireaddr.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <wire/wire.h>

#define MAX_TOR_COOKIE_LEN 32
#define MAX_TOR_SERVICE_READBUFFER_LEN 255
#define MAX_TOR_ONION_V2_ADDR_LEN 16
#define MAX_TOR_ONION_V3_ADDR_LEN 56

static bool return_from_service_call;

struct tor_service_reaching {
struct lightningd *ld;
u8 buffer[MAX_TOR_SERVICE_READBUFFER_LEN];
char *cookie[MAX_TOR_COOKIE_LEN];
u8 *p;
bool noauth;
size_t hlen;
};

static struct io_plan *io_tor_connect_close(struct io_conn *conn)
{
err(1, "Cannot create TOR service address");
return_from_service_call = true;
return io_close(conn);
}

static struct io_plan *io_tor_connect_create_onion_finished(struct io_conn
*conn, struct
tor_service_reaching
*reach)
{
char *temp_char;

if (reach->hlen == MAX_TOR_ONION_V2_ADDR_LEN) {
size_t n = tal_count(reach->ld->proposed_wireaddr);
tal_resize(&reach->ld->proposed_wireaddr, n + 1);
tal_resize(&reach->ld->proposed_listen_announce, n+1);
reach->ld->proposed_listen_announce[n] = ADDR_ANNOUNCE;
temp_char = tal_fmt(tmpctx, "%.56s.onion", reach->buffer);
parse_wireaddr_internal(temp_char,
&reach->ld->proposed_wireaddr[n],
reach->ld->portnum, false, NULL);
return_from_service_call = true;
return io_close(conn);
}
/*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
//stays valid until reboot this might not be desired so we can also drop Detach and use the
//read_partial to keep it open until LN drops
//FIXME: SAIBATO we might not want to close this conn
//return io_read_partial(conn, reach->p, 1 ,&reach->hlen, io_tor_connect_create_onion_finished, reach);
return io_tor_connect_close(conn);
}

static struct io_plan *io_tor_connect_after_create_onion(struct io_conn *conn, struct
tor_service_reaching
*reach)
{
reach->p = reach->p + reach->hlen;

if (!strstr((char *)reach->buffer, "ServiceID=")) {
if (reach->hlen == 0)
return io_tor_connect_close(conn);

return io_read_partial(conn, reach->p, 1, &reach->hlen,
io_tor_connect_after_create_onion,
reach);
} else {
memset(reach->buffer, 0, sizeof(reach->buffer));
return io_read_partial(conn, reach->buffer,
MAX_TOR_ONION_V2_ADDR_LEN, &reach->hlen,
io_tor_connect_create_onion_finished,
reach);
}
}

//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");

static struct io_plan *io_tor_connect_make_onion(struct io_conn *conn, struct tor_service_reaching
*reach)
{
if (strstr((char *)reach->buffer, "250 OK") == NULL)
return io_tor_connect_close(conn);

sprintf((char *)reach->buffer,
"ADD_ONION NEW:RSA1024 Port=%d,127.0.0.1:%d Flags=DiscardPK,Detach\r\n",
reach->ld->portnum, reach->ld->portnum);

reach->hlen = strlen((char *)reach->buffer);
reach->p = reach->buffer;
return io_write(conn, reach->buffer, reach->hlen,
io_tor_connect_after_create_onion, reach);
}

static struct io_plan *io_tor_connect_after_authenticate(struct io_conn *conn, struct
tor_service_reaching
*reach)
{
return io_read(conn, reach->buffer, 7, io_tor_connect_make_onion,
reach);
}

static struct io_plan *io_tor_connect_authenticate(struct io_conn *conn, struct
tor_service_reaching
*reach)
{
sprintf((char *)reach->buffer, "AUTHENTICATE %s\r\n",
(char *)reach->cookie);

if (reach->noauth)
sprintf((char *)reach->buffer, "AUTHENTICATE\r\n");

reach->hlen = strlen((char *)reach->buffer);

return io_write(conn, reach->buffer, reach->hlen,
io_tor_connect_after_authenticate, reach);

}

static struct io_plan *io_tor_connect_after_answer_pi(struct io_conn *conn, struct
tor_service_reaching
*reach)
{
char *p = tal(reach, char);
char *p2 = tal(reach, char);

u8 *buf = tal_arrz(reach, u8, MAX_TOR_COOKIE_LEN);

reach->noauth = false;

if (strstr((char *)reach->buffer, "NULL"))
reach->noauth = true;
else if (strstr((char *)reach->buffer, "HASHEDPASSWORD")
&& (strlen(reach->ld->tor_service_password))) {
reach->noauth = false;
sprintf((char *)reach->cookie, "\"%s\"",
reach->ld->tor_service_password);
} else if ((p = strstr((char *)reach->buffer, "COOKIEFILE="))) {
assert(strlen(p) > 12);
p2 = strstr((char *)(p + 12), "\"");
assert(p2 != NULL);
*(char *)(p + (strlen(p) - strlen(p2))) = 0;

int fd = open((char *)(p + 12), O_RDONLY);
if (fd < 0)
return io_tor_connect_close(conn);
if (!read(fd, buf, MAX_TOR_COOKIE_LEN)) {
close(fd);
return io_tor_connect_close(conn);
} else
close(fd);

hex_encode(buf, 32, (char *)reach->cookie, 80);
reach->noauth = false;
} else
return io_tor_connect_close(conn);

return io_tor_connect_authenticate(conn, reach);

}

static struct io_plan *io_tor_connect_after_protocolinfo(struct io_conn *conn, struct
tor_service_reaching
*reach)
{

memset(reach->buffer, 0, MAX_TOR_SERVICE_READBUFFER_LEN);
return io_read_partial(conn, reach->buffer,
MAX_TOR_SERVICE_READBUFFER_LEN - 1, &reach->hlen,
&io_tor_connect_after_answer_pi, reach);
}

static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn
*conn, struct
tor_service_reaching
*reach)
{

sprintf((char *)reach->buffer, "PROTOCOLINFO 1\r\n");
reach->hlen = strlen((char *)reach->buffer);

return io_write(conn, reach->buffer, reach->hlen,
io_tor_connect_after_protocolinfo, reach);
}

static struct io_plan *tor_connect_finish(struct io_conn *conn,
struct tor_service_reaching *reach)
{
return io_tor_connect_after_resp_to_connect(conn, reach);
}

static struct io_plan *tor_conn_init(struct io_conn *conn,
struct lightningd *ld)
{
struct addrinfo *ai_tor = tal(ld, struct addrinfo);
struct tor_service_reaching *reach =
tal(ld, struct tor_service_reaching);

reach->ld = ld;

getaddrinfo(fmt_wireaddr_without_port(ld, ld->tor_serviceaddrs),
tal_fmt(ld, "%d", ld->tor_serviceaddrs->port), NULL,
&ai_tor);

return io_connect(conn, ai_tor, &tor_connect_finish, reach);
}

bool create_tor_hidden_service_conn(struct lightningd * ld)
{
int fd;
struct io_conn *conn;

return_from_service_call = false;

fd = socket(AF_INET, SOCK_STREAM, 0);
conn = io_new_conn(NULL, fd, &tor_conn_init, ld);
if (!conn) {
return_from_service_call = true;
err(1, "Cannot create new TOR connection");
}
return true;
}

bool do_we_use_tor_addr(const struct wireaddr * wireaddr)
{
for (int i = 0; i < tal_count(wireaddr); i++) {
if ((wireaddr[i].type == ADDR_TYPE_TOR_V2)
|| (wireaddr[i].type == ADDR_TYPE_TOR_V3))
return true;
}
return false;
}

bool check_return_from_service_call(void)
{
return return_from_service_call;
}
14 changes: 14 additions & 0 deletions common/tor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef LIGHTNING_COMMON_TOR_H
#define LIGHTNING_COMMON_TOR_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <lightningd/lightningd.h>
#include <stdbool.h>
#include <stdlib.h>

bool check_return_from_service_call(void);
bool parse_tor_wireaddr(const char *arg,u8 *ip_ld,u16 *port_ld);
bool create_tor_hidden_service_conn(struct lightningd *);
bool do_we_use_tor_addr(const struct wireaddr *wireaddrs);
#endif /* LIGHTNING_COMMON_TOR_H */
Loading

0 comments on commit 877f63e

Please sign in to comment.