]> jfr.im git - solanum.git/blobdiff - ircd/authd.c
authd: more minor cleanups
[solanum.git] / ircd / authd.c
index 5d4a7f8f9f18f1bce1f74439fe6ee43f8831dc45..861821aa667bc8bdc635a00660c4a44508f4a9b3 100644 (file)
 static int start_authd(void);
 static void parse_authd_reply(rb_helper * helper);
 static void restart_authd_cb(rb_helper * helper);
+static EVH timeout_dead_authd_clients;
 
 rb_helper *authd_helper;
 static char *authd_path;
 
-uint32_t cid = 1;
+uint32_t cid;
 static rb_dictionary *cid_clients;
+static struct ev_entry *timeout_ev;
 
 rb_dictionary *bl_stats;
 
@@ -71,9 +73,8 @@ start_authd(void)
                                 ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
                        if(access(fullpath, X_OK) == -1)
                        {
-                               ilog(L_MAIN,
-                                    "Unable to execute authd in %s or %s/bin",
-                                    ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
+                               ierror("Unable to execute authd in %s or %s/bin",
+                                       ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
                                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                                       "Unable to execute authd in %s or %s/bin",
                                                       ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath);
@@ -91,11 +92,14 @@ start_authd(void)
        if(bl_stats == NULL)
                bl_stats = rb_dictionary_create("blacklist statistics", strcasecmp);
 
+       if(timeout_ev == NULL)
+               timeout_ev = rb_event_addish("timeout_dead_authd_clients", timeout_dead_authd_clients, NULL, 1);
+
        authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb);
 
        if(authd_helper == NULL)
        {
-               ilog(L_MAIN, "Unable to start authd helper: %s", strerror(errno));
+               ierror("Unable to start authd helper: %s", strerror(errno));
                sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start authd helper: %s", strerror(errno));
                return 1;
        }
@@ -105,20 +109,54 @@ start_authd(void)
        return 0;
 }
 
