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