1 /* authd/providers/opm.c - small open proxy monitor
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
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.
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.
28 #define OPM_READSIZE 128
30 typedef enum protocol_t
41 rb_dlink_list scans
; /* List of scans */
57 struct auth_client
*auth
;
59 struct opm_proxy
*proxy
;
60 rb_fde_t
*F
; /* fd for scan */
69 struct rb_sockaddr_storage addr
;
73 /* Proxies that we scan for */
74 static rb_dlink_list proxy_scanners
;
76 static ACCB accept_opm
;
77 static PF read_opm_reply
;
79 static CNCB socks4_connected
;
80 static CNCB socks5_connected
;
82 static void opm_cancel(struct auth_client
*auth
);
83 static bool create_listener(const char *ip
, uint16_t port
);
85 static int opm_timeout
= 10;
86 static bool opm_enable
= false;
92 static struct opm_listener listeners
[2];
94 static inline protocol_t
95 get_protocol_from_string(const char *str
)
97 if(strcasecmp(str
, "socks4") == 0)
99 else if(strcasecmp(str
, "socks5") == 0)
101 else if(strcasecmp(str
, "httpconnect") == 0)
102 return PROTO_HTTP_CONNECT
;
103 else if(strcasecmp(str
, "httpsconnect") == 0)
104 return PROTO_HTTPS_CONNECT
;
109 static inline struct opm_proxy
*
110 find_proxy_scanner(protocol_t proto
, uint16_t port
)
114 RB_DLINK_FOREACH(ptr
, proxy_scanners
.head
)
116 struct opm_proxy
*proxy
= ptr
->data
;
118 if(proxy
->proto
== proto
&& proxy
->port
== port
)
126 read_opm_reply(rb_fde_t
*F
, void *data
)
129 struct auth_client
*auth
= data
;
130 struct opm_lookup
*lookup
;
131 char readbuf
[OPM_READSIZE
];
134 if(auth
== NULL
|| (lookup
= auth
->data
[PROVIDER_OPM
]) == NULL
)
140 if((len
= rb_read(F
, readbuf
, sizeof(readbuf
))) < 0 && rb_ignore_errno(errno
))
142 rb_setselect(F
, RB_SELECT_READ
, read_opm_reply
, auth
);
152 RB_DLINK_FOREACH(ptr
, proxy_scanners
.head
)
154 struct opm_proxy
*proxy
= ptr
->data
;
156 if(strncmp(proxy
->note
, readbuf
, strlen(proxy
->note
)) == 0)
158 rb_dlink_node
*ptr
, *nptr
;
160 /* Cancel outstanding lookups */
161 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, lookup
->scans
.head
)
163 struct opm_scan
*scan
= ptr
->data
;
169 /* No longer needed, client is going away */
172 reject_client(auth
, PROVIDER_OPM
, readbuf
, "Open proxy detected");
181 accept_opm(rb_fde_t
*F
, int status
, struct sockaddr
*addr
, rb_socklen_t len
, void *data
)
183 struct auth_client
*auth
= NULL
;
184 struct opm_listener
*listener
= data
;
185 struct rb_sockaddr_storage localaddr
;
186 unsigned int llen
= sizeof(struct rb_sockaddr_storage
);
187 rb_dictionary_iter iter
;
189 if(status
!= 0 || listener
== NULL
)
195 if(getsockname(rb_get_fd(F
), (struct sockaddr
*)&localaddr
, &llen
))
197 /* This can happen if the client goes away after accept */
202 /* Correlate connection with client(s) */
203 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
205 if(GET_SS_FAMILY(&auth
->c_addr
) != GET_SS_FAMILY(&localaddr
))
208 /* Compare the addresses */
209 switch(GET_SS_FAMILY(&localaddr
))
213 struct sockaddr_in
*s
= (struct sockaddr_in
*)&localaddr
, *c
= (struct sockaddr_in
*)&auth
->c_addr
;
215 if(s
->sin_addr
.s_addr
== c
->sin_addr
.s_addr
)
217 /* Match... check if it's real */
218 rb_setselect(F
, RB_SELECT_READ
, read_opm_reply
, auth
);
226 struct sockaddr_in6
*s
= (struct sockaddr_in6
*)&localaddr
, *c
= (struct sockaddr_in6
*)&auth
->c_addr
;
228 if(IN6_ARE_ADDR_EQUAL(&s
->sin6_addr
, &c
->sin6_addr
))
230 rb_setselect(F
, RB_SELECT_READ
, read_opm_reply
, auth
);
237 warn_opers(L_CRIT
, "OPM: unknown address type in listen function");
238 exit(EX_PROVIDER_ERROR
);
242 /* We don't care about the socket if we get here */
249 socks4_connected(rb_fde_t
*F
, int error
, void *data
)
251 struct opm_scan
*scan
= data
;
252 struct opm_lookup
*lookup
;
253 struct auth_client
*auth
;
254 uint8_t sendbuf
[9]; /* Size we're building */
255 uint8_t *c
= sendbuf
;
258 if(scan
== NULL
|| (auth
= scan
->auth
) == NULL
|| (lookup
= auth
->data
[PROVIDER_OPM
]) == NULL
)
261 if(error
|| !opm_enable
)
264 memcpy(c
, "\x04\x01", 2); c
+= 2; /* Socks version 4, connect command */
266 switch(GET_SS_FAMILY(&auth
->c_addr
))
269 if(listeners
[LISTEN_IPV4
].F
== NULL
)
270 /* They cannot respond to us */
273 memcpy(c
, &(((struct sockaddr_in
*)&listeners
[LISTEN_IPV4
].addr
)->sin_port
), 2); c
+= 2; /* Port */
274 memcpy(c
, &(((struct sockaddr_in
*)&listeners
[LISTEN_IPV4
].addr
)->sin_addr
.s_addr
), 4); c
+= 4; /* Address */
278 /* socks4 doesn't support IPv6 */
284 *c
= '\x00'; /* No userid */
287 if(rb_write(scan
->F
, sendbuf
, sizeof(sendbuf
)) < 0)
291 if(rb_write(scan
->F
, scan
->proxy
->note
, strlen(scan
->proxy
->note
) + 1) < 0)
296 rb_dlinkDelete(&scan
->node
, &lookup
->scans
);
301 socks5_connected(rb_fde_t
*F
, int error
, void *data
)
303 struct opm_scan
*scan
= data
;
304 struct opm_lookup
*lookup
;
305 struct opm_listener
*listener
;
306 struct auth_client
*auth
;
307 uint8_t sendbuf
[25]; /* Size we're building */
308 uint8_t *c
= sendbuf
;
311 if(scan
== NULL
|| (auth
= scan
->auth
) == NULL
|| (lookup
= auth
->data
[PROVIDER_OPM
]) == NULL
)
314 if(error
|| !opm_enable
)
317 /* Build the version header and socks request
318 * version header (3 bytes): version, number of auth methods, auth type (0 for none)
319 * connect req (3 bytes): version, command (1 = connect), reserved (0)
321 memcpy(c
, "\x05\x01\x00\x05\x01\x00", 6); c
+= 6;
323 switch(GET_SS_FAMILY(&auth
->c_addr
))
326 listener
= &listeners
[LISTEN_IPV4
];
330 *(c
++) = '\x01'; /* Address type (1 = IPv4) */
331 memcpy(c
, &(((struct sockaddr_in
*)&listener
->addr
)->sin_addr
.s_addr
), 4); c
+= 4;/* Address */
332 memcpy(c
, &(((struct sockaddr_in
*)&listener
->addr
)->sin_port
), 2); c
+= 2; /* Port */
336 listener
= &listeners
[LISTEN_IPV6
];
340 *(c
++) = '\x04'; /* Address type (4 = IPv6) */
341 memcpy(c
, ((struct sockaddr_in6
*)&listener
->addr
)->sin6_addr
.s6_addr
, 16); c
+= 16; /* Address */
342 memcpy(c
, &(((struct sockaddr_in6
*)&listener
->addr
)->sin6_port
), 2); c
+= 2; /* Port */
350 if(rb_write(scan
->F
, sendbuf
, (size_t)(sendbuf
- c
)) <= 0)
353 /* Now the note in a separate write */
354 if(rb_write(scan
->F
, scan
->proxy
->note
, strlen(scan
->proxy
->note
) + 1) <= 0)
359 rb_dlinkDelete(&scan
->node
, &lookup
->scans
);
364 http_connect_connected(rb_fde_t
*F
, int error
, void *data
)
366 struct opm_scan
*scan
= data
;
367 struct opm_lookup
*lookup
;
368 struct opm_listener
*listener
;
369 struct auth_client
*auth
;
370 char sendbuf
[128]; /* A bit bigger than we need but better safe than sorry */
374 if(scan
== NULL
|| (auth
= scan
->auth
) == NULL
|| (lookup
= auth
->data
[PROVIDER_OPM
]) == NULL
)
377 if(error
|| !opm_enable
)
380 switch(GET_SS_FAMILY(&auth
->c_addr
))
383 listener
= &listeners
[LISTEN_IPV4
];
389 listener
= &listeners
[LISTEN_IPV6
];
398 /* Simple enough to build */
399 snprintf(sendbuf
, sizeof(sendbuf
), "CONNECT %s:%hu HTTP/1.0\r\n\r\n", listener
->ip
, listener
->port
);
402 if(rb_write(scan
->F
, sendbuf
, strlen(sendbuf
)) <= 0)
405 /* Now the note in a separate write */
406 if(rb_write(scan
->F
, scan
->proxy
->note
, strlen(scan
->proxy
->note
) + 1) <= 0)
409 /* MiroTik needs this, and as a separate write */
410 if(rb_write(scan
->F
, "\r\n", 2) <= 0)
415 rb_dlinkDelete(&scan
->node
, &lookup
->scans
);
419 /* Establish connections */
421 establish_connection(struct auth_client
*auth
, struct opm_proxy
*proxy
)
423 struct opm_lookup
*lookup
= auth
->data
[PROVIDER_OPM
];
424 struct opm_listener
*listener
;
425 struct opm_scan
*scan
= rb_malloc(sizeof(struct opm_scan
));
426 struct rb_sockaddr_storage c_a
, l_a
;
434 /* SOCKS4 is IPv4 only */
435 if(GET_SS_FAMILY(&auth
->c_addr
) == AF_INET6
)
441 callback
= socks4_connected
;
444 callback
= socks5_connected
;
446 case PROTO_HTTP_CONNECT
:
447 case PROTO_HTTPS_CONNECT
:
448 callback
= http_connect_connected
;
454 if(GET_SS_FAMILY(&auth
->c_addr
) == AF_INET6
)
455 listener
= &listeners
[LISTEN_IPV6
];
458 listener
= &listeners
[LISTEN_IPV4
];
460 c_a
= auth
->c_addr
; /* Client */
461 l_a
= listener
->addr
; /* Listener */
465 if((scan
->F
= rb_socket(GET_SS_FAMILY(&auth
->c_addr
), SOCK_STREAM
, 0, proxy
->note
)) == NULL
)
467 warn_opers(L_WARN
, "OPM: could not create OPM socket (proto %s): %s", proxy
->note
, strerror(errno
));
472 /* Disable Nagle's algorithim - buffering could affect scans */
473 (void)setsockopt(rb_get_fd(scan
->F
), IPPROTO_TCP
, TCP_NODELAY
, (char *)&opt
, sizeof(opt
));
475 SET_SS_PORT(&l_a
, 0);
476 SET_SS_PORT(&c_a
, htons(proxy
->port
));
478 rb_dlinkAdd(scan
, &scan
->node
, &lookup
->scans
);
481 rb_connect_tcp(scan
->F
,
482 (struct sockaddr
*)&c_a
,
483 (struct sockaddr
*)&l_a
,
485 callback
, scan
, opm_timeout
);
487 rb_connect_tcp_ssl(scan
->F
,
488 (struct sockaddr
*)&c_a
,
489 (struct sockaddr
*)&l_a
,
491 callback
, scan
, opm_timeout
);
495 create_listener(const char *ip
, uint16_t port
)
497 struct auth_client
*auth
;
498 struct opm_listener
*listener
;
499 struct rb_sockaddr_storage addr
;
500 rb_dictionary_iter iter
;
504 if(!rb_inet_pton_sock(ip
, (struct sockaddr
*)&addr
))
506 warn_opers(L_CRIT
, "OPM: got a bad listener: %s:%hu", ip
, port
);
507 exit(EX_PROVIDER_ERROR
);
510 SET_SS_PORT(&addr
, htons(port
));
513 if(GET_SS_FAMILY(&addr
) == AF_INET6
)
515 struct sockaddr_in6
*a1
, *a2
;
517 listener
= &listeners
[LISTEN_IPV6
];
519 a1
= (struct sockaddr_in6
*)&addr
;
520 a2
= (struct sockaddr_in6
*)&listener
->addr
;
522 if(IN6_ARE_ADDR_EQUAL(&a1
->sin6_addr
, &a2
->sin6_addr
) &&
523 GET_SS_PORT(&addr
) == GET_SS_PORT(&listener
->addr
) &&
526 /* Listener already exists */
533 struct sockaddr_in
*a1
, *a2
;
535 listener
= &listeners
[LISTEN_IPV4
];
537 a1
= (struct sockaddr_in
*)&addr
;
538 a2
= (struct sockaddr_in
*)&listener
->addr
;
540 if(a1
->sin_addr
.s_addr
== a2
->sin_addr
.s_addr
&&
541 GET_SS_PORT(&addr
) == GET_SS_PORT(&listener
->addr
) &&
544 /* Listener already exists */
549 if((F
= rb_socket(GET_SS_FAMILY(&addr
), SOCK_STREAM
, 0, "OPM listener socket")) == NULL
)
551 /* This shouldn't fail, or we have big problems... */
552 warn_opers(L_CRIT
, "OPM: cannot create socket: %s", strerror(errno
));
553 exit(EX_PROVIDER_ERROR
);
556 if(setsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_REUSEADDR
, (char *)&opt
, sizeof(opt
)))
558 /* This shouldn't fail either... */
559 warn_opers(L_CRIT
, "OPM: cannot set options on socket: %s", strerror(errno
));
560 exit(EX_PROVIDER_ERROR
);
563 if(bind(rb_get_fd(F
), (struct sockaddr
*)&addr
, GET_SS_LEN(&addr
)))
565 /* Shit happens, let's not cripple authd over /this/ since it could be user error */
566 warn_opers(L_WARN
, "OPM: cannot bind on socket: %s", strerror(errno
));
571 if(rb_listen(F
, SOMAXCONN
, false)) /* deferred accept could interfere with detection */
573 /* Again, could be user error */
574 warn_opers(L_WARN
, "OPM: cannot listen on socket: %s", strerror(errno
));
579 /* From this point forward we assume we have a listener */
581 if(listener
->F
!= NULL
)
582 /* Close old listener */
583 rb_close(listener
->F
);
587 /* Cancel clients that may be on old listener
588 * XXX - should rescan clients that need it
590 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
596 rb_strlcpy(listener
->ip
, ip
, sizeof(listener
->ip
));
597 listener
->port
= port
;
598 listener
->addr
= addr
;
600 opm_enable
= true; /* Implicitly set this to true for now if we have a listener */
601 rb_accept_tcp(listener
->F
, NULL
, accept_opm
, listener
);
606 opm_scan(struct auth_client
*auth
)
609 struct opm_lookup
*lookup
;
611 lrb_assert(auth
!= NULL
);
612 lookup
= auth
->data
[PROVIDER_OPM
];
614 auth
->timeout
[PROVIDER_OPM
] = rb_current_time() + opm_timeout
;
616 lookup
->in_progress
= true;
618 RB_DLINK_FOREACH(ptr
, proxy_scanners
.head
)
620 struct opm_proxy
*proxy
= ptr
->data
;
621 establish_connection(auth
, proxy
);
624 notice_client(auth
->cid
, "*** Scanning for open proxies...");
627 /* This is called every time a provider is completed as long as we are marked not done */
629 blacklists_initiate(struct auth_client
*auth
, provider_t provider
)
631 struct opm_lookup
*lookup
= auth
->data
[PROVIDER_OPM
];
633 lrb_assert(provider
!= PROVIDER_OPM
);
634 lrb_assert(!is_provider_done(auth
, PROVIDER_OPM
));
635 lrb_assert(rb_dlink_list_length(&proxy_scanners
) > 0);
637 if(lookup
== NULL
|| lookup
->in_progress
)
640 else if(!(is_provider_done(auth
, PROVIDER_RDNS
) && is_provider_done(auth
, PROVIDER_IDENT
)))
641 /* Don't start until we've completed these */
648 opm_start(struct auth_client
*auth
)
650 if(auth
->data
[PROVIDER_OPM
] != NULL
)
653 if(!opm_enable
|| rb_dlink_list_length(&proxy_scanners
) == 0)
655 /* Nothing to do... */
656 notice_client(auth
->cid
, "*** Proxy scanning disabled, not scanning");
660 auth
->data
[PROVIDER_BLACKLIST
] = rb_malloc(sizeof(struct opm_lookup
));
662 if(is_provider_done(auth
, PROVIDER_RDNS
) && is_provider_done(auth
, PROVIDER_IDENT
))
663 /* This probably can't happen but let's handle this case anyway */
666 set_provider_on(auth
, PROVIDER_BLACKLIST
);
671 opm_cancel(struct auth_client
*auth
)
673 struct opm_lookup
*lookup
= auth
->data
[PROVIDER_OPM
];
677 rb_dlink_node
*ptr
, *nptr
;
679 notice_client(auth
->cid
, "*** Did not detect open proxies");
681 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, lookup
->scans
.head
)
683 struct opm_scan
*scan
= ptr
->data
;
690 provider_done(auth
, PROVIDER_OPM
);
697 struct auth_client
*auth
;
698 rb_dictionary_iter iter
;
700 /* Nuke all opm lookups */
701 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
709 add_conf_opm_timeout(const char *key __unused
, int parc __unused
, const char **parv
)
711 int timeout
= atoi(parv
[0]);
715 warn_opers(L_CRIT
, "opm: opm timeout < 0 (value: %d)", timeout
);
719 opm_timeout
= timeout
;
723 set_opm_enabled(const char *key __unused
, int parc __unused
, const char **parv
)
725 bool enable
= (*parv
[0] == '1');
729 if(listeners
[LISTEN_IPV4
].F
!= NULL
|| listeners
[LISTEN_IPV6
].F
!= NULL
)
731 struct auth_client
*auth
;
732 rb_dictionary_iter iter
;
734 /* Close the listening socket */
735 if(listeners
[LISTEN_IPV4
].F
!= NULL
)
736 rb_close(listeners
[LISTEN_IPV4
].F
);
738 if(listeners
[LISTEN_IPV6
].F
!= NULL
)
739 rb_close(listeners
[LISTEN_IPV6
].F
);
741 listeners
[LISTEN_IPV4
].F
= listeners
[LISTEN_IPV6
].F
= NULL
;
743 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
751 if(listeners
[LISTEN_IPV4
].ip
[0] != '\0' && listeners
[LISTEN_IPV4
].port
!= 0)
753 lrb_assert(listeners
[LISTEN_IPV4
].F
== NULL
);
755 /* Pre-configured IP/port, just re-establish */
756 create_listener(listeners
[LISTEN_IPV4
].ip
, listeners
[LISTEN_IPV4
].port
);
759 if(listeners
[LISTEN_IPV6
].ip
[0] != '\0' && listeners
[LISTEN_IPV6
].port
!= 0)
761 lrb_assert(listeners
[LISTEN_IPV6
].F
== NULL
);
763 /* Pre-configured IP/port, just re-establish */
764 create_listener(listeners
[LISTEN_IPV6
].ip
, listeners
[LISTEN_IPV6
].port
);
772 set_opm_listener(const char *key __unused
, int parc __unused
, const char **parv
)
774 const char *ip
= parv
[0];
775 int iport
= atoi(parv
[1]);
777 if(iport
> 65535 || iport
<= 0)
779 warn_opers(L_CRIT
, "OPM: got a bad listener: %s:%s", parv
[0], parv
[1]);
780 exit(EX_PROVIDER_ERROR
);
783 create_listener(ip
, (uint16_t)iport
);
787 create_opm_scanner(const char *key __unused
, int parc __unused
, const char **parv
)
789 int iport
= atoi(parv
[1]);
790 struct opm_proxy
*proxy
= rb_malloc(sizeof(struct opm_proxy
));
792 if(iport
<= 0 || iport
> 65535)
794 warn_opers(L_CRIT
, "OPM: got a bad scanner: %s (port %s)", parv
[0], parv
[1]);
795 exit(EX_PROVIDER_ERROR
);
798 proxy
->port
= (uint16_t)iport
;
800 switch((proxy
->proto
= get_protocol_from_string(parv
[0])))
803 snprintf(proxy
->note
, sizeof(proxy
->note
), "socks4:%hu", proxy
->port
);
807 snprintf(proxy
->note
, sizeof(proxy
->note
), "socks5:%hu", proxy
->port
);
810 case PROTO_HTTP_CONNECT
:
811 snprintf(proxy
->note
, sizeof(proxy
->note
), "httpconnect:%hu", proxy
->port
);
814 case PROTO_HTTPS_CONNECT
:
815 snprintf(proxy
->note
, sizeof(proxy
->note
), "httpsconnect:%hu", proxy
->port
);
819 warn_opers(L_CRIT
, "OPM: got an unknown proxy type: %s (port %hu)", parv
[0], proxy
->port
);
820 exit(EX_PROVIDER_ERROR
);
823 if(find_proxy_scanner(proxy
->proto
, proxy
->port
) != NULL
)
825 warn_opers(L_CRIT
, "OPM: got a duplicate scanner: %s (port %hu)", parv
[0], proxy
->port
);
826 exit(EX_PROVIDER_ERROR
);
829 rb_dlinkAdd(proxy
, &proxy
->node
, &proxy_scanners
);
833 delete_opm_scanner(const char *key __unused
, int parc __unused
, const char **parv
)
835 struct auth_client
*auth
;
836 struct opm_proxy
*proxy
;
837 protocol_t proto
= get_protocol_from_string(parv
[0]);
838 int iport
= atoi(parv
[1]);
839 rb_dictionary_iter iter
;
841 if(iport
<= 0 || iport
> 65535)
843 warn_opers(L_CRIT
, "OPM: got a bad scanner to delete: %s (port %s)", parv
[0], parv
[1]);
844 exit(EX_PROVIDER_ERROR
);
847 if(proto
== PROTO_NONE
)
849 warn_opers(L_CRIT
, "OPM: got an unknown proxy type to delete: %s (port %d)", parv
[0], iport
);
850 exit(EX_PROVIDER_ERROR
);
853 if((proxy
= find_proxy_scanner(proto
, (uint16_t)iport
)) == NULL
)
855 warn_opers(L_CRIT
, "OPM: cannot find proxy to delete: %s (port %d)", parv
[0], iport
);
856 exit(EX_PROVIDER_ERROR
);
859 /* Abort remaining clients on this scanner */
860 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
863 struct opm_lookup
*lookup
= auth
->data
[PROVIDER_OPM
];
868 RB_DLINK_FOREACH(ptr
, lookup
->scans
.head
)
870 struct opm_scan
*scan
= ptr
->data
;
872 if(scan
->proxy
->port
== proxy
->port
&& scan
->proxy
->proto
== proxy
->proto
)
875 rb_dlinkDelete(&scan
->node
, &lookup
->scans
);
878 if(rb_dlink_list_length(&lookup
->scans
) == 0)
886 rb_dlinkDelete(&proxy
->node
, &proxy_scanners
);
889 if(rb_dlink_list_length(&proxy_scanners
) == 0)
894 delete_opm_scanner_all(const char *key __unused
, int parc __unused
, const char **parv __unused
)
896 struct auth_client
*auth
;
897 rb_dlink_node
*ptr
, *nptr
;
898 rb_dictionary_iter iter
;
900 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, proxy_scanners
.head
)
903 rb_dlinkDelete(ptr
, &proxy_scanners
);
906 RB_DICTIONARY_FOREACH(auth
, &iter
, auth_clients
)
915 struct auth_opts_handler opm_options
[] =
917 { "opm_timeout", 1, add_conf_opm_timeout
},
918 { "opm_enabled", 1, set_opm_enabled
},
919 { "opm_listener", 2, set_opm_listener
},
920 { "opm_scanner", 2, create_opm_scanner
},
921 { "opm_scanner_del", 2, delete_opm_scanner
},
922 { "opm_scanner_del_all", 0, delete_opm_scanner_all
},
926 struct auth_provider opm_provider
=
929 .destroy
= opm_destroy
,
931 .cancel
= opm_cancel
,
932 .timeout
= opm_cancel
,
933 .opt_handlers
= opm_options
,