+static inline uint32_t
+str_to_cid(const char *str)
+{
+       long lcid = strtol(str, NULL, 16);
+
+       if(lcid > UINT32_MAX || lcid <= 0)
+       {
+               iwarn("authd sent us back a bad client ID: %lx", lcid);
+               restart_authd();
+               return 0;
+       }
+
+       return (uint32_t)lcid;
+}
+
+static inline struct Client *
+cid_to_client(uint32_t cid, bool delete)
+{
+       struct Client *client_p;
+
+       if(delete)
+               client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid));
+       else
+               client_p = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(cid));
+
+       if(client_p == NULL)
+       {
+               iwarn("authd sent us back a bad client ID: %ux", cid);
+               restart_authd();
+               return NULL;
+       }
+
+       return client_p;
+}
+
 static void
 parse_authd_reply(rb_helper * helper)
 {
        ssize_t len;
        int parc;
-       char dnsBuf[READBUF_SIZE];
+       char authdBuf[READBUF_SIZE];
        char *parv[MAXPARA + 1];
-       long lcid;
-       char *id;
+       uint32_t cid;
        struct Client *client_p;
 
-       while((len = rb_helper_read(helper, dnsBuf, sizeof(dnsBuf))) > 0)
+       while((len = rb_helper_read(helper, authdBuf, sizeof(authdBuf))) > 0)
        {
-               parc = rb_string_to_array(dnsBuf, parv, MAXPARA+1);
+               parc = rb_string_to_array(authdBuf, parv, MAXPARA+1);
 
                switch (*parv[0])
                {
@@ -130,31 +168,14 @@ parse_authd_reply(rb_helper * helper)
                                return;
                        }
 
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
-                       {
-                               iwarn("authd sent us back a bad client ID");
-                               restart_authd();
+                       if((cid = str_to_cid(parv[1])) == 0)
                                return;
-                       }
 
                        /* cid to uid (retrieve and delete) */
-                       if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
-                       {
-                               iwarn("authd sent us back an unknown client ID");
-                               restart_authd();
-                               return;
-                       }
-
-                       if((client_p = find_id(id)) == NULL)
-                       {
-                               /* Client vanished... */
-                               rb_free(id);
+                       if((client_p = cid_to_client(cid, true)) == NULL)
                                return;
-                       }
-
-                       rb_free(id);
 
-                       authd_decide_client(client_p, parv[2], parv[3], true, '\0', NULL, NULL);
+                       authd_accept_client(client_p, parv[2], parv[3]);
                        break;
                case 'R':       /* Reject client */
                        if(parc != 7)
@@ -164,57 +185,28 @@ parse_authd_reply(rb_helper * helper)
                                return;
                        }
 
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
-                       {
-                               iwarn("authd sent us back a bad client ID");
-                               restart_authd();
+                       if((cid = str_to_cid(parv[1])) == 0)
                                return;
-                       }
 
                        /* cid to uid (retrieve and delete) */
-                       if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
-                       {
-                               iwarn("authd sent us back an unknown client ID");
-                               restart_authd();
+                       if((client_p = cid_to_client(cid, true)) == NULL)
                                return;
-                       }
-
-                       if((client_p = find_id(id)) == NULL)
-                       {
-                               /* Client vanished... */
-                               rb_free(id);
-                               return;
-                       }
 
-                       rb_free(id);
-
-                       authd_decide_client(client_p, parv[3], parv[4], false, toupper(*parv[2]), parv[5], parv[6]);
+                       authd_reject_client(client_p, parv[3], parv[4], toupper(*parv[2]), parv[5], parv[6]);
                        break;
                case 'N':       /* Notice to client */
-                       if(parv != 3)
+                       if(parc != 3)
                        {
                                iwarn("authd sent us a result with wrong number of arguments: got %d", parc);
                                restart_authd();
                                return;
                        }
-                       
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
-                       {
-                               iwarn("authd sent us back a bad client ID");
-                               restart_authd();
-                               return;
-                       }
 
-                       /* cid to uid */
-                       if((id = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
-                       {
-                               iwarn("authd sent us back an unknown client ID");
-                               restart_authd();
+                       if((cid = str_to_cid(parv[1])) == 0)
                                return;
-                       }
 
-                       if((client_p = find_id(id)) == NULL)
-                               /* Client vanished... we'll let the timeout code handle it */
+                       /* cid to uid */
+                       if((client_p = cid_to_client(cid, false)) == NULL)
                                return;
 
                        sendto_one_notice(client_p, ":%s", parv[2]);
@@ -222,7 +214,7 @@ parse_authd_reply(rb_helper * helper)
                case 'E':       /* DNS Result */
                        if(parc != 5)
                        {
-                               ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
+                               iwarn("authd sent a result with wrong number of arguments: got %d", parc);
                                restart_authd();
                                return;
                        }
@@ -231,7 +223,7 @@ parse_authd_reply(rb_helper * helper)
                case 'W':       /* Oper warning */
                        if(parc != 3)
                        {
-                               ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
+                               iwarn("authd sent a result with wrong number of arguments: got %d", parc);
                                restart_authd();
                                return;
                        }
@@ -240,18 +232,19 @@ parse_authd_reply(rb_helper * helper)
                        {
                        case 'D':       /* Debug */
                                sendto_realops_snomask(SNO_DEBUG, L_ALL, "authd debug: %s", parv[3]);
+                               idebug("authd: %s", parv[3]);
                                break;
                        case 'I':       /* Info */
                                sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd info: %s", parv[3]);
-                               inotice("authd info: %s", parv[3]);
+                               inotice("authd: %s", parv[3]);
                                break;
                        case 'W':       /* Warning */
                                sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd WARNING: %s", parv[3]);
-                               iwarn("authd warning: %s", parv[3]);
+                               iwarn("authd: %s", parv[3]);
                                break;
                        case 'C':       /* Critical (error) */
                                sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd CRITICAL: %s", parv[3]);
-                               ierror("authd critical: %s", parv[3]);
+                               ierror("authd: %s", parv[3]);
                                break;
                        default:        /* idk */
                                sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd sent us an unknown oper notice type (%s): %s", parv[2], parv[3]);
@@ -266,7 +259,7 @@ parse_authd_reply(rb_helper * helper)
                case 'Z':       /* End of stats reply */
                        if(parc < 3)
                        {
-                               ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
+                               iwarn("authd sent a result with wrong number of arguments: got %d", parc);
                                restart_authd();
                                return;
                        }
@@ -278,7 +271,7 @@ parse_authd_reply(rb_helper * helper)
                                /* parv[0] conveys status */
                                if(parc < 4)
                                {
-                                       ilog(L_MAIN, "authd sent a result with wrong number of arguments: got %d", parc);
+                                       iwarn("authd sent a result with wrong number of arguments: got %d", parc);
                                        restart_authd();
                                        return;
                                }
@@ -299,7 +292,7 @@ init_authd(void)
 {
        if(start_authd())
        {
-               ilog(L_MAIN, "Unable to start authd helper: %s", strerror(errno));
+               ierror("Unable to start authd helper: %s", strerror(errno));
                exit(0);
        }
 }
@@ -310,19 +303,31 @@ configure_authd(void)
        /* These will do for now */
        set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout);
        set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout);
-       set_authd_timeout("blacklist_timeout", ConfigFileEntry.connect_timeout);
+       set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout);
+       ident_check_enable(!ConfigFileEntry.disable_auth);
 }
 
 static void
 restart_authd_cb(rb_helper * helper)
 {
-       ilog(L_MAIN, "authd: restart_authd_cb called, authd died?");
+       rb_dictionary_iter iter;
+       struct Client *client_p;
+
+       iwarn("authd: restart_authd_cb called, authd died?");
        sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd: restart_authd_cb called, authd died?");
+
        if(helper != NULL)
        {
                rb_helper_close(helper);
                authd_helper = NULL;
        }
+
+       RB_DICTIONARY_FOREACH(client_p, &iter, cid_clients)
+       {
+               /* Abort any existing clients */
+               authd_abort_client(client_p);
+       }
+
        start_authd();
 }
 
