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