]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conn.c
NoticeAuth: Fix test if IDENT reply has been invalid
[ngircd-alex.git] / src / ngircd / conn.c
index aa754eb482ae5c38f224adee20c9ac129751f19e..09f726ca2bf91016d54a8d2b2c7c10029943fa68 100644 (file)
@@ -65,6 +65,7 @@
 #include "ngircd.h"
 #include "array.h"
 #include "client.h"
+#include "class.h"
 #include "conf.h"
 #include "conn-ssl.h"
 #include "conn-zip.h"
@@ -81,8 +82,8 @@
 #define SERVER_WAIT (NONE - 1)
 
 #define MAX_COMMANDS 3
-#define MAX_COMMANDS_SERVER 10
-#define MAX_COMMANDS_SERVICE MAX_COMMANDS_SERVER
+#define MAX_COMMANDS_SERVER_MIN 10
+#define MAX_COMMANDS_SERVICE 10
 
 
 static bool Handle_Write PARAMS(( CONN_ID Idx ));
@@ -369,7 +370,7 @@ cb_clientserver_ssl(int sock, short what)
 
 
 /**
- * Initialite connecion module.
+ * Initialize connecion module.
  */
 GLOBAL void
 Conn_Init( void )
@@ -742,6 +743,9 @@ Conn_Handler(void)
                Check_Servers();
                Check_Connections();
 