@@ -371,35 +376,24 @@ authd_initiate_client(struct Client *client_p)
        uint16_t client_port, listen_port;
        uint32_t authd_cid;
 
-       if(client_p->preClient == NULL || client_p->preClient->authd_cid == 0)
+       if(client_p->preClient == NULL || client_p->preClient->authd_cid != 0)
                return;
 
        authd_cid = client_p->preClient->authd_cid = generate_cid();
 
        /* Collisions are extremely unlikely, so disregard the possibility */
-       rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), rb_strdup(client_p->id));
+       rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), client_p);
 
        /* Retrieve listener and client IP's */
        rb_inet_ntop_sock((struct sockaddr *)&client_p->preClient->lip, listen_ipaddr, sizeof(listen_ipaddr));
        rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip, client_ipaddr, sizeof(client_ipaddr));
 
        /* Retrieve listener and client ports */
-#ifdef RB_IPV6
-       if(GET_SS_FAMILY(&client_p->preClient->lip) == AF_INET6)
-               listen_port = ntohs(((struct sockaddr_in6 *)&client_p->preClient->lip)->sin6_port);
-       else
-#endif
-               listen_port = ntohs(((struct sockaddr_in *)&client_p->preClient->lip)->sin_port);
-
-#ifdef RB_IPV6
-       if(GET_SS_FAMILY(&client_p->localClient->ip) == AF_INET6)
-               client_port = ntohs(((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port);
-       else
-#endif
-               client_port = ntohs(((struct sockaddr_in *)&client_p->localClient->ip)->sin_port);
+       listen_port = ntohs(GET_SS_PORT(&client_p->preClient->lip));
+       client_port = ntohs(GET_SS_PORT(&client_p->localClient->ip));
 
-       /* FIXME timeout should be configurable */
-       client_p->preClient->authd_timeout = rb_current_time() + 45;
+       /* Add a bit of a fudge factor... */
+       client_p->preClient->authd_timeout = rb_current_time() + ConfigFileEntry.connect_timeout + 10;
 
        rb_helper_write(authd_helper, "C %x %s %hu %s %hu", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port);
 }
@@ -408,7 +402,7 @@ authd_initiate_client(struct Client *client_p)
  *
  * After this point authd no longer "owns" the client.
  */
-void
+static inline void
 authd_decide_client(struct Client *client_p, const char *ident, const char *host, bool accept, char cause, const char *data, const char *reason)
 {
        if(client_p->preClient == NULL || client_p->preClient->authd_cid == 0)
@@ -417,10 +411,10 @@ authd_decide_client(struct Client *client_p, const char *ident, const char *host
        if(*ident != '*')
        {
                rb_strlcpy(client_p->username, ident, sizeof(client_p->username));
-               ServerStats.is_abad++; /* s_auth used to do this, stay compatible */
+               ServerStats.is_asuc++;
        }
        else
-               ServerStats.is_asuc++;
+               ServerStats.is_abad++; /* s_auth used to do this, stay compatible */
 
        if(*host != '*')
                rb_strlcpy(client_p->host, host, sizeof(client_p->host));
@@ -431,7 +425,6 @@ authd_decide_client(struct Client *client_p, const char *ident, const char *host
        client_p->preClient->authd_reason = (reason == NULL ? NULL : rb_strdup(reason));
 
        rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid));
-
        client_p->preClient->authd_cid = 0;
 
        /*
@@ -446,10 +439,24 @@ authd_decide_client(struct Client *client_p, const char *ident, const char *host
        read_packet(client_p->localClient->F, client_p);
 }
 
+/* Convenience function to accept client */
+void
+authd_accept_client(struct Client *client_p, const char *ident, const char *host)
+{
+       authd_decide_client(client_p, ident, host, true, '\0', NULL, NULL);
+}
+
+/* Convenience function to reject client */
+void
+authd_reject_client(struct Client *client_p, const char *ident, const char *host, char cause, const char *data, const char *reason)
+{
+       authd_decide_client(client_p, ident, host, false, cause, data, reason);
+}
+
 void
 authd_abort_client(struct Client *client_p)
 {
-       if(client_p->preClient == NULL)
+       if(client_p == NULL || client_p->preClient == NULL)
                return;
 
        if(client_p->preClient->authd_cid == 0)
@@ -457,10 +464,27 @@ authd_abort_client(struct Client *client_p)
 
        rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid));
 
-       rb_helper_write(authd_helper, "E %x", client_p->preClient->authd_cid);
+       if(authd_helper != NULL)
+               rb_helper_write(authd_helper, "E %x", client_p->preClient->authd_cid);
+
+       /* XXX should we blindly allow like this? */
+       authd_accept_client(client_p, "*", "*");
        client_p->preClient->authd_cid = 0;
 }
 
