]> jfr.im git - solanum.git/blobdiff - ircd/authd.c
authd: properly abort clients who timeout or when the helper restarts
[solanum.git] / ircd / authd.c
index d2514deb08bd38edbef06559633517aafe8df223..7a088c075e9aa8be907fdff6f2902bdd3764492a 100644 (file)
@@ -48,7 +48,7 @@ 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;
 
@@ -73,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);
@@ -100,7 +99,7 @@ start_authd(void)
 
        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;
        }
@@ -115,15 +114,15 @@ 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])
                {
@@ -135,30 +134,23 @@ parse_authd_reply(rb_helper * helper)
                                return;
                        }
 
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
+                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0)
                        {
-                               iwarn("authd sent us back a bad client ID");
+                               iwarn("authd sent us back a bad client ID: %ld", lcid);
                                restart_authd();
                                return;
                        }
 
+                       cid = (uint32_t)lcid;
+
                        /* cid to uid (retrieve and delete) */
-                       if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
+                       if((client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL)
                        {
-                               iwarn("authd sent us back an unknown client ID");
+                               iwarn("authd sent us back an unknown client ID %x", cid);
                                restart_authd();
                                return;
                        }
 
-                       if((client_p = find_id(id)) == NULL)
-                       {
-                               /* Client vanished... */
-                               rb_free(id);
-                               return;
-                       }
-
-                       rb_free(id);
-
                        authd_decide_client(client_p, parv[2], parv[3], true, '\0', NULL, NULL);
                        break;
                case 'R':       /* Reject client */
@@ -169,30 +161,23 @@ parse_authd_reply(rb_helper * helper)
                                return;
                        }
 
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
+                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0)
                        {
-                               iwarn("authd sent us back a bad client ID");
+                               iwarn("authd sent us back a bad client ID %ld", lcid);
                                restart_authd();
                                return;
                        }
 
+                       cid = (uint32_t)lcid;
+
                        /* cid to uid (retrieve and delete) */
-                       if((id = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
+                       if((client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL)
                        {
-                               iwarn("authd sent us back an unknown client ID");
+                               iwarn("authd sent us back an unknown client ID %x", cid);
                                restart_authd();
                                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]);
                        break;
                case 'N':       /* Notice to client */
@@ -202,32 +187,30 @@ parse_authd_reply(rb_helper * helper)
                                restart_authd();
                                return;
                        }
-                       
-                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX)
+
+                       if((lcid = strtol(parv[1], NULL, 16)) > UINT32_MAX || lcid < 0)
                        {
-                               iwarn("authd sent us back a bad client ID");
+                               iwarn("authd sent us back a bad client ID %ld", lcid);
                                restart_authd();
                                return;
                        }
 
+                       cid = (uint32_t)lcid;
+
                        /* cid to uid */
-                       if((id = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER((uint32_t)lcid))) == NULL)
+                       if((client_p = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(cid))) == NULL)
                        {
-                               iwarn("authd sent us back an unknown client ID");
+                               iwarn("authd sent us back an unknown client ID %x", cid);
                                restart_authd();
                                return;
                        }
 
-                       if((client_p = find_id(id)) == NULL)
-                               /* Client vanished... we'll let the timeout code handle it */
-                               return;
-
                        sendto_one_notice(client_p, ":%s", parv[2]);
                        break;
                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;
                        }
@@ -236,7 +219,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;
                        }
@@ -245,18 +228,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]);
@@ -271,7 +255,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;
                        }
@@ -283,7 +267,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;
                                }
@@ -304,7 +288,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);
        }
 }
@@ -315,20 +299,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);
-       ident_check_enable(ConfigFileEntry.disable_auth);       
+       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();
 }
 
@@ -377,35 +372,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));
 
        /* Add a bit of a fudge factor... */
-       client_p->preClient->authd_timeout = rb_current_time() + ConfigFileEntry.connect_timeout + 5;
+       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);
 }
@@ -455,7 +439,7 @@ authd_decide_client(struct Client *client_p, const char *ident, const char *host
 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)
@@ -463,7 +447,12 @@ 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_decide_client(client_p, parv[2], parv[3], true, '\0', NULL, NULL);
+
        client_p->preClient->authd_cid = 0;
 }
 
@@ -471,26 +460,12 @@ static void
 timeout_dead_authd_clients(void *notused __unused)
 {
        rb_dictionary_iter iter;
-       char *id;
+       struct Client *client_p;
 
-       RB_DICTIONARY_FOREACH(id, &iter, cid_clients)
+       RB_DICTIONARY_FOREACH(client_p, &iter, cid_clients)
        {
-               struct Client *client_p;
-               if((client_p = find_id(id)) == NULL)
-               {
-                       /* This shouldn't happen... but just in case... */
-                       rb_helper_write(authd_helper, "E %x", RB_POINTER_TO_UINT(iter.cur->key));
-                       rb_free(id);
-                       rb_dictionary_delete(cid_clients, iter.cur->key);
-                       continue;
-               }
-
                if(client_p->preClient->authd_timeout < rb_current_time())
-               {
-                       rb_helper_write(authd_helper, "E %x", client_p->preClient->authd_cid);
-                       rb_free(id);
-                       rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->authd_cid));
-               }
+                       authd_abort_client(client_p);
        }
 }
 
@@ -517,7 +492,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.