+               /* Expire outdated class/list items */
+               Class_Expire();
+
                /* Look for non-empty read buffers ... */
                for (i = 0; i < Pool_Size; i++) {
                        if ((My_Connections[i].sock > NONE)
@@ -932,22 +936,25 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
        assert( Data != NULL );
        assert( Len > 0 );
 
-       c = Conn_GetClient(Idx);
-       assert( c != NULL);
-
-       /* Servers do get special write buffer limits, so they can generate
-        * all the messages that are required while peering. */
-       if (Client_Type(c) == CLIENT_SERVER)
-               writebuf_limit = WRITEBUFFER_SLINK_LEN;
-
        /* Is the socket still open? A previous call to Conn_Write()
         * may have closed the connection due to a fatal error.
         * In this case it is sufficient to return an error, as well. */
-       if( My_Connections[Idx].sock <= NONE ) {
+       if (My_Connections[Idx].sock <= NONE) {
                LogDebug("Skipped write on closed socket (connection %d).", Idx);
                return false;
        }
 
+       /* Make sure that there still exists a CLIENT structure associated
+        * with this connection and check if this is a server or not: */
+       c = Conn_GetClient(Idx);
+       if (c) {
+               /* Servers do get special write buffer limits, so they can
+                * generate all the messages that are required while peering. */
+               if (Client_Type(c) == CLIENT_SERVER)
+                       writebuf_limit = WRITEBUFFER_SLINK_LEN;
+       } else
+               LogDebug("Write on socket without client (connection %d)!?", Idx);
+
 #ifdef ZLIB
        if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
                /* Compressed link:
@@ -1010,7 +1017,7 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
 GLOBAL void
 Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
 {
-       /* Close connection. Open pipes of asyncronous resolver
+       /* Close connection. Open pipes of asynchronous resolver
         * sub-processes are closed down. */
 
        CLIENT *c;
@@ -1219,6 +1226,20 @@ Conn_SyncServerStruct(void)
 } /* SyncServerStruct */
 
 
+/**
+ * Get IP address string of a connection.
+ *
+ * @param Idx Connection index.
+ * @return Pointer to a global buffer containing the IP address as string.
+ */
+GLOBAL const char *
+Conn_GetIPAInfo(CONN_ID Idx)
+{
+       assert(Idx > NONE);
+       return ng_ipaddr_tostr(&My_Connections[Idx].addr);
+}
+
+
 /**
  * Send out data of write buffer; connect new sockets.
  *
@@ -1417,7 +1438,7 @@ New_Connection(int Sock)
                return -1;
        }
 
-       c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false);
+       c = Client_NewLocal(new_sock, NULL, CLIENT_UNKNOWN, false);
        if (!c) {
                Log(LOG_ALERT,
                    "Can't accept connection: can't create client structure!");
@@ -1568,7 +1589,7 @@ Read_Request( CONN_ID Idx )
                if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
                                (size_t) len)) {
                        Log(LOG_ERR,
-                           "Could not append recieved data to zip input buffer (connn %d): %d bytes!",
+                           "Could not append received data to zip input buffer (connection %d): %d bytes!",
                            Idx, len);
                        Conn_Close(Idx, "Receive buffer space exhausted", NULL,
                                   false);
@@ -1578,7 +1599,9 @@ Read_Request( CONN_ID Idx )
 #endif
        {
                if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
-                       Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
+                       Log(LOG_ERR,
+                           "Could not append received data to input buffer (connection %d): %d bytes!",
+                           Idx, len);
                        Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
                }
        }
@@ -1651,16 +1674,15 @@ Handle_Buffer(CONN_ID Idx)
 
        assert(c != NULL);
 
-       /* Servers do get special command limits, so they can process
-        * all the messages that are required while peering. */
+       /* Servers get special command limits that depend on the user count */
        switch (Client_Type(c)) {
            case CLIENT_SERVER:
-               /* Allow servers to send more commands in the first 10 secods
+               maxcmd = (int)(Client_UserCount() / 5)
+                      + MAX_COMMANDS_SERVER_MIN;
+               /* Allow servers to handle even more commands while peering
                 * to speed up server login and network synchronisation. */
-               if (starttime - Client_StartTime(c) < 10)
-                       maxcmd = MAX_COMMANDS_SERVER * 5;
-               else
-                       maxcmd = MAX_COMMANDS_SERVER;
+               if (Conn_LastPing(Idx) == 0)
+                       maxcmd *= 5;
                break;
            case CLIENT_SERVICE:
                maxcmd = MAX_COMMANDS_SERVICE; break;
@@ -1827,7 +1849,7 @@ Check_Connections(void)
                                   time(NULL) - Conf_PingTimeout) {
                                /* We need to send a PING ... */
                                LogDebug("Connection %d: sending PING ...", i);
-                               My_Connections[i].lastping = time(NULL);
+                               Conn_UpdatePing(i);
                                Conn_WriteStr(i, "PING :%s",
                                              Client_ID(Client_ThisServer()));
                        }
@@ -2152,6 +2174,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
        char *identptr;
 #ifdef IDENTAUTH
        char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
+       char *ptr;
 #else
        char readbuf[HOST_LEN + 1];
 #endif
@@ -2204,11 +2227,30 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
 #ifdef IDENTAUTH
                ++identptr;
                if (*identptr) {
-                       Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
-                       Client_SetUser(c, identptr, true);
-                       if (Conf_NoticeAuth)
+                       ptr = identptr;
+                       while (*ptr) {
+                               if ((*ptr < '0' || *ptr > '9') &&
+                                   (*ptr < 'A' || *ptr > 'Z') &&
+                                   (*ptr < 'a' || *ptr > 'z'))
+                                       break;
+                               ptr++;
+                       }
+                       if (*ptr) {
+                               /* Erroneous IDENT reply */
+                               Log(LOG_NOTICE,
+                                   "Got invalid IDENT reply for connection %d! Ignored.",
+                                   i);
+                       } else {
+                               Log(LOG_INFO,
+                                   "IDENT lookup for connection %d: \"%s\".",
+                                   i, identptr);
+                               Client_SetUser(c, identptr, true);
+                       }
+                       if (Conf_NoticeAuth) {
                                (void)Conn_WriteStr(i,
-                                       "NOTICE AUTH :*** Got ident response");
+                                       "NOTICE AUTH :*** Got %sident response",
+                                       *ptr ? "invalid " : "");
+                       }
                } else {
                        Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
                        if (Conf_NoticeAuth && Conf_Ident)
@@ -2216,6 +2258,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
                                        "NOTICE AUTH :*** No ident response");
                }
 #endif
+               Class_HandleServerBans(c);
        }
 #ifdef DEBUG
                else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );