repo: ngircd action: commit revision: path_from: revision_from: 162433398e320c45f3c8a523814518aa6b78372e: path_to: revision_to:
commit 162433398e320c45f3c8a523814518aa6b78372e Author: Alexander BartonDate: Sun Mar 27 19:33:48 2011 +0200 New configuration option "RequireAuthPing": PING-PONG on login When enabled, this configuration option lets ngIRCd send a PING with an numeric "token" to clients logging in; and it will not become registered in the network until the client responds with the correct PONG. This is used by QuakeNet for example (ircu/snircd), and looks like this: NICK nick :irc.example.net PING :1858979527 USER user . . :real name PONG 1858979527 :irc.example.net 001 nick :Welcome to the Internet Relay Network ... diff --git a/src/ngircd/client.h b/src/ngircd/client.h
--- a/src/ngircd/client.h +++ b/src/ngircd/client.h @@ -26,6 +26,9 @@ #define CLIENT_SERVICE 64 /* client is a service */ #define CLIENT_UNKNOWNSERVER 128 /* unregistered server connection */ #define CLIENT_GOTPASS_2813 256 /* client did send PASS, RFC 2813 style */ +#ifndef STRICT_RFC +# define CLIENT_WAITAUTHPING 512 /* waiting for AUTH PONG from client */ +#endif #define CLIENT_TYPE int diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c
--- a/src/ngircd/conf.c
+++ b/src/ngircd/conf.c
@@ -353,9 +353,12 @@ Conf_Test( void )
printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
printf(" CloakHost = %s\n", Conf_CloakHost);
- printf(" CloakUserToNick = %s\n\n", yesno_to_str(Conf_CloakUserToNick));
+ printf(" CloakUserToNick = %s\n", yesno_to_str(Conf_CloakUserToNick));
+#ifndef STRICT_RFC
+ printf(" RequireAuthPing = %s\n", yesno_to_str(Conf_AuthPing));
+#endif
- puts("[FEATURES]");
+ printf("\n[FEATURES]\n");
printf(" DNS = %s\n", yesno_to_str(Conf_DNS));
printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
@@ -641,6 +644,11 @@ Set_Defaults(bool InitServers)
Conf_SyslogFacility = 0;
#endif
#endif
+
+#ifndef STRICT_RFC
+ Conf_AuthPing = false;
+#endif
+
Set_Defaults_Optional();
/* Initialize server configuration structures */
@@ -1248,6 +1256,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
Conf_SyslogFacility);
return;
}
+#endif
+#ifndef STRICT_RFC
+ if (strcasecmp(Var, "RequireAuthPing") == 0 ) {
+ /* Require new clients to do an "autheticatin PING-PONG" */
+ Conf_AuthPing = Check_ArgIsTrue(Arg);
+ return;
+ }
#endif
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var);
diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h
--- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -199,6 +199,13 @@ GLOBAL int Conf_MaxConnectionsIP; /** Maximum length of a nick name */ GLOBAL unsigned int Conf_MaxNickLength; +#ifndef STRICT_RFC + +/** Require "AUTH PING-PONG" on login */ +GLOBAL bool Conf_AuthPing; + +#endif + #ifdef SYSLOG /* Syslog "facility" */ diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -2283,6 +2283,25 @@ Conn_GetFromProc(int fd)
} /* Conn_GetFromProc */
+#ifndef STRICT_RFC
+
+GLOBAL long
+Conn_GetAuthPing(CONN_ID Idx)
+{
+ assert (Idx != NONE);
+ return My_Connections[Idx].auth_ping;
+} /* Conn_GetAuthPing */
+
+GLOBAL void
+Conn_SetAuthPing(CONN_ID Idx, long ID)
+{
+ assert (Idx != NONE);
+ My_Connections[Idx].auth_ping = ID;
+} /* Conn_SetAuthPing */
+
+#endif
+
+
#ifdef SSL_SUPPORT
/**
diff --git a/src/ngircd/conn.h b/src/ngircd/conn.h
--- a/src/ngircd/conn.h +++ b/src/ngircd/conn.h @@ -91,6 +91,9 @@ typedef struct _Connection #ifdef SSL_SUPPORT struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */ #endif +#ifndef STRICT_RFC + long auth_ping; /** PING response expected on login */ +#endif } CONNECTION; GLOBAL CONNECTION *My_Connections; @@ -132,6 +135,11 @@ GLOBAL long Conn_Count PARAMS((void)); GLOBAL long Conn_CountMax PARAMS((void)); GLOBAL long Conn_CountAccepted PARAMS((void)); +#ifndef STRICT_RFC +GLOBAL long Conn_GetAuthPing PARAMS((CONN_ID Idx)); +GLOBAL void Conn_SetAuthPing PARAMS((CONN_ID Idx, long ID)); +#endif + #ifdef DEBUG GLOBAL void Conn_DebugDump PARAMS((void)); #endif diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c
--- a/src/ngircd/irc-login.c
+++ b/src/ngircd/irc-login.c
@@ -271,6 +271,17 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
/* Register new nickname of this client */
Client_SetID( target, Req->argv[0] );
+#ifndef STRICT_RFC
+ if (Conf_AuthPing) {
+ Conn_SetAuthPing(Client_Conn(Client), random());
+ IRC_WriteStrClient(Client, "PING :%ld",
+ Conn_GetAuthPing(Client_Conn(Client)));
+ LogDebug("Connection %d: sent AUTH PING %ld ...",
+ Client_Conn(Client),
+ Conn_GetAuthPing(Client_Conn(Client)));
+ }
+#endif
+
/* If we received a valid USER command already then
* register the new client! */
if( Client_Type( Client ) == CLIENT_GOTUSER )
@@ -797,18 +808,32 @@ GLOBAL bool
IRC_PONG(CLIENT *Client, REQUEST *Req)
{
CLIENT *target, *from;
+ CONN_ID conn;
+#ifndef STRICT_RFC
+ long auth_ping;
+#endif
char *s;
assert(Client != NULL);
assert(Req != NULL);
/* Wrong number of arguments? */
- if (Req->argc < 1)
- return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
- Client_ID(Client));
- if (Req->argc > 2)
- return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
- Client_ID(Client), Req->command);
+ if (Req->argc < 1) {
+ if (Client_Type(Client) == CLIENT_USER)
+ return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
+ Client_ID(Client));
+ else
+ return CONNECTED;
+ }
+ if (Req->argc > 2) {
+ if (Client_Type(Client) == CLIENT_USER)
+ return IRC_WriteStrClient(Client,
+ ERR_NEEDMOREPARAMS_MSG,
+ Client_ID(Client),
+ Req->command);
+ else
+ return CONNECTED;
+ }
/* Forward? */
if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
@@ -837,15 +862,35 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
/* The connection timestamp has already been updated when the data has
* been read from so socket, so we don't need to update it here. */
+
+ conn = Client_Conn(Client);
+
+#ifndef STRICT_RFC
+ /* Check authentication PING-PONG ... */
+ auth_ping = Conn_GetAuthPing(conn);
+ if (auth_ping) {
+ LogDebug("AUTH PONG: waiting for token \"%ld\", got \"%s\" ...",
+ auth_ping, Req->argv[0]);
+ if (auth_ping == atoi(Req->argv[0])) {
+ Conn_SetAuthPing(conn, 0);
+ if (Client_Type(Client) == CLIENT_WAITAUTHPING)
+ Hello_User(Client);
+ } else
+ if (!IRC_WriteStrClient(Client,
+ "To connect, type /QUOTE PONG %ld",
+ auth_ping))
+ return DISCONNECTED;
+ }
+#endif
+
#ifdef DEBUG
- if (Client_Conn(Client) > NONE)
+ if (conn > NONE)
Log(LOG_DEBUG,
- "Connection %d: received PONG. Lag: %ld seconds.",
- Client_Conn(Client),
+ "Connection %d: received PONG. Lag: %ld seconds.", conn,
time(NULL) - Conn_LastPing(Client_Conn(Client)));
else
Log(LOG_DEBUG,
- "Connection %d: received PONG.", Client_Conn(Client));
+ "Connection %d: received PONG.", conn);
#endif
return CONNECTED;
} /* IRC_PONG */
@@ -867,12 +912,25 @@ Hello_User(CLIENT * Client)
{
#ifdef PAM
int pipefd[2], result;
- CONN_ID conn;
pid_t pid;
+#endif
+ CONN_ID conn;
assert(Client != NULL);
conn = Client_Conn(Client);
+#ifndef STRICT_RFC
+ if (Conf_AuthPing) {
+ /* Did we receive the "auth PONG" already? */
+ if (Conn_GetAuthPing(conn)) {
+ Client_SetType(Client, CLIENT_WAITAUTHPING);
+ LogDebug("Connection %d: Waiting for AUTH PONG ...", conn);
+ return CONNECTED;
+ }
+ }
+#endif
+
+#ifdef PAM
if (!Conf_PAM) {
/* Don't do any PAM authentication at all, instead emulate
* the beahiour of the daemon compiled without PAM support:
@@ -903,8 +961,6 @@ Hello_User(CLIENT * Client)
exit(0);
}
#else
- assert(Client != NULL);
-
/* Check global server password ... */
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
/* Bad password! */
diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c
--- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -289,6 +289,8 @@ main( int argc, const char *argv[] ) exit(1); } + srandom(getpid()); + /* Create protocol and server identification. The syntax * used by ngIRCd in PASS commands and the known "extended * flags" are described in doc/Protocol.txt. */ diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c
--- a/src/ngircd/parse.c
+++ b/src/ngircd/parse.c
@@ -82,7 +82,7 @@ static COMMAND My_Commands[] =
{ "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
{ "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
- { "PONG", IRC_PONG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
+ { "PONG", IRC_PONG, 0xFFFF, 0, 0, 0 },
{ "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
{ "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
-----END OF PAGE-----