]> jfr.im git - solanum.git/blobdiff - authd/providers/opm.c
authd/providers/opm.c: include <netinet/tcp.h> (#318)
[solanum.git] / authd / providers / opm.c
index 3c53e77c15946641053e7b58680b9a9db480c588..54ae6c2de0550e3350c0f39d19b8dc3cf395cc57 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "rb_lib.h"
 #include "stdinc.h"
+#include "rb_lib.h"
+#include "defaults.h"
 #include "setup.h"
 #include "authd.h"
 #include "notice.h"
 #include "provider.h"
 
+#include <netinet/tcp.h> // TCP_NODELAY
+
 #define SELF_PID (opm_provider.id)
 
 #define OPM_READSIZE 128
@@ -94,14 +97,18 @@ static CNCB opm_connected;
 static void opm_cancel(struct auth_client *auth);
 static bool create_listener(const char *ip, uint16_t port);
 
-static int opm_timeout = 10;
+static int opm_timeout = OPM_TIMEOUT_DEFAULT;
 static bool opm_enable = false;
 
-#define LISTEN_IPV4 0
-#define LISTEN_IPV6 1
+enum
+{
+       LISTEN_IPV4,
+       LISTEN_IPV6,
+       LISTEN_LAST,
+};
 
 /* IPv4 and IPv6 */
-static struct opm_listener listeners[2];
+static struct opm_listener listeners[LISTEN_LAST];
 
 static inline protocol_t
 get_protocol_from_string(const char *str)
@@ -231,7 +238,6 @@ accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, voi
                                }
                                break;
                        }
-#ifdef RB_IPV6
                case AF_INET6:
                        {
                                struct sockaddr_in6 *s = (struct sockaddr_in6 *)&localaddr, *c = (struct sockaddr_in6 *)&auth->c_addr;
@@ -243,7 +249,6 @@ accept_opm(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t len, voi
                                }
                                break;
                        }
-#endif
                default:
                        warn_opers(L_CRIT, "OPM: unknown address type in listen function");
                        exit(EX_PROVIDER_ERROR);
@@ -278,7 +283,6 @@ opm_connected(rb_fde_t *F, int error, void *data)
                        goto end;
 
                break;
-#ifdef RB_IPV6
        case AF_INET6:
                if(!proxy->ipv6)
                        /* Welp, too bad */
@@ -289,7 +293,6 @@ opm_connected(rb_fde_t *F, int error, void *data)
                        goto end;
 
                break;
-#endif
        default:
                goto end;
        }
@@ -298,15 +301,13 @@ opm_connected(rb_fde_t *F, int error, void *data)
 
 end:
        rb_close(scan->F);
