]> jfr.im git - solanum.git/blob - authd/providers/opm.c
sockaddr_storage -> rb_sockaddr_storage
[solanum.git] / authd / providers / opm.c
1 /* authd/providers/opm.c - small open proxy monitor
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21 #include "rb_lib.h"
22 #include "stdinc.h"
23 #include "setup.h"
24 #include "authd.h"
25 #include "notice.h"
26 #include "provider.h"
27
28 #define OPM_READSIZE 128
29
30 typedef enum protocol_t
31 {
32 PROTO_NONE,
33 PROTO_SOCKS4,
34 PROTO_SOCKS5,
35 } protocol_t;
36
37 struct opm_lookup
38 {
39 rb_dlink_list scans; /* List of scans */
40 };
41
42 struct opm_proxy
43 {
44 const char *note;
45 protocol_t proto;
46 uint16_t port;
47 };
48
49 struct opm_scan
50 {
51 struct auth_client *auth;
52
53 struct opm_proxy *proxy;
54 rb_fde_t *F; /* fd for scan */
55
56 rb_dlink_node node;
57 };
58
59 struct opm_listener
60 {
61 char ip[HOSTIPLEN];
62 uint16_t port;
63 struct rb_sockaddr_storage addr;
64 rb_fde_t *F;
65 };
66
67 /* Proxies that we scan for */
68 static struct opm_proxy opm_proxy_scans[] =
69 {
70 { "socks4-1080", PROTO_SOCKS4, 1080 },
71 { "socks5-1080", PROTO_SOCKS5, 1080 },
72 { "socks4-80", PROTO_SOCKS4, 80 },
73 { "socks5-80", PROTO_SOCKS5, 80 },
74 { "socks4-8080", PROTO_SOCKS4, 8080 },
75 { "socks5-8080", PROTO_SOCKS5, 8080 },
76 { NULL, PROTO_NONE, 0 }
77 };
78
79
80 static ACCB accept_opm;
81 static PF read_opm_reply;
82
83 static CNCB socks4_connected;
84 static CNCB socks5_connected;
85
86 static void opm_cancel(struct auth_client *auth);
87
88 static int opm_timeout = 5;
89 static bool opm_enable = false;
90
91 #define LISTEN_IPV4 0
92 #define LISTEN_IPV6 1
93
94 /* IPv4 and IPv6 */
95 static struct opm_listener listeners[2];
96
97
98 static void
99 read_opm_reply(rb_fde_t *F, void *data)
100 {
101 struct auth_client *auth = data;
102 struct opm_lookup *lookup;
103 char readbuf[OPM_READSIZE];
104 ssize_t len;
105
106 if(auth == NULL || (lookup = auth->data[PROVIDER_OPM]) == NULL)
107 {
108 rb_close(F);
109 return;
110 }
111
112 if((len = rb_read(F, readbuf, sizeof(readbuf))) < 0 && rb_ignore_errno(errno))
113 {
114 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
115 return;
116 }
117 else if(len <= 0)
118 {
119 /* Dead */
120 rb_close(F);
121 return;
122 }
123
124 for(struct opm_proxy *proxy = opm_proxy_scans; proxy->note != NULL; proxy++)
125 {
126 if(strncmp(proxy->note, readbuf, sizeof(readbuf)) != 0)
127 /* Nope */
128 continue;
129
130 /* If we get here we have an open proxy */
131 reject_client(auth, PROVIDER_OPM, readbuf, "Open proxy detected");
132 opm_cancel(auth);
133 break;
134 }
135
136 rb_close(F);
137 }
138
139 static void
140 accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
141 {
142 struct auth_client *auth = NULL;
143 struct opm_listener *listener = data;
144 struct rb_sockaddr_storage s_addr;
145 unsigned int llen = sizeof(struct rb_sockaddr_storage);
146 rb_dictionary_iter iter;
147
148 if(status != 0 || listener == NULL)
149 {
150 rb_close(F);
151 return;
152 }
153
154 if(getsockname(rb_get_fd(F), (struct sockaddr *)&s_addr, &llen))
155 {
156 /* This can happen if the client goes away after accept */
157 rb_close(F);
158 return;
159 }
160
161 /* Correlate connection with client(s) */
162 RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
163 {
164 if(GET_SS_FAMILY(&auth->c_addr) != GET_SS_FAMILY(&s_addr))
165 continue;
166
167 /* Compare the addresses */
168 switch(GET_SS_FAMILY(&s_addr))
169 {
170 case AF_INET:
171 {
172 struct sockaddr_in *s = (struct sockaddr_in *)&s_addr, *c = (struct sockaddr_in *)&auth->c_addr;
173
174 if(s->sin_addr.s_addr == c->sin_addr.s_addr)
175 {
176 /* Match... check if it's real */
177 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
178 return;
179 }
180 break;
181 }
182 #ifdef RB_IPV6
183 case AF_INET6:
184 {
185 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&s_addr, *c = (struct sockaddr_in6 *)&auth->c_addr;
186
187 if(memcmp(s->sin6_addr.s6_addr, c->sin6_addr.s6_addr, 16) == 0)
188 {
189 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
190 return;
191 }
192 break;
193 }
194 #endif
195 default:
196 warn_opers(L_CRIT, "OPM: unknown address type in listen function");
197 exit(EX_PROVIDER_ERROR);
198 }
199 }
200
201 /* We don't care about the socket if we get here */
202 rb_close(F);
203 }
204
205 /* Scanners */
206
207 static void
208 socks4_connected(rb_fde_t *F, int error, void *data)
209 {
210 struct opm_scan *scan = data;
211 struct opm_lookup *lookup;
212 struct auth_client *auth;
213 uint8_t sendbuf[9]; /* Size we're building */
214 uint8_t *c = sendbuf;
215 ssize_t ret;
216
217 if(scan == NULL || (auth = scan->auth) == NULL || (lookup = auth->data[PROVIDER_OPM]) == NULL)
218 return;
219
220 if(error || !opm_enable)
221 goto end;
222
223 memcpy(c, "\x04\x01", 2); c += 2; /* Socks version 4, connect command */
224
225 switch(GET_SS_FAMILY(&auth->c_addr))
226 {
227 case AF_INET:
228 if(listeners[LISTEN_IPV4].F == NULL)
229 /* They cannot respond to us */
230 goto end;
231
232 memcpy(c, &(((struct sockaddr_in *)&listeners[LISTEN_IPV4].addr)->sin_port), 2); c += 2; /* Port */
233 memcpy(c, &(((struct sockaddr_in *)&listeners[LISTEN_IPV4].addr)->sin_addr.s_addr), 4); c += 4; /* Address */
234 break;
235 #ifdef RB_IPV6
236 case AF_INET6:
237 /* socks4 doesn't support IPv6 */
238 #endif
239 default:
240 goto end;
241 }
242
243 *c = '\x00'; /* No userid */
244
245 /* Send header */
246 if(rb_write(scan->F, sendbuf, sizeof(sendbuf)) < 0)
247 goto end;
248
249 /* Send note */
250 if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) < 0)
251 goto end;
252
253 end:
254 rb_close(scan->F);
255 rb_dlinkDelete(&scan->node, &lookup->scans);
256 rb_free(scan);
257 }
258
259 static void
260 socks5_connected(rb_fde_t *F, int error, void *data)
261 {
262 struct opm_scan *scan = data;
263 struct opm_lookup *lookup;
264 struct opm_listener *listener;
265 struct auth_client *auth;
266 uint8_t sendbuf[25]; /* Size we're building */
267 uint8_t *c = sendbuf;
268 ssize_t ret;
269
270 if(scan == NULL || (auth = scan->auth) == NULL || (lookup = auth->data[PROVIDER_OPM]) == NULL)
271 return;
272
273 if(error || !opm_enable)
274 goto end;
275
276 /* Build the version header and socks request
277 * version header (3 bytes): version, number of auth methods, auth type (0 for none)
278 * connect req (3 bytes): version, command (1 = connect), reserved (0)
279 */
280 memcpy(c, "\x05\x01\x00\x05\x01\x00", 6); c += 6;
281
282 switch(GET_SS_FAMILY(&auth->c_addr))
283 {
284 case AF_INET:
285 listener = &listeners[LISTEN_IPV4];
286 if(!listener->F)
287 goto end;
288
289 *(c++) = '\x01'; /* Address type (1 = IPv4) */
290 memcpy(c, &(((struct sockaddr_in *)&listener->addr)->sin_addr.s_addr), 4); c += 4;/* Address */
291 memcpy(c, &(((struct sockaddr_in *)&listener->addr)->sin_port), 2); c += 2; /* Port */
292 break;
293 #ifdef RB_IPV6
294 case AF_INET6:
295 listener = &listeners[LISTEN_IPV6];
296 if(!listener->F)
297 goto end;
298
299 *(c++) = '\x04'; /* Address type (4 = IPv6) */
300 memcpy(c, ((struct sockaddr_in6 *)&listener->addr)->sin6_addr.s6_addr, 16); c += 16; /* Address */
301 memcpy(c, &(((struct sockaddr_in6 *)&listener->addr)->sin6_port), 2); c += 2; /* Port */
302 break;
303 #endif
304 default:
305 goto end;
306 }
307
308 /* Send header */
309 if(rb_write(scan->F, sendbuf, (size_t)(sendbuf - c)) <= 0)
310 goto end;
311
312 /* Now the note in a separate write */
313 if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) <= 0)
314 goto end;
315
316 end:
317 rb_close(scan->F);
318 rb_dlinkDelete(&scan->node, &lookup->scans);
319 rb_free(scan);
320 }
321
322 /* Establish connections */
323 static inline void
324 establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
325 {
326 struct opm_lookup *lookup = auth->data[PROVIDER_OPM];
327 struct opm_listener *listener;
328 struct opm_scan *scan = rb_malloc(sizeof(struct opm_scan));
329 struct rb_sockaddr_storage c_a, l_a;
330 int opt = 1;
331 CNCB *callback;
332
333 switch(proxy->proto)
334 {
335 case PROTO_SOCKS4:
336 callback = socks4_connected;
337 break;
338 case PROTO_SOCKS5:
339 callback = socks5_connected;
340 break;
341 default:
342 return;
343 }
344
345 #ifdef RB_IPV6
346 if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6)
347 listener = &listeners[LISTEN_IPV6];
348 else
349 #endif
350 listener = &listeners[LISTEN_IPV4];
351
352 c_a = auth->c_addr; /* Client */
353 l_a = listener->addr; /* Listener */
354
355 scan->auth = auth;
356 scan->proxy = proxy;
357 if((scan->F = rb_socket(GET_SS_FAMILY(&auth->c_addr), SOCK_STREAM, 0, proxy->note)) == NULL)
358 {
359 warn_opers(L_CRIT, "OPM: could not create OPM socket (proto %s): %s", proxy->note, strerror(errno));
360 rb_free(scan);
361 return;
362 }
363
364 /* Disable Nagle's algorithim - buffering could affect scans */
365 (void)setsockopt(rb_get_fd(scan->F), IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
366
367 /* Set the ports correctly */
368 #ifdef RB_IPV6
369 if(GET_SS_FAMILY(&l_a) == AF_INET6)
370 ((struct sockaddr_in6 *)&l_a)->sin6_port = 0;
371 else
372 #endif
373 ((struct sockaddr_in *)&l_a)->sin_port = 0;
374
375 #ifdef RB_IPV6
376 if(GET_SS_FAMILY(&c_a) == AF_INET6)
377 ((struct sockaddr_in6 *)&c_a)->sin6_port = ((struct sockaddr_in6 *)&listener->addr)->sin6_port;
378 else
379 #endif
380 ((struct sockaddr_in *)&c_a)->sin_port = ((struct sockaddr_in *)&listener->addr)->sin_port;
381
382 rb_dlinkAdd(scan, &scan->node, &lookup->scans);
383 rb_connect_tcp(scan->F,
384 (struct sockaddr *)&c_a,
385 (struct sockaddr *)&l_a,
386 GET_SS_LEN(&l_a),
387 callback, scan, opm_timeout);
388 }
389
390 static void
391 opm_destroy(void)
392 {
393 struct auth_client *auth;
394 rb_dictionary_iter iter;
395
396 /* Nuke all opm lookups */
397 RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
398 {
399 opm_cancel(auth);
400 }
401 }
402
403 static bool
404 opm_start(struct auth_client *auth)
405 {
406 struct opm_lookup *lookup = rb_malloc(sizeof(struct opm_lookup));
407
408 if(!opm_enable)
409 {
410 notice_client(auth->cid, "*** Proxy scanning disabled, not scanning");
411 return true;
412 }
413
414 auth->data[PROVIDER_OPM] = lookup = rb_malloc(sizeof(struct opm_lookup));
415 auth->timeout[PROVIDER_OPM] = rb_current_time() + opm_timeout;
416
417 for(struct opm_proxy *proxy = opm_proxy_scans; proxy->note != NULL; proxy++)
418 establish_connection(auth, proxy);
419
420 notice_client(auth->cid, "*** Scanning for open proxies...");
421 set_provider_on(auth, PROVIDER_OPM);
422
423 return true;
424 }
425
426 static void
427 opm_cancel(struct auth_client *auth)
428 {
429 struct opm_lookup *lookup = auth->data[PROVIDER_OPM];
430
431 if(lookup != NULL)
432 {
433 rb_dlink_node *ptr, *nptr;
434
435 RB_DLINK_FOREACH_SAFE(ptr, nptr, lookup->scans.head)
436 {
437 struct opm_scan *scan = ptr->data;
438
439 rb_close(scan->F);
440 rb_free(scan);
441 }
442
443 rb_free(lookup);
444 provider_done(auth, PROVIDER_OPM);
445 }
446 }
447
448 static void
449 add_conf_opm_timeout(const char *key __unused, int parc __unused, const char **parv)
450 {
451 int timeout = atoi(parv[0]);
452
453 if(timeout < 0)
454 {
455 warn_opers(L_CRIT, "opm: opm timeout < 0 (value: %d)", timeout);
456 return;
457 }
458
459 opm_timeout = timeout;
460 }
461
462 static void
463 set_opm_enabled(const char *key __unused, int parc __unused, const char **parv)
464 {
465 if(listeners[LISTEN_IPV4].F != NULL || listeners[LISTEN_IPV6].F != NULL)
466 opm_enable = (*parv[0] == '1');
467 else
468 /* No listener, no point... */
469 opm_enable = false;
470 }
471
472 static void
473 set_opm_listener(const char *key __unused, int parc __unused, const char **parv)
474 {
475 struct auth_client *auth;
476 struct rb_sockaddr_storage addr;
477 struct opm_listener *listener;
478 int port = atoi(parv[1]), opt = 1;
479 rb_dictionary_iter iter;
480 rb_fde_t *F;
481 size_t i;
482
483 if(port > 65535 || port <= 0 || !rb_inet_pton_sock(parv[0], (struct sockaddr *)&addr))
484 {
485 warn_opers(L_CRIT, "OPM: got a bad listener: %s:%s", parv[0], parv[1]);
486 exit(EX_PROVIDER_ERROR);
487 }
488
489 #ifdef RB_IPV6
490 if(GET_SS_FAMILY(&addr) == AF_INET6)
491 listener = &listeners[LISTEN_IPV6];
492 else
493 #endif
494 listener = &listeners[LISTEN_IPV4];
495
496 if(strcmp(listener->ip, parv[0]) == 0 || listener->port == port)
497 return;
498
499 if((F = rb_socket(GET_SS_FAMILY(&addr), SOCK_STREAM, 0, "OPM listener socket")) == NULL)
500 {
501 /* This shouldn't fail, or we have problems... */
502 warn_opers(L_CRIT, "OPM: cannot create socket: %s", strerror(errno));
503 exit(EX_PROVIDER_ERROR);
504 }
505
506 if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)))
507 {
508 /* This shouldn't fail either... */
509 warn_opers(L_CRIT, "OPM: cannot set options on socket: %s", strerror(errno));
510 exit(EX_PROVIDER_ERROR);
511 }
512
513 if(bind(rb_get_fd(F), (struct sockaddr *)&addr, GET_SS_LEN(&addr)))
514 {
515 /* Shit happens, let's not cripple authd over this */
516 warn_opers(L_WARN, "OPM: cannot bind on socket: %s", strerror(errno));
517 rb_close(F);
518 return;
519 }
520
521 if(rb_listen(F, SOMAXCONN, false)) /* deferred accept could interfere with detection */
522 {
523 warn_opers(L_WARN, "OPM: cannot listen on socket: %s", strerror(errno));
524 rb_close(F);
525 return;
526 }
527
528 if(listener->F != NULL)
529 /* Close old listener */
530 rb_close(listener->F);
531
532 listener->F = F;
533
534 /* Cancel old clients that may be on old stale listener
535 * XXX - should rescan clients that need it
536 */
537 RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
538 {
539 opm_cancel(auth);
540 }
541
542 #ifdef RB_IPV6
543 if(GET_SS_FAMILY(&addr) == AF_INET6)
544 ((struct sockaddr_in6 *)&addr)->sin6_port = htons(port);
545 else
546 #endif
547 ((struct sockaddr_in *)&addr)->sin_port = htons(port);
548
549 /* Copy data */
550 rb_strlcpy(listener->ip, parv[0], sizeof(listener->ip));
551 listener->port = (uint16_t)port;
552 listener->addr = addr;
553
554 opm_enable = true; /* Implicitly set this to true for now if we have a listener */
555 rb_accept_tcp(F, NULL, accept_opm, listener);
556 }
557
558 struct auth_opts_handler opm_options[] =
559 {
560 { "opm_timeout", 1, add_conf_opm_timeout },
561 { "opm_enabled", 1, set_opm_enabled },
562 { "opm_listener", 2, set_opm_listener },
563 { NULL, 0, NULL },
564 };
565
566 struct auth_provider opm_provider =
567 {
568 .id = PROVIDER_OPM,
569 .destroy = opm_destroy,
570 .start = opm_start,
571 .cancel = opm_cancel,
572 .timeout = opm_cancel,
573 .opt_handlers = opm_options,
574 };