]> jfr.im git - solanum.git/blob - authd/providers/opm.c
[openssl] Forward-port some more cleanups from fixes to 3.5
[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 "stdinc.h"
22 #include "rb_lib.h"
23 #include "defaults.h"
24 #include "setup.h"
25 #include "authd.h"
26 #include "notice.h"
27 #include "provider.h"
28
29 #define SELF_PID (opm_provider.id)
30
31 #define OPM_READSIZE 128
32
33 typedef enum protocol_t
34 {
35 PROTO_NONE,
36 PROTO_SOCKS4,
37 PROTO_SOCKS5,
38 PROTO_HTTP_CONNECT,
39 PROTO_HTTPS_CONNECT,
40 } protocol_t;
41
42 /* Lookup data associated with auth client */
43 struct opm_lookup
44 {
45 rb_dlink_list scans; /* List of scans */
46 bool in_progress;
47 };
48
49 struct opm_scan;
50 typedef void (*opm_callback_t)(struct opm_scan *);
51
52 /* A proxy scanner */
53 struct opm_proxy
54 {
55 char note[16];
56 protocol_t proto;
57 uint16_t port;
58 bool ssl; /* Connect to proxy with SSL */
59 bool ipv6; /* Proxy supports IPv6 */
60
61 opm_callback_t callback;
62
63 rb_dlink_node node;
64 };
65
66 /* A listener for proxy replies */
67 struct opm_listener
68 {
69 char ip[HOSTIPLEN];
70 uint16_t port;
71 struct rb_sockaddr_storage addr;
72 rb_fde_t *F;
73 };
74
75 /* An individual proxy scan */
76 struct opm_scan
77 {
78 struct auth_client *auth;
79 rb_fde_t *F; /* fd for scan */
80
81 struct opm_proxy *proxy; /* Associated proxy */
82 struct opm_listener *listener; /* Associated listener */
83
84 rb_dlink_node node;
85 };
86
87 /* Proxies that we scan for */
88 static rb_dlink_list proxy_scanners;
89
90 static ACCB accept_opm;
91 static PF read_opm_reply;
92
93 static CNCB opm_connected;
94
95 static void opm_cancel(struct auth_client *auth);
96 static bool create_listener(const char *ip, uint16_t port);
97
98 static int opm_timeout = OPM_TIMEOUT_DEFAULT;
99 static bool opm_enable = false;
100
101 enum
102 {
103 LISTEN_IPV4,
104 LISTEN_IPV6,
105 LISTEN_LAST,
106 };
107
108 /* IPv4 and IPv6 */
109 static struct opm_listener listeners[LISTEN_LAST];
110
111 static inline protocol_t
112 get_protocol_from_string(const char *str)
113 {
114 if(strcasecmp(str, "socks4") == 0)
115 return PROTO_SOCKS4;
116 else if(strcasecmp(str, "socks5") == 0)
117 return PROTO_SOCKS5;
118 else if(strcasecmp(str, "httpconnect") == 0)
119 return PROTO_HTTP_CONNECT;
120 else if(strcasecmp(str, "httpsconnect") == 0)
121 return PROTO_HTTPS_CONNECT;
122 else
123 return PROTO_NONE;
124 }
125
126 static inline struct opm_proxy *
127 find_proxy_scanner(protocol_t proto, uint16_t port)
128 {
129 rb_dlink_node *ptr;
130
131 RB_DLINK_FOREACH(ptr, proxy_scanners.head)
132 {
133 struct opm_proxy *proxy = ptr->data;
134
135 if(proxy->proto == proto && proxy->port == port)
136 return proxy;
137 }
138
139 return NULL;
140 }
141
142 /* This is called when an open proxy connects to us */
143 static void
144 read_opm_reply(rb_fde_t *F, void *data)
145 {
146 rb_dlink_node *ptr;
147 struct auth_client *auth = data;
148 struct opm_lookup *lookup;
149 char readbuf[OPM_READSIZE];
150 ssize_t len;
151
152 lrb_assert(auth != NULL);
153 lookup = get_provider_data(auth, SELF_PID);
154 lrb_assert(lookup != NULL);
155
156 if((len = rb_read(F, readbuf, sizeof(readbuf))) < 0 && rb_ignore_errno(errno))
157 {
158 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
159 return;
160 }
161 else if(len <= 0)
162 {
163 /* Dead */
164 rb_close(F);
165 return;
166 }
167
168 RB_DLINK_FOREACH(ptr, proxy_scanners.head)
169 {
170 struct opm_proxy *proxy = ptr->data;
171
172 if(strncmp(proxy->note, readbuf, strlen(proxy->note)) == 0)
173 {
174 rb_dlink_node *ptr, *nptr;
175
176 /* Cancel outstanding lookups */
177 RB_DLINK_FOREACH_SAFE(ptr, nptr, lookup->scans.head)
178 {
179 struct opm_scan *scan = ptr->data;
180
181 rb_close(scan->F);
182 rb_free(scan);
183 }
184
185 /* No longer needed, client is going away */
186 rb_free(lookup);
187
188 reject_client(auth, SELF_PID, readbuf, "Open proxy detected");
189 break;
190 }
191 }
192
193 rb_close(F);
194 }
195
196 static void
197 accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, void *data)
198 {
199 struct opm_listener *listener = data;
200 struct rb_sockaddr_storage localaddr;
201 unsigned int llen = sizeof(struct rb_sockaddr_storage);
202 rb_dlink_node *ptr;
203
204 if(status != 0 || listener == NULL)
205 {
206 rb_close(F);
207 return;
208 }
209
210 if(getsockname(rb_get_fd(F), (struct sockaddr *)&localaddr, &llen))
211 {
212 /* This can happen if the client goes away after accept */
213 rb_close(F);
214 return;
215 }
216
217 /* Correlate connection with client(s) */
218 RB_DLINK_FOREACH(ptr, auth_clients.head)
219 {
220 struct auth_client *auth = ptr->data;
221
222 if(GET_SS_FAMILY(&auth->c_addr) != GET_SS_FAMILY(&localaddr))
223 continue;
224
225 /* Compare the addresses */
226 switch(GET_SS_FAMILY(&localaddr))
227 {
228 case AF_INET:
229 {
230 struct sockaddr_in *s = (struct sockaddr_in *)&localaddr, *c = (struct sockaddr_in *)&auth->c_addr;
231
232 if(s->sin_addr.s_addr == c->sin_addr.s_addr)
233 {
234 /* Match... check if it's real */
235 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
236 return;
237 }
238 break;
239 }
240 #ifdef RB_IPV6
241 case AF_INET6:
242 {
243 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&localaddr, *c = (struct sockaddr_in6 *)&auth->c_addr;
244
245 if(IN6_ARE_ADDR_EQUAL(&s->sin6_addr, &c->sin6_addr))
246 {
247 rb_setselect(F, RB_SELECT_READ, read_opm_reply, auth);
248 return;
249 }
250 break;
251 }
252 #endif
253 default:
254 warn_opers(L_CRIT, "OPM: unknown address type in listen function");
255 exit(EX_PROVIDER_ERROR);
256 }
257 }
258
259 /* We don't care about the socket if we get here */
260 rb_close(F);
261 }
262
263 /* Scanners */
264
265 static void
266 opm_connected(rb_fde_t *F, int error, void *data)
267 {
268 struct opm_scan *scan = data;
269 struct opm_proxy *proxy = scan->proxy;
270 struct auth_client *auth = scan->auth;
271 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
272
273 if(error || !opm_enable)
274 {
275 //notice_client(scan->auth->cid, "*** Scan not connected: %s", proxy->note);
276 goto end;
277 }
278
279 switch(GET_SS_FAMILY(&auth->c_addr))
280 {
281 case AF_INET:
282 if(listeners[LISTEN_IPV4].F == NULL)
283 /* They cannot respond to us */
284 goto end;
285
286 break;
287 #ifdef RB_IPV6
288 case AF_INET6:
289 if(!proxy->ipv6)
290 /* Welp, too bad */
291 goto end;
292
293 if(listeners[LISTEN_IPV6].F == NULL)
294 /* They cannot respond to us */
295 goto end;
296
297 break;
298 #endif
299 default:
300 goto end;
301 }
302
303 proxy->callback(scan);
304
305 end:
306 rb_close(scan->F);
307 rb_dlinkDelete(&scan->node, &lookup->scans);
308 rb_free(scan);
309 }
310
311 static void
312 socks4_connected(struct opm_scan *scan)
313 {
314 struct auth_client *auth = scan->auth;
315 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
316 uint8_t sendbuf[9]; /* Size we're building */
317 uint8_t *c = sendbuf;
318
319 memcpy(c, "\x04\x01", 2); c += 2; /* Socks version 4, connect command */
320 memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_port), 2); c += 2; /* Port */
321 memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_addr.s_addr), 4); c += 4; /* Address */
322 *c = '\x00'; /* No userid */
323
324 /* Send header */
325 if(rb_write(scan->F, sendbuf, sizeof(sendbuf)) < 0)
326 return;
327
328 /* Send note */
329 if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) < 0)
330 return;
331 }
332
333 static void
334 socks5_connected(struct opm_scan *scan)
335 {
336 struct auth_client *auth = scan->auth;
337 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
338 uint8_t sendbuf[25]; /* Size we're building */
339 uint8_t *c = sendbuf;
340
341 auth = scan->auth;
342 lookup = get_provider_data(auth, SELF_PID);
343
344 /* Build the version header and socks request
345 * version header (3 bytes): version, number of auth methods, auth type (0 for none)
346 * connect req (3 bytes): version, command (1 = connect), reserved (0)
347 */
348 memcpy(c, "\x05\x01\x00\x05\x01\x00", 6); c += 6;
349
350 switch(GET_SS_FAMILY(&auth->c_addr))
351 {
352 case AF_INET:
353 *(c++) = '\x01'; /* Address type (1 = IPv4) */
354 memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_addr.s_addr), 4); c += 4; /* Address */
355 memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_port), 2); c += 2; /* Port */
356 break;
357 #ifdef RB_IPV6
358 case AF_INET6:
359 *(c++) = '\x04'; /* Address type (4 = IPv6) */
360 memcpy(c, ((struct sockaddr_in6 *)&scan->listener->addr)->sin6_addr.s6_addr, 16); c += 16; /* Address */
361 memcpy(c, &(((struct sockaddr_in6 *)&scan->listener->addr)->sin6_port), 2); c += 2; /* Port */
362 break;
363 #endif
364 default:
365 return;
366 }
367
368 /* Send header */
369 if(rb_write(scan->F, sendbuf, (size_t)(sendbuf - c)) <= 0)
370 return;
371
372 /* Now the note in a separate write */
373 if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) <= 0)
374 return;
375 }
376
377 static void
378 http_connect_connected(struct opm_scan *scan)
379 {
380 struct auth_client *auth = scan->auth;
381 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
382 char sendbuf[128]; /* A bit bigger than we need but better safe than sorry */
383 char *c = sendbuf;
384
385 /* Simple enough to build */
386 snprintf(sendbuf, sizeof(sendbuf), "CONNECT %s:%hu HTTP/1.0\r\n\r\n", scan->listener->ip, scan->listener->port);
387
388 /* Send request */
389 if(rb_write(scan->F, sendbuf, strlen(sendbuf)) <= 0)
390 return;
391
392 /* Now the note in a separate write */
393 if(rb_write(scan->F, scan->proxy->note, strlen(scan->proxy->note) + 1) <= 0)
394 return;
395
396 /* MiroTik needs this, and as a separate write */
397 if(rb_write(scan->F, "\r\n", 2) <= 0)
398 return;
399 }
400
401 /* Establish connections */
402 static inline void
403 establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
404 {
405 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
406 struct opm_scan *scan = rb_malloc(sizeof(struct opm_scan));
407 struct opm_listener *listener;
408 struct rb_sockaddr_storage c_a, l_a;
409 int opt = 1;
410
411 lrb_assert(lookup != NULL);
412
413 #ifdef RB_IPV6
414 if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6)
415 {
416 if(proxy->proto == PROTO_SOCKS4)
417 {
418 /* SOCKS4 doesn't support IPv6 */
419 rb_free(scan);
420 return;
421 }
422 listener = &listeners[LISTEN_IPV6];
423 }
424 else
425 #endif
426 listener = &listeners[LISTEN_IPV4];
427
428 if(listener->F == NULL)
429 {
430 /* We can't respond */
431 rb_free(scan);
432 return;
433 }
434
435 c_a = auth->c_addr; /* Client */
436 l_a = listener->addr; /* Listener (connect using its IP) */
437
438 scan->auth = auth;
439 scan->proxy = proxy;
440 scan->listener = listener;
441 if((scan->F = rb_socket(GET_SS_FAMILY(&auth->c_addr), SOCK_STREAM, 0, proxy->note)) == NULL)
442 {
443 warn_opers(L_WARN, "OPM: could not create OPM socket (proto %s): %s", proxy->note, strerror(errno));
444 rb_free(scan);
445 return;
446 }
447
448 /* Disable Nagle's algorithim - buffering could affect scans */
449 (void)setsockopt(rb_get_fd(scan->F), IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
450
451 SET_SS_PORT(&l_a, 0);
452 SET_SS_PORT(&c_a, htons(proxy->port));
453
454 rb_dlinkAdd(scan, &scan->node, &lookup->scans);
455
456 if(!proxy->ssl)
457 rb_connect_tcp(scan->F,
458 (struct sockaddr *)&c_a,
459 (struct sockaddr *)&l_a,
460 opm_connected, scan, opm_timeout);
461 else
462 rb_connect_tcp_ssl(scan->F,
463 (struct sockaddr *)&c_a,
464 (struct sockaddr *)&l_a,
465 opm_connected, scan, opm_timeout);
466 }
467
468 static bool
469 create_listener(const char *ip, uint16_t port)
470 {
471 struct opm_listener *listener;
472 struct rb_sockaddr_storage addr;
473 rb_dlink_node *ptr, *nptr;
474 rb_fde_t *F;
475 int opt = 1;
476
477 if(!rb_inet_pton_sock(ip, (struct sockaddr *)&addr))
478 {
479 warn_opers(L_CRIT, "OPM: got a bad listener: %s:%hu", ip, port);
480 exit(EX_PROVIDER_ERROR);
481 }
482
483 SET_SS_PORT(&addr, htons(port));
484
485 #ifdef RB_IPV6
486 if(GET_SS_FAMILY(&addr) == AF_INET6)
487 {
488 struct sockaddr_in6 *a1, *a2;
489
490 listener = &listeners[LISTEN_IPV6];
491
492 a1 = (struct sockaddr_in6 *)&addr;
493 a2 = (struct sockaddr_in6 *)&listener->addr;
494
495 if(IN6_ARE_ADDR_EQUAL(&a1->sin6_addr, &a2->sin6_addr) &&
496 GET_SS_PORT(&addr) == GET_SS_PORT(&listener->addr) &&
497 listener->F != NULL)
498 {
499 /* Listener already exists */
500 return false;
501 }
502 }
503 else
504 #endif
505 {
506 struct sockaddr_in *a1, *a2;
507
508 listener = &listeners[LISTEN_IPV4];
509
510 a1 = (struct sockaddr_in *)&addr;
511 a2 = (struct sockaddr_in *)&listener->addr;
512
513 if(a1->sin_addr.s_addr == a2->sin_addr.s_addr &&
514 GET_SS_PORT(&addr) == GET_SS_PORT(&listener->addr) &&
515 listener->F != NULL)
516 {
517 /* Listener already exists */
518 return false;
519 }
520 }
521
522 if((F = rb_socket(GET_SS_FAMILY(&addr), SOCK_STREAM, 0, "OPM listener socket")) == NULL)
523 {
524 /* This shouldn't fail, or we have big problems... */
525 warn_opers(L_CRIT, "OPM: cannot create socket: %s", strerror(errno));
526 exit(EX_PROVIDER_ERROR);
527 }
528
529 if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)))
530 {
531 /* This shouldn't fail either... */
532 warn_opers(L_CRIT, "OPM: cannot set options on socket: %s", strerror(errno));
533 exit(EX_PROVIDER_ERROR);
534 }
535
536 if(bind(rb_get_fd(F), (struct sockaddr *)&addr, GET_SS_LEN(&addr)))
537 {
538 /* Shit happens, let's not cripple authd over /this/ since it could be user error */
539 warn_opers(L_WARN, "OPM: cannot bind on socket: %s", strerror(errno));
540 rb_close(F);
541 return false;
542 }
543
544 if(rb_listen(F, SOMAXCONN, false)) /* deferred accept could interfere with detection */
545 {
546 /* Again, could be user error */
547 warn_opers(L_WARN, "OPM: cannot listen on socket: %s", strerror(errno));
548 rb_close(F);
549 return false;
550 }
551
552 /* From this point forward we assume we have a listener */
553
554 if(listener->F != NULL)
555 /* Close old listener */
556 rb_close(listener->F);
557
558 listener->F = F;
559
560 /* Cancel clients that may be on old listener
561 * XXX - should rescan clients that need it
562 */
563 RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head)
564 {
565 struct auth_client *auth = ptr->data;
566 opm_cancel(auth);
567 }
568
569 /* Copy data */
570 rb_strlcpy(listener->ip, ip, sizeof(listener->ip));
571 listener->port = port;
572 listener->addr = addr;
573
574 opm_enable = true; /* Implicitly set this to true for now if we have a listener */
575 rb_accept_tcp(listener->F, NULL, accept_opm, listener);
576 return true;
577 }
578
579 static void
580 opm_scan(struct auth_client *auth)
581 {
582 rb_dlink_node *ptr;
583 struct opm_lookup *lookup;
584
585 lrb_assert(auth != NULL);
586
587 lookup = get_provider_data(auth, SELF_PID);
588 set_provider_timeout_relative(auth, SELF_PID, opm_timeout);
589
590 lookup->in_progress = true;
591
592 RB_DLINK_FOREACH(ptr, proxy_scanners.head)
593 {
594 struct opm_proxy *proxy = ptr->data;
595 //notice_client(auth->cid, "*** Scanning for proxy type %s", proxy->note);
596 establish_connection(auth, proxy);
597 }
598
599 notice_client(auth->cid, "*** Scanning for open proxies...");
600 }
601
602 /* This is called every time a provider is completed as long as we are marked not done */
603 static void
604 opm_initiate(struct auth_client *auth, uint32_t provider)
605 {
606 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
607 uint32_t rdns_pid, ident_pid;
608
609 lrb_assert(provider != SELF_PID);
610 lrb_assert(!is_provider_done(auth, SELF_PID));
611 lrb_assert(rb_dlink_list_length(&proxy_scanners) > 0);
612
613 if(lookup == NULL || lookup->in_progress)
614 /* Nothing to do */
615 return;
616 else if((!get_provider_id("rdns", &rdns_pid) || is_provider_done(auth, rdns_pid)) &&
617 (!get_provider_id("ident", &ident_pid) || is_provider_done(auth, ident_pid)))
618 /* Don't start until ident and rdns are finished (or not loaded) */
619 return;
620 else
621 opm_scan(auth);
622 }
623
624 static bool
625 opm_start(struct auth_client *auth)
626 {
627 uint32_t rdns_pid, ident_pid;
628
629 lrb_assert(get_provider_data(auth, SELF_PID) == NULL);
630
631 if(!opm_enable || rb_dlink_list_length(&proxy_scanners) == 0)
632 /* Nothing to do... */
633 return true;
634
635 set_provider_data(auth, SELF_PID, rb_malloc(sizeof(struct opm_lookup)));
636
637 if((!get_provider_id("rdns", &rdns_pid) || is_provider_done(auth, rdns_pid)) &&
638 (!get_provider_id("ident", &ident_pid) || is_provider_done(auth, ident_pid)))
639 {
640 /* Don't start until ident and rdns are finished (or not loaded) */
641 opm_scan(auth);
642 }
643
644 set_provider_running(auth, SELF_PID);
645 return true;
646 }
647
648 static void
649 opm_cancel(struct auth_client *auth)
650 {
651 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
652
653 if(lookup != NULL)
654 {
655 rb_dlink_node *ptr, *nptr;
656
657 notice_client(auth->cid, "*** Did not detect open proxies");
658
659 RB_DLINK_FOREACH_SAFE(ptr, nptr, lookup->scans.head)
660 {
661 struct opm_scan *scan = ptr->data;
662
663 rb_close(scan->F);
664 rb_free(scan);
665 }
666
667 rb_free(lookup);
668
669 set_provider_data(auth, SELF_PID, NULL);
670 set_provider_timeout_absolute(auth, SELF_PID, 0);
671 provider_done(auth, SELF_PID);
672 }
673 }
674
675 static void
676 opm_destroy(void)
677 {
678 rb_dlink_node *ptr, *nptr;
679
680 /* Nuke all opm lookups */
681 RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head)
682 {
683 struct auth_client *auth = ptr->data;
684 opm_cancel(auth);
685 }
686 }
687
688
689 static void
690 add_conf_opm_timeout(const char *key __unused, int parc __unused, const char **parv)
691 {
692 int timeout = atoi(parv[0]);
693
694 if(timeout < 0)
695 {
696 warn_opers(L_CRIT, "opm: opm timeout < 0 (value: %d)", timeout);
697 return;
698 }
699
700 opm_timeout = timeout;
701 }
702
703 static void
704 set_opm_enabled(const char *key __unused, int parc __unused, const char **parv)
705 {
706 bool enable = (*parv[0] == '1');
707
708 if(!enable)
709 {
710 if(listeners[LISTEN_IPV4].F != NULL || listeners[LISTEN_IPV6].F != NULL)
711 {
712 rb_dlink_node *ptr, *nptr;
713
714 /* Close the listening socket */
715 if(listeners[LISTEN_IPV4].F != NULL)
716 rb_close(listeners[LISTEN_IPV4].F);
717
718 if(listeners[LISTEN_IPV6].F != NULL)
719 rb_close(listeners[LISTEN_IPV6].F);
720
721 listeners[LISTEN_IPV4].F = listeners[LISTEN_IPV6].F = NULL;
722
723 RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head)
724 {
725 struct auth_client *auth = ptr->data;
726 opm_cancel(auth);
727 }
728 }
729 }
730 else
731 {
732 if(listeners[LISTEN_IPV4].ip[0] != '\0' && listeners[LISTEN_IPV4].port != 0)
733 {
734 if(listeners[LISTEN_IPV4].F == NULL)
735 /* Pre-configured IP/port, just re-establish */
736 create_listener(listeners[LISTEN_IPV4].ip, listeners[LISTEN_IPV4].port);
737 }
738
739 if(listeners[LISTEN_IPV6].ip[0] != '\0' && listeners[LISTEN_IPV6].port != 0)
740 {
741 if(listeners[LISTEN_IPV6].F == NULL)
742 /* Pre-configured IP/port, just re-establish */
743 create_listener(listeners[LISTEN_IPV6].ip, listeners[LISTEN_IPV6].port);
744 }
745 }
746
747 opm_enable = enable;
748 }
749
750 static void
751 set_opm_listener(const char *key __unused, int parc __unused, const char **parv)
752 {
753 const char *ip = parv[0];
754 int iport = atoi(parv[1]);
755
756 if(iport > 65535 || iport <= 0)
757 {
758 warn_opers(L_CRIT, "OPM: got a bad listener: %s:%s", parv[0], parv[1]);
759 exit(EX_PROVIDER_ERROR);
760 }
761
762 create_listener(ip, (uint16_t)iport);
763 }
764
765 static void
766 create_opm_scanner(const char *key __unused, int parc __unused, const char **parv)
767 {
768 int iport = atoi(parv[1]);
769 struct opm_proxy *proxy = rb_malloc(sizeof(struct opm_proxy));
770
771 if(iport <= 0 || iport > 65535)
772 {
773 warn_opers(L_CRIT, "OPM: got a bad scanner: %s (port %s)", parv[0], parv[1]);
774 exit(EX_PROVIDER_ERROR);
775 }
776
777 proxy->port = (uint16_t)iport;
778
779 switch((proxy->proto = get_protocol_from_string(parv[0])))
780 {
781 case PROTO_SOCKS4:
782 snprintf(proxy->note, sizeof(proxy->note), "socks4:%hu", proxy->port);
783 proxy->ssl = false;
784 proxy->callback = socks4_connected;
785 break;
786 case PROTO_SOCKS5:
787 snprintf(proxy->note, sizeof(proxy->note), "socks5:%hu", proxy->port);
788 proxy->ssl = false;
789 proxy->callback = socks5_connected;
790 break;
791 case PROTO_HTTP_CONNECT:
792 snprintf(proxy->note, sizeof(proxy->note), "httpconnect:%hu", proxy->port);
793 proxy->ssl = false;
794 proxy->callback = http_connect_connected;
795 break;
796 case PROTO_HTTPS_CONNECT:
797 snprintf(proxy->note, sizeof(proxy->note), "httpsconnect:%hu", proxy->port);
798 proxy->callback = http_connect_connected;
799 proxy->ssl = true;
800 break;
801 default:
802 warn_opers(L_CRIT, "OPM: got an unknown proxy type: %s (port %hu)", parv[0], proxy->port);
803 exit(EX_PROVIDER_ERROR);
804 }
805
806 if(find_proxy_scanner(proxy->proto, proxy->port) != NULL)
807 {
808 warn_opers(L_CRIT, "OPM: got a duplicate scanner: %s (port %hu)", parv[0], proxy->port);
809 exit(EX_PROVIDER_ERROR);
810 }
811
812 rb_dlinkAdd(proxy, &proxy->node, &proxy_scanners);
813 }
814
815 static void
816 delete_opm_scanner(const char *key __unused, int parc __unused, const char **parv)
817 {
818 struct opm_proxy *proxy;
819 protocol_t proto = get_protocol_from_string(parv[0]);
820 int iport = atoi(parv[1]);
821 rb_dlink_node *ptr, *nptr;
822
823 if(iport <= 0 || iport > 65535)
824 {
825 warn_opers(L_CRIT, "OPM: got a bad scanner to delete: %s (port %s)", parv[0], parv[1]);
826 exit(EX_PROVIDER_ERROR);
827 }
828
829 if(proto == PROTO_NONE)
830 {
831 warn_opers(L_CRIT, "OPM: got an unknown proxy type to delete: %s (port %d)", parv[0], iport);
832 exit(EX_PROVIDER_ERROR);
833 }
834
835 if((proxy = find_proxy_scanner(proto, (uint16_t)iport)) == NULL)
836 {
837 warn_opers(L_CRIT, "OPM: cannot find proxy to delete: %s (port %d)", parv[0], iport);
838 exit(EX_PROVIDER_ERROR);
839 }
840
841 /* Abort remaining clients on this scanner */
842 RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head)
843 {
844 struct auth_client *auth = ptr->data;
845 struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
846 rb_dlink_node *optr;
847
848 if(lookup == NULL)
849 continue;
850
851 RB_DLINK_FOREACH(optr, lookup->scans.head)
852 {
853 struct opm_scan *scan = optr->data;
854
855 if(scan->proxy->port == proxy->port && scan->proxy->proto == proxy->proto)
856 {
857 /* Match */
858 rb_dlinkDelete(&scan->node, &lookup->scans);
859 rb_free(scan);
860
861 if(rb_dlink_list_length(&lookup->scans) == 0)
862 opm_cancel(auth);
863
864 break;
865 }
866 }
867 }
868
869 rb_dlinkDelete(&proxy->node, &proxy_scanners);
870 rb_free(proxy);
871
872 if(rb_dlink_list_length(&proxy_scanners) == 0)
873 opm_enable = false;
874 }
875
876 static void
877 delete_opm_scanner_all(const char *key __unused, int parc __unused, const char **parv __unused)
878 {
879 rb_dlink_node *ptr, *nptr;
880
881 RB_DLINK_FOREACH_SAFE(ptr, nptr, proxy_scanners.head)
882 {
883 rb_free(ptr->data);
884 rb_dlinkDelete(ptr, &proxy_scanners);
885 }
886
887 RB_DLINK_FOREACH_SAFE(ptr, nptr, auth_clients.head)
888 {
889 struct auth_client *auth = ptr->data;
890 opm_cancel(auth);
891 }
892
893 opm_enable = false;
894 }
895
896 static void
897 delete_opm_listener_all(const char *key __unused, int parc __unused, const char **parv __unused)
898 {
899 if(listeners[LISTEN_IPV4].F != NULL)
900 rb_close(listeners[LISTEN_IPV4].F);
901
902 #ifdef RB_IPV6
903 if(listeners[LISTEN_IPV6].F != NULL)
904 rb_close(listeners[LISTEN_IPV6].F);
905 #endif
906
907 memset(&listeners, 0, sizeof(listeners));
908 }
909
910
911 struct auth_opts_handler opm_options[] =
912 {
913 { "opm_timeout", 1, add_conf_opm_timeout },
914 { "opm_enabled", 1, set_opm_enabled },
915 { "opm_listener", 2, set_opm_listener },
916 { "opm_listener_del_all", 0, delete_opm_listener_all },
917 { "opm_scanner", 2, create_opm_scanner },
918 { "opm_scanner_del", 2, delete_opm_scanner },
919 { "opm_scanner_del_all", 0, delete_opm_scanner_all },
920 { NULL, 0, NULL },
921 };
922
923 struct auth_provider opm_provider =
924 {
925 .name = "opm",
926 .letter = 'O',
927 .destroy = opm_destroy,
928 .start = opm_start,
929 .cancel = opm_cancel,
930 .timeout = opm_cancel,
931 .completed = opm_initiate,
932 .opt_handlers = opm_options,
933 };