-       rb_dlinkFindDelete(scan, &lookup->scans);
+       rb_dlinkDelete(&scan->node, &lookup->scans);
        rb_free(scan);
 }
 
 static void
 socks4_connected(struct opm_scan *scan)
 {
-       struct auth_client *auth = scan->auth;
-       struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
        uint8_t sendbuf[9]; /* Size we're building */
        uint8_t *c = sendbuf;
 
@@ -328,13 +329,9 @@ static void
 socks5_connected(struct opm_scan *scan)
 {
        struct auth_client *auth = scan->auth;
-       struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
        uint8_t sendbuf[25]; /* Size we're building */
        uint8_t *c = sendbuf;
 
-       auth = scan->auth;
-       lookup = get_provider_data(auth, SELF_PID);
-
        /* Build the version header and socks request
         * version header (3 bytes): version, number of auth methods, auth type (0 for none)
         * connect req (3 bytes): version, command (1 = connect), reserved (0)
@@ -348,13 +345,11 @@ socks5_connected(struct opm_scan *scan)
                memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_addr.s_addr), 4); c += 4; /* Address */
                memcpy(c, &(((struct sockaddr_in *)&scan->listener->addr)->sin_port), 2); c += 2; /* Port */
                break;
-#ifdef RB_IPV6
        case AF_INET6:
                *(c++) = '\x04'; /* Address type (4 = IPv6) */
                memcpy(c, ((struct sockaddr_in6 *)&scan->listener->addr)->sin6_addr.s6_addr, 16); c += 16; /* Address */
                memcpy(c, &(((struct sockaddr_in6 *)&scan->listener->addr)->sin6_port), 2); c += 2; /* Port */
                break;
-#endif
        default:
                return;
        }
@@ -371,10 +366,7 @@ socks5_connected(struct opm_scan *scan)
 static void
 http_connect_connected(struct opm_scan *scan)
 {
-       struct auth_client *auth = scan->auth;
-       struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
        char sendbuf[128]; /* A bit bigger than we need but better safe than sorry */
-       char *c = sendbuf;
 
        /* Simple enough to build */
        snprintf(sendbuf, sizeof(sendbuf), "CONNECT %s:%hu HTTP/1.0\r\n\r\n", scan->listener->ip, scan->listener->port);
@@ -404,7 +396,6 @@ establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
 
        lrb_assert(lookup != NULL);
 
-#ifdef RB_IPV6
        if(GET_SS_FAMILY(&auth->c_addr) == AF_INET6)
        {
                if(proxy->proto == PROTO_SOCKS4)
@@ -416,7 +407,6 @@ establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
                listener = &listeners[LISTEN_IPV6];
        }
        else
-#endif
                listener = &listeners[LISTEN_IPV4];
 
        if(listener->F == NULL)
@@ -451,13 +441,11 @@ establish_connection(struct auth_client *auth, struct opm_proxy *proxy)
                rb_connect_tcp(scan->F,
                                (struct sockaddr *)&c_a,
                                (struct sockaddr *)&l_a,
-                               GET_SS_LEN(&l_a),
                                opm_connected, scan, opm_timeout);
        else
                rb_connect_tcp_ssl(scan->F,
                                (struct sockaddr *)&c_a,
                                (struct sockaddr *)&l_a,
-                               GET_SS_LEN(&l_a),
                                opm_connected, scan, opm_timeout);
 }
 
@@ -471,7 +459,7 @@ create_listener(const char *ip, uint16_t port)
        rb_fde_t *F;
        int opt = 1;
 
-       if(!rb_inet_pton_sock(ip, (struct sockaddr *)&addr))
+       if(!rb_inet_pton_sock(ip, &addr))
        {
                warn_opers(L_CRIT, "OPM: got a bad listener: %s:%hu", ip, port);
                exit(EX_PROVIDER_ERROR);
@@ -479,7 +467,6 @@ create_listener(const char *ip, uint16_t port)
 
        SET_SS_PORT(&addr, htons(port));
 
-#ifdef RB_IPV6
        if(GET_SS_FAMILY(&addr) == AF_INET6)
        {
                struct sockaddr_in6 *a1, *a2;
@@ -498,7 +485,6 @@ create_listener(const char *ip, uint16_t port)
                }
        }
        else
-#endif
        {
                struct sockaddr_in *a1, *a2;
 
@@ -560,6 +546,7 @@ create_listener(const char *ip, uint16_t port)
        RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
        {
                opm_cancel(auth);
+               /* auth is now invalid as we have no reference */
        }
 
        /* Copy data */
@@ -600,47 +587,40 @@ static void
 opm_initiate(struct auth_client *auth, uint32_t provider)
 {
        struct opm_lookup *lookup = get_provider_data(auth, SELF_PID);
-       uint32_t rdns_pid, ident_pid;
 
        lrb_assert(provider != SELF_PID);
        lrb_assert(!is_provider_done(auth, SELF_PID));
        lrb_assert(rb_dlink_list_length(&proxy_scanners) > 0);
 
-       if(lookup == NULL || lookup->in_progress)
+       if (lookup == NULL || lookup->in_progress) {
                /* Nothing to do */
                return;
-       else if((!get_provider_id("rdns", &rdns_pid) || is_provider_done(auth, rdns_pid)) &&
-               (!get_provider_id("ident", &ident_pid) || is_provider_done(auth, ident_pid)))
-               /* Don't start until ident and rdns are finished (or not loaded) */
-               return;
-       else
+       } else if (run_after_provider(auth, "rdns") && run_after_provider(auth,"ident")) {
+               /* Start scanning if ident and rdns are finished, or not loaded. */
                opm_scan(auth);
+       }
 }
 
 static bool
 opm_start(struct auth_client *auth)
 {
-       uint32_t rdns_pid, ident_pid;
-
        lrb_assert(get_provider_data(auth, SELF_PID) == NULL);
 
-       if(!opm_enable || rb_dlink_list_length(&proxy_scanners) == 0)
-       {
+       if (!opm_enable || rb_dlink_list_length(&proxy_scanners) == 0) {
                /* Nothing to do... */
-               notice_client(auth->cid, "*** Proxy scanning disabled, not scanning");
+               provider_done(auth, SELF_PID);
                return true;
        }
 
+       auth_client_ref(auth);
+
        set_provider_data(auth, SELF_PID, rb_malloc(sizeof(struct opm_lookup)));
 
-       if((!get_provider_id("rdns", &rdns_pid) || is_provider_done(auth, rdns_pid)) &&
-               (!get_provider_id("ident", &ident_pid) || is_provider_done(auth, ident_pid)))
-       {
-               /* Don't start until ident and rdns are finished (or not loaded) */
+       if (run_after_provider(auth, "rdns") && run_after_provider(auth, "ident")) {
+               /* Start scanning if ident and rdns are finished, or not loaded. */
                opm_scan(auth);
        }
 
-       set_provider_running(auth, SELF_PID);
        return true;
 }
 
@@ -668,6 +648,8 @@ opm_cancel(struct auth_client *auth)
                set_provider_data(auth, SELF_PID, NULL);
                set_provider_timeout_absolute(auth, SELF_PID, 0);
                provider_done(auth, SELF_PID);
+
+               auth_client_unref(auth);
        }
 }
 
@@ -681,6 +663,7 @@ opm_destroy(void)
        RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
        {
                opm_cancel(auth);
+               /* auth is now invalid as we have no reference */
        }
 }
 
@@ -723,6 +706,7 @@ set_opm_enabled(const char *key __unused, int parc __unused, const char **parv)
                        RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
                        {
                                opm_cancel(auth);
+                               /* auth is now invalid as we have no reference */
                        }
                }
        }