+static void
+timeout_dead_authd_clients(void *notused __unused)
+{
+       rb_dictionary_iter iter;
+       struct Client *client_p;
+
+       RB_DICTIONARY_FOREACH(client_p, &iter, cid_clients)
+       {
+               if(client_p->preClient->authd_timeout < rb_current_time())
+                       authd_abort_client(client_p);
+       }
+}
+
 /* Turn a cause char (who rejected us) into the name of the provider */
 const char *
 get_provider_string(char cause)
@@ -484,7 +508,7 @@ add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_lis
 {
        rb_dlink_node *ptr;
        struct blacklist_stats *stats = rb_malloc(sizeof(struct blacklist_stats));
-       char filterbuf[BUFSIZE];
+       char filterbuf[BUFSIZE] = "*";
        size_t s = 0;
 
        /* Build a list of comma-separated values for authd.
@@ -539,8 +563,40 @@ del_blacklist_all(void)
 }
 
 /* Adjust an authd timeout value */
-void
+bool
 set_authd_timeout(const char *key, int timeout)
 {
+       if(timeout <= 0)
+               return false;
+
        rb_helper_write(authd_helper, "O %s %d", key, timeout);
+       return true;
+}
+
+/* Enable identd checks */
+void
+ident_check_enable(bool enabled)
+{
+       rb_helper_write(authd_helper, "O ident_enabled %d", enabled ? 1 : 0);
+}
+
+/* Create an OPM listener */
+void
+create_opm_listener(const char *ip, uint16_t port)
+{
+       rb_helper_write(authd_helper, "O opm_listener %s %hu", ip, port);
+}
+
+/* Disable all OPM scans */
+void
+opm_check_enable(bool enabled)
+{
+       rb_helper_write(authd_helper, "O opm_enable %d", enabled ? 1 : 0);
+}
+
+/* Create an OPM proxy scan */
+void
+create_opm_proxy_scan(const char *scan, uint16_t port)
+{
+       rb_helper_write(authd_helper, "O opm_scanner %s %hu", scan, port);
 }