1 #include "config.h"
2 #include <ccan/err/err.h>
3 #include <ccan/rbuf/rbuf.h>
4 #include <ccan/read_write_all/read_write_all.h>
5 #include <ccan/tal/grab_file/grab_file.h>
6 #include <ccan/tal/str/str.h>
7 #include <common/base64.h>
8 #include <common/utils.h>
9 #include <common/wireaddr.h>
10 #include <connectd/tor_autoservice.h>
11 #include <errno.h>
12 #include <lightningd/log.h>
13 #include <netdb.h>
14 #include <unistd.h>
15 
16 
buf_resize(struct membuf * mb,void * buf,size_t len)17 static void *buf_resize(struct membuf *mb, void *buf, size_t len)
18 {
19 	tal_resize(&buf, len);
20 	return buf;
21 }
22 
tor_send_cmd(struct rbuf * rbuf,const char * cmd)23 static void tor_send_cmd(struct rbuf *rbuf, const char *cmd)
24 {
25 	status_io(LOG_IO_OUT, NULL, "torcontrol", cmd, strlen(cmd));
26 	if (!write_all(rbuf->fd, cmd, strlen(cmd)))
27 		status_failed(STATUS_FAIL_INTERNAL_ERROR,
28 			      "Writing '%s' to Tor socket", cmd);
29 
30 	status_io(LOG_IO_OUT, NULL, "torcontrol", "\r\n", 2);
31 	if (!write_all(rbuf->fd, "\r\n", 2))
32 		status_failed(STATUS_FAIL_INTERNAL_ERROR,
33 			      "Writing CRLF to Tor socket");
34 }
35 
tor_response_line_wfail(struct rbuf * rbuf)36 static char *tor_response_line_wfail(struct rbuf *rbuf)
37 {
38 	char *line = NULL;
39 
40 	while ((line = rbuf_read_str(rbuf, '\n')) != NULL) {
41 		status_io(LOG_IO_IN, NULL, "torcontrol", line, strlen(line));
42 
43 		/* Weird response */
44 		if (!strstarts(line, "250") && !strstarts(line, "550"))
45 			status_failed(STATUS_FAIL_INTERNAL_ERROR,
46 				      "Tor returned '%s'", line);
47 
48 		/* Last line */
49 		if (strstarts(line, "250 ") || strstarts(line, "550 "))
50 			break;
51 
52 		return line + 4;
53 	}
54 	if (line)
55 		return line + 4;
56 	else
57 		return NULL;
58 }
59 
tor_response_line(struct rbuf * rbuf)60 static char *tor_response_line(struct rbuf *rbuf)
61 {
62 	char *line;
63 
64 	while ((line = rbuf_read_str(rbuf, '\n')) != NULL) {
65 		status_io(LOG_IO_IN, NULL, "torcontrol", line, strlen(line));
66 
67 		/* Weird response */
68 		if (!strstarts(line, "250"))
69 			status_failed(STATUS_FAIL_INTERNAL_ERROR,
70 				      "Tor returned '%s'", line);
71 
72 		/* Last line */
73 		if (strstarts(line, "250 "))
74 			break;
75 
76 		return line + 4;
77 	}
78 	return NULL;
79 }
80 
discard_remaining_response(struct rbuf * rbuf)81 static void discard_remaining_response(struct rbuf *rbuf)
82 {
83 	while (tor_response_line(rbuf));
84 }
85 
make_onion(const tal_t * ctx,struct rbuf * rbuf,const struct wireaddr * local,bool use_v3_autotor,u16 port)86 static struct wireaddr *make_onion(const tal_t *ctx,
87 				   struct rbuf *rbuf,
88 				   const struct wireaddr *local,
89 				   bool use_v3_autotor,
90 				   u16 port)
91 {
92 	char *line;
93 	struct wireaddr *onion;
94 
95 	/* Now that V3 is out of Beta default to V3 autoservice onions if version is above 0.4
96 	*/
97 	tor_send_cmd(rbuf, "PROTOCOLINFO 1");
98 
99 	while ((line = tor_response_line(rbuf)) != NULL) {
100 
101 		if (!strstarts(line, "VERSION Tor="))
102 			continue;
103 
104 		if (use_v3_autotor)
105 			if (strstr(line, "\"0.0") ||
106 				strstr(line, "\"0.1") ||
107 				strstr(line, "\"0.2") ||
108 				strstr(line, "\"0.3")) {
109 						use_v3_autotor = false;
110 						status_unusual("Autotor: fallback to try a V2 onion service, your Tor version is smaller than 0.4.x.x");
111 			}
112 	};
113 
114 	if (!use_v3_autotor) {
115 		tor_send_cmd(rbuf,
116 		     tal_fmt(tmpctx, "ADD_ONION NEW:RSA1024 Port=%d,%s Flags=DiscardPK,Detach",
117 			     port, fmt_wireaddr(tmpctx, local)));
118 	} else {
119 		tor_send_cmd(rbuf,
120 		     tal_fmt(tmpctx, "ADD_ONION NEW:ED25519-V3 Port=%d,%s Flags=DiscardPK,Detach",
121 			     port, fmt_wireaddr(tmpctx, local)));
122 	}
123 
124 	while ((line = tor_response_line(rbuf)) != NULL) {
125 		const char *name;
126 
127 		if (!strstarts(line, "ServiceID="))
128 			continue;
129 		line += strlen("ServiceID=");
130 		/* Strip the trailing CR */
131 		if (strchr(line, '\r'))
132 			*strchr(line, '\r') = '\0';
133 
134 		name = tal_fmt(tmpctx, "%s.onion", line);
135 		onion = tal(ctx, struct wireaddr);
136 		if (!parse_wireaddr(name, onion, local->port, false, NULL))
137 			status_failed(STATUS_FAIL_INTERNAL_ERROR,
138 				      "Tor gave bad onion name '%s'", name);
139 		status_info("New autotor service onion address: \"%s:%d\" bound from extern port:%d", name, local->port, port);
140 		discard_remaining_response(rbuf);
141 		return onion;
142 	}
143 	status_failed(STATUS_FAIL_INTERNAL_ERROR,
144 		      "Tor didn't give us a ServiceID");
145 }
146 
make_fixed_onion(const tal_t * ctx,struct rbuf * rbuf,const struct wireaddr * local,const u8 * blob,u16 port)147 static struct wireaddr *make_fixed_onion(const tal_t *ctx,
148 				   struct rbuf *rbuf,
149 				   const struct wireaddr *local, const u8 *blob, u16 port)
150 {
151 	char *line;
152 	struct wireaddr *onion;
153 	char *blob64;
154 
155 	blob64 = b64_encode(tmpctx, blob, 64);
156 
157 	tor_send_cmd(rbuf,
158 			 tal_fmt(tmpctx, "ADD_ONION ED25519-V3:%s Port=%d,%s Flags=DiscardPK",
159 			 blob64, port, fmt_wireaddr(tmpctx, local)));
160 
161 	while ((line = tor_response_line_wfail(rbuf))) {
162 		const char *name;
163 		if (strstarts(line, "Onion address collision"))
164 			status_failed(STATUS_FAIL_INTERNAL_ERROR,
165 				      "Tor address in use");
166 
167 		if (!strstarts(line, "ServiceID="))
168 			continue;
169 		line += strlen("ServiceID=");
170 		/* Strip the trailing CR */
171 		if (strchr(line, '\r'))
172 			*strchr(line, '\r') = '\0';
173 
174 		name = tal_fmt(tmpctx, "%s.onion", line);
175 		onion = tal(ctx, struct wireaddr);
176 		if (!parse_wireaddr(name, onion, port, false, NULL))
177 			status_failed(STATUS_FAIL_INTERNAL_ERROR,
178 				      "Tor gave bad onion name '%s'", name);
179 		#ifdef SUPERVERBOSE
180 		 status_info("Static Tor service onion address: \"%s:%d,%s\"from blob %s base64 %s ",
181 						name, port ,fmt_wireaddr(tmpctx, local), blob ,blob64);
182 		#else
183 		status_info("Static Tor service onion address: \"%s:%d,%s\" bound from extern port %d ",
184 						name, port ,fmt_wireaddr(tmpctx, local), port);
185 		#endif
186 		discard_remaining_response(rbuf);
187 		return onion;
188 	}
189 	return NULL;
190 }
191 
192 /* https://gitweb.torproject.org/torspec.git/tree/control-spec.txt:
193  *
194  *     MidReplyLine = StatusCode "-" ReplyLine
195  *     DataReplyLine = StatusCode "+" ReplyLine CmdData
196  *         EndReplyLine = StatusCode SP ReplyLine
197  *         ReplyLine = [ReplyText] CRLF
198  *         ReplyText = XXXX
199  *         StatusCode = 3DIGIT
200  */
negotiate_auth(struct rbuf * rbuf,const char * tor_password)201 static void negotiate_auth(struct rbuf *rbuf, const char *tor_password)
202 {
203 	char *line;
204 	char *cookiefile = NULL;
205 	int cookiefileerrno = 0;
206 
207 	tor_send_cmd(rbuf, "PROTOCOLINFO 1");
208 
209 	while ((line = tor_response_line(rbuf)) != NULL) {
210 		const char *p;
211 
212 		if (!strstarts(line, "AUTH METHODS="))
213 			continue;
214 
215 		if (strstr(line, "NULL")) {
216 			discard_remaining_response(rbuf);
217 			tor_send_cmd(rbuf, "AUTHENTICATE");
218 			discard_remaining_response(rbuf);
219 			return;
220 		} else if (strstr(line, "HASHEDPASSWORD")
221 			   && strlen(tor_password)) {
222 			discard_remaining_response(rbuf);
223 			tor_send_cmd(rbuf,
224 				     tal_fmt(tmpctx, "AUTHENTICATE \"%s\"",
225 					     tor_password));
226 			discard_remaining_response(rbuf);
227 			return;
228 		} else if ((p = strstr(line, "COOKIEFILE=\"")) != NULL) {
229 			char *contents, *end;
230 
231 			p += strlen("COOKIEFILE=\"");
232 			end = strstr(p, "\"");
233 			if (!end)
234 				status_failed(STATUS_FAIL_INTERNAL_ERROR,
235 					      "Tor protocolinfo bad line '%s'",
236 					      line);
237 			*end = '\0';
238 
239 			/* If we can't access this, try other methods */
240 			cookiefile = tal_strdup(tmpctx, p);
241 			contents = grab_file(tmpctx, p);
242 			if (!contents) {
243 				cookiefileerrno = errno;
244 				continue;
245 			}
246 			assert(tal_count(contents) != 0);
247 			discard_remaining_response(rbuf);
248 			tor_send_cmd(rbuf,
249 				     tal_fmt(tmpctx, "AUTHENTICATE %s",
250 					     tal_hexstr(tmpctx,
251 							contents,
252 							tal_count(contents)-1)));
253 			discard_remaining_response(rbuf);
254 			return;
255 		}
256 	}
257 
258 	/* Now report if we tried cookie file and it failed */
259 	if (cookiefile)
260 		status_failed(STATUS_FAIL_INTERNAL_ERROR,
261 			      "Could not open Tor cookie file '%s': %s",
262 			      cookiefile, strerror(cookiefileerrno));
263 
264 	status_failed(STATUS_FAIL_INTERNAL_ERROR,
265 		      "Tor protocolinfo did not give auth");
266 }
267 
268 /* We need to have a bound address we can tell Tor to connect to */
269 const struct wireaddr *
find_local_address(const struct wireaddr_internal * bindings)270 find_local_address(const struct wireaddr_internal *bindings)
271 {
272 	for (size_t i = 0; i < tal_count(bindings); i++) {
273 		if (bindings[i].itype != ADDR_INTERNAL_WIREADDR)
274 			continue;
275 		if (bindings[i].u.wireaddr.type != ADDR_TYPE_IPV4
276 		    && bindings[i].u.wireaddr.type != ADDR_TYPE_IPV6)
277 			continue;
278 		return &bindings[i].u.wireaddr;
279 	}
280 	status_failed(STATUS_FAIL_INTERNAL_ERROR,
281 		      "No local address found to tell Tor to connect to");
282 }
283 
tor_autoservice(const tal_t * ctx,const struct wireaddr_internal * tor_serviceaddr,const char * tor_password,const struct wireaddr_internal * bindings,const bool use_v3_autotor)284 struct wireaddr *tor_autoservice(const tal_t *ctx,
285 				 const struct wireaddr_internal *tor_serviceaddr,
286 				 const char *tor_password,
287 				 const struct wireaddr_internal *bindings,
288 				 const bool use_v3_autotor)
289 {
290 	int fd;
291 	const struct wireaddr *laddr;
292 	struct wireaddr *onion;
293 	struct addrinfo *ai_tor;
294 	struct rbuf rbuf;
295 	char *buffer;
296 
297 	laddr = find_local_address(bindings);
298 	ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address);
299 
300 	fd = socket(ai_tor->ai_family, SOCK_STREAM, 0);
301 	if (fd < 0)
302 		err(1, "Creating stream socket for Tor");
303 
304 	if (connect(fd, ai_tor->ai_addr, ai_tor->ai_addrlen) != 0)
305 		err(1, "Connecting stream socket to Tor service");
306 
307 	buffer = tal_arr(tmpctx, char, rbuf_good_size(fd));
308 	rbuf_init(&rbuf, fd, buffer, tal_count(buffer), buf_resize);
309 
310 	negotiate_auth(&rbuf, tor_password);
311 	onion = make_onion(ctx, &rbuf, laddr, use_v3_autotor, tor_serviceaddr->u.torservice.port);
312 
313 	/*on the other hand we can stay connected until ln finish to keep onion alive and then vanish */
314 	//because when we run with Detach flag as we now do every start of LN creates a new addr while the old
315 	//stays valid until reboot this might not be desired so we can also drop Detach and use the
316 	//read_partial to keep it open until LN drops
317 	//FIXME: SAIBATO we might not want to close this conn
318 	close(fd);
319 
320 	return onion;
321 }
322 
tor_fixed_service(const tal_t * ctx,const struct wireaddr_internal * tor_serviceaddr,const char * tor_password,const u8 * blob,const struct wireaddr * bind,const u8 index)323 struct wireaddr *tor_fixed_service(const tal_t *ctx,
324 				 const struct wireaddr_internal *tor_serviceaddr,
325 				 const char *tor_password,
326 				 const u8 *blob,
327 				 const struct wireaddr *bind,
328 				 const u8 index)
329 {
330 	int fd;
331 	const struct wireaddr *laddr;
332 	struct wireaddr *onion;
333 	struct addrinfo *ai_tor;
334 	struct rbuf rbuf;
335 	char *buffer;
336 
337 	laddr = bind;
338 	ai_tor = wireaddr_to_addrinfo(tmpctx, &tor_serviceaddr->u.torservice.address);
339 
340 	fd = socket(ai_tor->ai_family, SOCK_STREAM, 0);
341 	if (fd < 0)
342 		err(1, "Creating stream socket for Tor");
343 
344 	if (connect(fd, ai_tor->ai_addr, ai_tor->ai_addrlen) != 0)
345 		err(1, "Connecting stream socket to Tor service");
346 
347 	buffer = tal_arr(tmpctx, char, rbuf_good_size(fd));
348 	rbuf_init(&rbuf, fd, buffer, tal_count(buffer), buf_resize);
349 
350 	negotiate_auth(&rbuf, tor_password);
351 
352 	onion = make_fixed_onion(ctx, &rbuf, laddr, blob, tor_serviceaddr->u.torservice.port);
353 	/*on the other hand we can stay connected until ln finish to keep onion alive and then vanish
354 	* because when we run with Detach flag as we now do every start of LN creates a new addr while the old
355 	* stays valid until reboot this might not be desired so we can also drop Detach and use the
356 	* read_partial to keep it open until LN drops
357 	* DO NOT CLOSE FD TO KEEP ADDRESS ALIVE AS WE DO NOT DETACH WITH STATIC ADDRESS
358 	*/
359 	return onion;
360 }
361