commit - 2981fe9eb707b340107b5131018805ee2a469950
commit + 7b6e26628a884a768863c753a3fdff00116c0eed
blob - 7e173e3c56bb12f1e43a0b492568d055a6e9b450
blob + a59923c579cff259a958b2f08f569cca1a856cff
--- ChangeLog
+++ ChangeLog
ngIRCd CVS-HEAD
+ - Fixed and enhanced the "penalty handling" of the server: commands that
+ require more resources block the client for a short time.
+ - Changed the internal time resolution to one second.
- New configuration variable "MaxConnectionsIP" to limit the number of
simultaneous connections from a single IP that the server will accept.
This configuration options lowers the risk of denial of service attacks
--
-$Id: ChangeLog,v 1.214 2003/11/05 21:41:01 alex Exp $
+$Id: ChangeLog,v 1.215 2003/11/05 23:24:48 alex Exp $
blob - 172784b660f4a650cd731b49e8ad9bcfa0e52fb3
blob + 591804b1910aafa565ade56f2a09e9b2ba47ad97
--- src/ngircd/conn-func.c
+++ src/ngircd/conn-func.c
#include "portab.h"
-static char UNUSED id[] = "$Id: conn-func.c,v 1.1 2002/12/30 17:14:28 alex Exp $";
+static char UNUSED id[] = "$Id: conn-func.c,v 1.2 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
+#include <log.h>
#include "conn.h"
assert( Idx > NONE );
assert( Seconds >= 0 );
-
+
t = time( NULL ) + Seconds;
if( t > My_Connections[Idx].delaytime ) My_Connections[Idx].delaytime = t;
} /* Conn_SetPenalty */
blob - 2c65f26e1f52204cffd87e16b60407d482326c6c
blob + 317171ea1ddb3e833f592238beb9fc0ac321c0f0
--- src/ngircd/conn.c
+++ src/ngircd/conn.c
#include "portab.h"
-static char UNUSED id[] = "$Id: conn.c,v 1.126 2003/11/05 21:41:02 alex Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.127 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" );
exit( 1 );
}
+#ifdef DEBUG
Log( LOG_DEBUG, "Allocated connection pool for %d items (%ld bytes).", Pool_Size, sizeof( CONNECTION ) * Pool_Size );
+#endif
/* zu Beginn haben wir keine Verbindungen */
FD_ZERO( &My_Listeners );
CONN_ID idx;
INT i;
+#ifdef DEBUG
Log( LOG_DEBUG, "Shutting down all connections ..." );
+#endif
#ifdef RENDEZVOUS
Rendezvous_UnregisterListeners( );
if( FD_ISSET( i, &My_Listeners ))
{
close( i );
+#ifdef DEBUG
Log( LOG_DEBUG, "Listening socket %d closed.", i );
+#endif
}
else if( FD_ISSET( i, &My_Connects ))
{
close( i );
+#ifdef DEBUG
Log( LOG_DEBUG, "Connection %d closed during creation (socket %d).", idx, i );
+#endif
}
else if( idx < Pool_Size )
{
if( FD_ISSET( i, &My_Sockets ) && FD_ISSET( i, &My_Listeners ))
{
close( i );
+#ifdef DEBUG
Log( LOG_DEBUG, "Listening socket %d closed.", i );
+#endif
}
}
} /* Conn_ExitListeners */
Check_Servers( );
Check_Connections( );
+ t = time( NULL );
+
/* noch volle Lese-Buffer suchen */
for( i = 0; i < Pool_Size; i++ )
{
- if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 ))
+ if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 ) &&
+ ( My_Connections[i].delaytime < t ))
{
/* Kann aus dem Buffer noch ein Befehl extrahiert werden? */
if( Handle_Buffer( i )) timeout = FALSE;
}
/* von welchen Sockets koennte gelesen werden? */
- t = time( NULL );
read_sockets = My_Sockets;
for( i = 0; i < Pool_Size; i++ )
{
/* Timeout initialisieren */
tv.tv_usec = 0;
- if( timeout ) tv.tv_sec = TIME_RES;
+ if( timeout ) tv.tv_sec = 1;
else tv.tv_sec = 0;
/* Auf Aktivitaet warten */
* In diesem Fall wird hier einfach ein Fehler geliefert. */
if( My_Connections[Idx].sock <= NONE )
{
+#ifdef DEBUG
Log( LOG_DEBUG, "Skipped write on closed socket (connection %d).", Idx );
+#endif
return FALSE;
}
return FALSE;
}
+#ifdef DEBUG
Log( LOG_DEBUG, "Connection %d with \"%s:%d\" established, now sendig PASS and SERVER ...", Idx, My_Connections[Idx].host, Conf_Server[Conf_GetServer( Idx )].port );
+#endif
/* PASS und SERVER verschicken */
Conn_WriteStr( Idx, "PASS %s %s", Conf_Server[Conf_GetServer( Idx )].pwd_out, NGIRCd_ProtoID );
/* Struktur umkopieren ... */
memcpy( ptr, My_Connections, sizeof( CONNECTION ) * Pool_Size );
+#ifdef DEBUG
Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [malloc()/memcpy()]", new_size, sizeof( CONNECTION ) * new_size );
+#endif
}
+#ifdef DEBUG
else Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [realloc()]", new_size, sizeof( CONNECTION ) * new_size );
+#endif
/* Adjust pointer to new block */
My_Connections = ptr;
{
/* die Connection wurde vermutlich (wegen eines
* Fehlers) bereits wieder abgebaut ... */
+#ifdef DEBUG
Log( LOG_DEBUG, "Socket2Index: can't get connection for socket %d!", Sock );
+#endif
return NONE;
}
else return idx;
result = FALSE;
do
{
+ /* Check penalty */
+ if( My_Connections[Idx].delaytime > time( NULL )) return result;
+
#ifdef USE_ZLIB
/* ggf. noch unkomprimiete Daten weiter entpacken */
if( My_Connections[Idx].options & CONN_ZIP )
memcpy( My_Connections[Idx].zip.rbuf, My_Connections[Idx].rbuf, My_Connections[Idx].rdatalen );
My_Connections[Idx].zip.rdatalen = My_Connections[Idx].rdatalen;
My_Connections[Idx].rdatalen = 0;
+#ifdef DEBUG
Log( LOG_DEBUG, "Moved already received data (%d bytes) to uncompression buffer.", My_Connections[Idx].zip.rdatalen );
+#endif
}
}
#endif
if( My_Connections[i].lastping < time( NULL ) - Conf_PongTimeout )
{
/* Timeout */
+#ifdef DEBUG
Log( LOG_DEBUG, "Connection %d: Ping timeout: %d seconds.", i, Conf_PongTimeout );
+#endif
Conn_Close( i, NULL, "Ping timeout", TRUE );
}
}
else if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout )
{
/* es muss ein PING gesendet werden */
+#ifdef DEBUG
Log( LOG_DEBUG, "Connection %d: sending PING ...", i );
+#endif
My_Connections[i].lastping = time( NULL );
Conn_WriteStr( i, "PING :%s", Client_ID( Client_ThisServer( )));
}
if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout )
{
/* Timeout */
+#ifdef DEBUG
Log( LOG_DEBUG, "Connection %d timed out ...", i );
+#endif
Conn_Close( i, NULL, "Timeout", FALSE );
}
}
Log( LOG_ALERT, "Can't establist server connection: connection limit reached (%d)!", Pool_Size );
return;
}
+#ifdef DEBUG
Log( LOG_DEBUG, "Preparing connection %d for \"%s\" ...", idx, Conf_Server[i].host );
+#endif
/* Verbindungs-Struktur initialisieren */
Init_Conn_Struct( idx );
FD_SET( new_sock, &My_Connects );
if( new_sock > Conn_MaxFD ) Conn_MaxFD = new_sock;
+#ifdef DEBUG
Log( LOG_DEBUG, "Registered new connection %d on socket %d.", Idx, My_Connections[Idx].sock );
+#endif
} /* New_Server */
/* Opsa! Keine passende Connection gefunden!? Vermutlich
* wurde sie schon wieder geschlossen. */
close( r_fd );
+#ifdef DEBUG
Log( LOG_DEBUG, "Resolver: Got result for unknown connection!?" );
+#endif
return;
}
+#ifdef DEBUG
Log( LOG_DEBUG, "Resolver: %s is \"%s\".", My_Connections[i].host, result );
+#endif
/* Aufraeumen */
close( My_Connections[i].res_stat->pipe[0] );
blob - 57f82b69ad51489d0af0e2c21e54e65c29e26b1a
blob + e4865e1a762a6d9504ade6a9a288754712fff511
--- src/ngircd/defines.h
+++ src/ngircd/defines.h
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
- * $Id: defines.h,v 1.42 2003/02/23 12:03:39 alex Exp $
+ * $Id: defines.h,v 1.43 2003/11/05 23:24:48 alex Exp $
*
* Global defines of ngIRCd.
*/
#define NONE -1
-#define TIME_RES 2 /* Zeit-Aufloesung des Servers in Sekunden */
-
#define FNAME_LEN 256 /* max. Laenge eines Dateinamen */
#define LINE_LEN 256 /* max. Laenge einer Konfigurationszeile */
blob - 3bc6904f5dc1efe3d5d9ee60cc9a2929ad2e8cf9
blob + e4d1c7fcc3fbcd93dd4dacff65aac44242b737dc
--- src/ngircd/irc-info.c
+++ src/ngircd/irc-info.c
#include "portab.h"
-static char UNUSED id[] = "$Id: irc-info.c,v 1.17 2003/06/06 20:46:11 alex Exp $";
+static char UNUSED id[] = "$Id: irc-info.c,v 1.18 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC2_MSG, Client_ID( prefix ), Conf_ServerAdmin2 )) return DISCONNECTED;
if( ! IRC_WriteStrClient( Client, RPL_ADMINEMAIL_MSG, Client_ID( prefix ), Conf_ServerAdminMail )) return DISCONNECTED;
+ IRC_SetPenalty( Client, 1 );
return CONNECTED;
} /* IRC_ADMIN */
}
c = Client_Next( c );
}
-
+
+ IRC_SetPenalty( target, 1 );
return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
} /* IRC_LINKS */
IRC_Send_LUSERS( target );
+ IRC_SetPenalty( target, 1 );
return CONNECTED;
} /* IRC_LUSERS */
}
}
+ IRC_SetPenalty( from, 3 );
return IRC_Show_MOTD( from );
} /* IRC_MOTD */
if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED;
}
+ IRC_SetPenalty( from, 1 );
return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" );
} /* IRC_NAMES */
break;
}
+ IRC_SetPenalty( from, 2 );
return IRC_WriteStrClient( from, RPL_ENDOFSTATS_MSG, Client_ID( from ), query );
} /* IRC_STATS */
}
/* mit Versionsinfo antworten */
+ IRC_SetPenalty( Client, 1 );
#ifdef CVSDATE
strlcpy( ver, CVSDATE, sizeof( ver ));
strncpy( ver + 4, ver + 5, 2 );
blob - 280923a798856413fef87fa036aeaa20125fe3b2
blob + b4b489f5a8dc0f67e189cc2c21371d977e956eaf
--- src/ngircd/irc-login.c
+++ src/ngircd/irc-login.c
#include "portab.h"
-static char UNUSED id[] = "$Id: irc-login.c,v 1.34 2003/03/31 15:54:21 alex Exp $";
+static char UNUSED id[] = "$Id: irc-login.c,v 1.35 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
/* neuen Client-Nick speichern */
Client_SetID( target, Req->argv[0] );
+ IRC_SetPenalty( target, 2 );
}
return CONNECTED;
if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED;
if( ! IRC_Show_MOTD( Client )) return DISCONNECTED;
+ /* Suspend the client for a second ... */
+ IRC_SetPenalty( Client, 1 );
+
return CONNECTED;
} /* Hello_User */
blob - cf6354171df7a454dbd704163b0a146e90673729
blob + 5586989ca75e8cca7895c2252effbf86bf3c0610
--- src/ngircd/irc-mode.c
+++ src/ngircd/irc-mode.c
#include "portab.h"
-static char UNUSED id[] = "$Id: irc-mode.c,v 1.31 2003/01/21 21:04:16 alex Exp $";
+static char UNUSED id[] = "$Id: irc-mode.c,v 1.32 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
}
Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target ));
}
-
+
+ IRC_SetPenalty( Client, 1 );
return ok;
} /* Client_Mode */
}
}
+ IRC_SetPenalty( Client, 1 );
return CONNECTED;
} /* Channel_Mode */
blob - b8a5e28d6eaa1095f5291e6c478a09c539638a95
blob + 9127ef11e2ab1c47ee8532ca4124d827af4b1bf3
--- src/ngircd/irc-write.c
+++ src/ngircd/irc-write.c
#include "portab.h"
-static char UNUSED id[] = "$Id: irc-write.c,v 1.14 2002/12/30 17:15:42 alex Exp $";
+static char UNUSED id[] = "$Id: irc-write.c,v 1.15 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
} /* IRC_WriteStrRelatedPrefix */
+GLOBAL VOID
+IRC_SetPenalty( CLIENT *Client, INT Seconds )
+{
+ CONN_ID c;
+
+ assert( Client != NULL );
+ assert( Seconds > 0 );
+
+ if( Client_Type( Client ) == CLIENT_SERVER ) return;
+
+ c = Client_Conn( Client );
+ if( c > NONE ) Conn_SetPenalty( c, Seconds );
+} /* IRC_SetPenalty */
+
+
LOCAL CHAR *
Get_Prefix( CLIENT *Target, CLIENT *Client )
{
blob - 7d70d696c1b520a9a80b1ecc87717ac0b18f7c43
blob + 41e2f2e7359e2316ee31f6358e2c1d2a06362058
--- src/ngircd/irc-write.h
+++ src/ngircd/irc-write.h
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
- * $Id: irc-write.h,v 1.5 2002/12/12 12:23:43 alex Exp $
+ * $Id: irc-write.h,v 1.6 2003/11/05 23:24:48 alex Exp $
*
* Sending IRC commands over the network (header)
*/
#define __irc_write_h__
-GLOBAL BOOLEAN IRC_WriteStrClient PARAMS((CLIENT *Client, CHAR *Format, ... ));
-GLOBAL BOOLEAN IRC_WriteStrClientPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... ));
+GLOBAL BOOLEAN IRC_WriteStrClient PARAMS(( CLIENT *Client, CHAR *Format, ... ));
+GLOBAL BOOLEAN IRC_WriteStrClientPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... ));
-GLOBAL BOOLEAN IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... ));
-GLOBAL BOOLEAN IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... ));
+GLOBAL BOOLEAN IRC_WriteStrChannel PARAMS(( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... ));
+GLOBAL BOOLEAN IRC_WriteStrChannelPrefix PARAMS(( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... ));
-GLOBAL VOID IRC_WriteStrServers PARAMS((CLIENT *ExceptOf, CHAR *Format, ... ));
-GLOBAL VOID IRC_WriteStrServersPrefix PARAMS((CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... ));
-GLOBAL VOID IRC_WriteStrServersPrefixFlag PARAMS((CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... ));
+GLOBAL VOID IRC_WriteStrServers PARAMS(( CLIENT *ExceptOf, CHAR *Format, ... ));
+GLOBAL VOID IRC_WriteStrServersPrefix PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... ));
+GLOBAL VOID IRC_WriteStrServersPrefixFlag PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... ));
-GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... ));
+GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... ));
+GLOBAL VOID IRC_SetPenalty PARAMS(( CLIENT *Client, INT Seconds ));
+
#endif
blob - 1c1212af38d83c06cff1ecb59a3b6f4fc63e5f2e
blob + eb32afdd134a9988fc17a0fe7282c4d4b82236ef
--- src/ngircd/irc.c
+++ src/ngircd/irc.c
#include "portab.h"
-static char UNUSED id[] = "$Id: irc.c,v 1.121 2003/04/29 12:19:20 alex Exp $";
+static char UNUSED id[] = "$Id: irc.c,v 1.122 2003/11/05 23:24:48 alex Exp $";
#include "imp.h"
#include <assert.h>
/* Some information about us */
if( ! IRC_WriteStrClient( from, RPL_TRACESERVER_MSG, Client_ID( from ), Conf_ServerName, Client_Mask( Client_ThisServer( )), Option_String( Client_Conn( Client )))) return DISCONNECTED;
+ IRC_SetPenalty( Client, 3 );
return IRC_WriteStrClient( from, RPL_TRACEEND_MSG, Client_ID( from ), Conf_ServerName, PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel );
} /* IRC_TRACE */
if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
cmd++;
}
+
+ IRC_SetPenalty( Client, 2 );
return CONNECTED;
} /* IRC_HELP */