forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
1 parent
855d0b9
commit 877f63e
Showing
24 changed files
with
921 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 */ |
Oops, something went wrong.