1 #include <ccan/io/io.h>
2 #include <ccan/tal/str/str.h>
3 #include <common/status.h>
4 #include <common/utils.h>
5 #include <connectd/connectd.h>
6 #include <connectd/tor.h>
7 #include <errno.h>
8 #include <inttypes.h>
9 #include <netinet/in.h>
10
11 #define SOCKS_NOAUTH 0
12 #define SOCKS_ERROR 0xff
13 #define SOCKS_CONNECT 1
14 #define SOCKS_TYP_IPV4 1
15 #define SOCKS_DOMAIN 3
16 #define SOCKS_TYP_IPV6 4
17 #define SOCKS_V5 5
18
19 #define MAX_SIZE_OF_SOCKS5_REQ_OR_RESP 255
20 #define SIZE_OF_RESPONSE 4
21 #define SIZE_OF_REQUEST 3
22 #define SIZE_OF_IPV4_RESPONSE 6
23 #define SIZE_OF_IPV6_RESPONSE 18
24 #define SOCK_REQ_METH_LEN 3
25 #define SOCK_REQ_V5_LEN 5
26 #define SOCK_REQ_V5_HEADER_LEN 7
27
28 /* some crufts can not forward ipv6 */
29 #undef BIND_FIRST_TO_IPV6
30
31 struct connecting_socks {
32 u8 buffer[MAX_SIZE_OF_SOCKS5_REQ_OR_RESP];
33 size_t hlen;
34 in_port_t port;
35 char *host;
36 struct connecting *connect;
37 };
38
socks5strerror(const tal_t * ctx,u8 code)39 static const char* socks5strerror(const tal_t *ctx, u8 code)
40 {
41 /* Error codes defined in https://tools.ietf.org/html/rfc1928#section-6 */
42 switch (code) {
43 case 0:
44 return tal_strdup(ctx, "success");
45 case 1:
46 return tal_strdup(ctx, "general SOCKS server failure");
47 case 2:
48 return tal_strdup(ctx, "connection not allowed by ruleset");
49 case 3:
50 return tal_strdup(ctx, "network unreachable");
51 case 4:
52 return tal_strdup(ctx, "host unreachable");
53 case 5:
54 return tal_strdup(ctx, "connection refused");
55 case 6:
56 return tal_strdup(ctx, "TTL expired");
57 case 7:
58 return tal_strdup(ctx, "command not supported");
59 case 8:
60 return tal_strdup(ctx, "address type not supported");
61 }
62 return tal_fmt(ctx, "unknown error: %" PRIu8, code);
63 }
64
connect_finish2(struct io_conn * conn,struct connecting_socks * connect)65 static struct io_plan *connect_finish2(struct io_conn *conn,
66 struct connecting_socks *connect)
67 {
68 status_io(LOG_IO_IN, NULL, "proxy",
69 connect->buffer + SIZE_OF_RESPONSE + SIZE_OF_IPV4_RESPONSE,
70 SIZE_OF_IPV6_RESPONSE - SIZE_OF_IPV4_RESPONSE);
71 status_debug("Now try LN connect out for host %s", connect->host);
72 return connection_out(conn, connect->connect);
73 }
74
connect_finish(struct io_conn * conn,struct connecting_socks * connect)75 static struct io_plan *connect_finish(struct io_conn *conn,
76 struct connecting_socks *connect)
77 {
78 status_io(LOG_IO_IN, NULL, "proxy",
79 connect->buffer, SIZE_OF_IPV4_RESPONSE + SIZE_OF_RESPONSE);
80
81 /* buffer[1] contains the reply status code and 0 means "success",
82 * see https://tools.ietf.org/html/rfc1928#section-6
83 */
84 if ( connect->buffer[1] == '\0') {
85 if ( connect->buffer[3] == SOCKS_TYP_IPV6) {
86 /* Read rest of response */
87 return io_read(conn,
88 connect->buffer + SIZE_OF_RESPONSE +
89 SIZE_OF_IPV4_RESPONSE,
90 SIZE_OF_IPV6_RESPONSE -
91 SIZE_OF_IPV4_RESPONSE,
92 &connect_finish2, connect);
93
94 } else if ( connect->buffer[3] == SOCKS_TYP_IPV4) {
95 status_debug("Now try LN connect out for host %s",
96 connect->host);
97 return connection_out(conn, connect->connect);
98 } else {
99 const char *msg = tal_fmt(tmpctx,
100 "Tor connect out for host %s error invalid "
101 "type return: %0x", connect->host,
102 connect->buffer[3]);
103 status_debug("%s", msg);
104 add_errors_to_error_list(connect->connect, msg);
105
106 errno = ECONNREFUSED;
107 return io_close(conn);
108 }
109 } else {
110 const char *msg = tal_fmt(tmpctx,
111 "Error connecting to %s: Tor server reply: %s",
112 connect->host,
113 socks5strerror(tmpctx, connect->buffer[1]));
114 status_debug("%s", msg);
115 add_errors_to_error_list(connect->connect, msg);
116
117 errno = ECONNREFUSED;
118 return io_close(conn);
119 }
120 }
121
122 /* called when TOR responds */
connect_out(struct io_conn * conn,struct connecting_socks * connect)123 static struct io_plan *connect_out(struct io_conn *conn,
124 struct connecting_socks *connect)
125 {
126 return io_read(conn, connect->buffer,
127 SIZE_OF_IPV4_RESPONSE + SIZE_OF_RESPONSE,
128 &connect_finish, connect);
129
130 }
131
io_tor_connect_after_resp_to_connect(struct io_conn * conn,struct connecting_socks * connect)132 static struct io_plan *io_tor_connect_after_resp_to_connect(struct io_conn
133 *conn,
134 struct
135 connecting_socks
136 *connect)
137 {
138 status_io(LOG_IO_IN, NULL, "proxy", connect->buffer, 2);
139
140 if (connect->buffer[1] == SOCKS_ERROR) {
141 /* The Tor socks5 server did not like any of our authentication
142 * methods and we provided only "no auth".
143 */
144 const char *msg = tal_fmt(tmpctx,
145 "Connected out for %s error: authentication required",
146 connect->host);
147 status_debug("%s", msg);
148 add_errors_to_error_list(connect->connect, msg);
149
150 errno = ECONNREFUSED;
151 return io_close(conn);
152 }
153 if (connect->buffer[1] == '\0') {
154 /* make the V5 request */
155 connect->hlen = strlen(connect->host);
156 connect->buffer[0] = SOCKS_V5;
157 connect->buffer[1] = SOCKS_CONNECT;
158 connect->buffer[2] = 0;
159 connect->buffer[3] = SOCKS_DOMAIN;
160 connect->buffer[4] = connect->hlen;
161
162 memcpy(connect->buffer + SOCK_REQ_V5_LEN, connect->host, connect->hlen);
163 memcpy(connect->buffer + SOCK_REQ_V5_LEN + strlen(connect->host),
164 &(connect->port), sizeof connect->port);
165
166 status_io(LOG_IO_OUT, NULL, "proxy", connect->buffer,
167 SOCK_REQ_V5_HEADER_LEN + connect->hlen);
168 return io_write(conn, connect->buffer,
169 SOCK_REQ_V5_HEADER_LEN + connect->hlen,
170 connect_out, connect);
171 } else {
172 const char *msg = tal_fmt(tmpctx,
173 "Connected out for %s error: unexpected connect answer %0x from the tor socks5 proxy",
174 connect->host,
175 connect->buffer[1]);
176 status_debug("%s", msg);
177 add_errors_to_error_list(connect->connect, msg);
178
179 errno = ECONNREFUSED;
180 return io_close(conn);
181 }
182 }
183
io_tor_connect_after_req_to_connect(struct io_conn * conn,struct connecting_socks * connect)184 static struct io_plan *io_tor_connect_after_req_to_connect(struct io_conn *conn,
185 struct connecting_socks
186 *connect)
187 {
188 return io_read(conn, connect->buffer, 2,
189 &io_tor_connect_after_resp_to_connect, connect);
190 }
191
io_tor_connect_do_req(struct io_conn * conn,struct connecting_socks * connect)192 static struct io_plan *io_tor_connect_do_req(struct io_conn *conn,
193 struct connecting_socks *connect)
194 {
195 /* make the init request */
196 connect->buffer[0] = SOCKS_V5;
197 connect->buffer[1] = 1;
198 connect->buffer[2] = SOCKS_NOAUTH;
199
200 status_io(LOG_IO_OUT, NULL, "proxy", connect->buffer, SOCK_REQ_METH_LEN);
201 return io_write(conn, connect->buffer, SOCK_REQ_METH_LEN,
202 &io_tor_connect_after_req_to_connect, connect);
203 }
204
205 /* called when we want to connect to TOR SOCKS5 */
io_tor_connect(struct io_conn * conn,const struct addrinfo * tor_proxyaddr,const char * host,u16 port,struct connecting * connect)206 struct io_plan *io_tor_connect(struct io_conn *conn,
207 const struct addrinfo *tor_proxyaddr,
208 const char *host, u16 port,
209 struct connecting *connect)
210 {
211 struct connecting_socks *connect_tor = tal(connect,
212 struct connecting_socks);
213
214 connect_tor->port = htons(port);
215 connect_tor->host = tal_strdup(connect_tor, host);
216 connect_tor->connect = connect;
217
218 return io_connect(conn, tor_proxyaddr,
219 &io_tor_connect_do_req, connect_tor);
220 }
221