@@ -805,7 +789,8 @@ create_opm_scanner(const char *key __unused, int parc __unused, const char **par
        if(find_proxy_scanner(proxy->proto, proxy->port) != NULL)
        {
                warn_opers(L_CRIT, "OPM: got a duplicate scanner: %s (port %hu)", parv[0], proxy->port);
-               exit(EX_PROVIDER_ERROR);
+               rb_free(proxy);
+               return;
        }
 
        rb_dlinkAdd(proxy, &proxy->node, &proxy_scanners);
@@ -847,6 +832,8 @@ delete_opm_scanner(const char *key __unused, int parc __unused, const char **par
                if(lookup == NULL)
                        continue;
 
+               auth_client_ref(auth);
+
                RB_DLINK_FOREACH(ptr, lookup->scans.head)
                {
                        struct opm_scan *scan = ptr->data;
@@ -854,7 +841,7 @@ delete_opm_scanner(const char *key __unused, int parc __unused, const char **par
                        if(scan->proxy->port == proxy->port && scan->proxy->proto == proxy->proto)
                        {
                                /* Match */
-                               rb_dlinkFindDelete(scan, &lookup->scans);
+                               rb_dlinkDelete(&scan->node, &lookup->scans);
                                rb_free(scan);
 
                                if(rb_dlink_list_length(&lookup->scans) == 0)
@@ -863,9 +850,11 @@ delete_opm_scanner(const char *key __unused, int parc __unused, const char **par
                                break;
                        }
                }
+
+               auth_client_unref(auth);
        }
 
-       rb_dlinkFindDelete(proxy, &proxy_scanners);
+       rb_dlinkDelete(&proxy->node, &proxy_scanners);
        rb_free(proxy);
 
        if(rb_dlink_list_length(&proxy_scanners) == 0)
@@ -888,17 +877,31 @@ delete_opm_scanner_all(const char *key __unused, int parc __unused, const char *
        RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
        {
                opm_cancel(auth);
+               /* auth is now invalid as we have no reference */
        }
 
        opm_enable = false;
 }
 
+static void
+delete_opm_listener_all(const char *key __unused, int parc __unused, const char **parv __unused)
+{
+       if(listeners[LISTEN_IPV4].F != NULL)
+               rb_close(listeners[LISTEN_IPV4].F);
+
+       if(listeners[LISTEN_IPV6].F != NULL)
+               rb_close(listeners[LISTEN_IPV6].F);
+
+       memset(&listeners, 0, sizeof(listeners));
+}
+
 
 struct auth_opts_handler opm_options[] =
 {
        { "opm_timeout", 1, add_conf_opm_timeout },
        { "opm_enabled", 1, set_opm_enabled },
        { "opm_listener", 2, set_opm_listener },
+       { "opm_listener_del_all", 0, delete_opm_listener_all },
        { "opm_scanner", 2, create_opm_scanner },
        { "opm_scanner_del", 2, delete_opm_scanner },
        { "opm_scanner_del_all", 0, delete_opm_scanner_all },