Module: ngircd.git Branch: master Commit: 162433398e320c45f3c8a523814518aa6b78372e URL: http://ngircd.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git&a=commit;h=16243...
Author: Alexander Barton alex@barton.de Date: 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 ...
---
src/ngircd/client.h | 3 ++ src/ngircd/conf.c | 19 ++++++++++- src/ngircd/conf.h | 7 ++++ src/ngircd/conn.c | 19 +++++++++++ src/ngircd/conn.h | 8 +++++ src/ngircd/irc-login.c | 82 ++++++++++++++++++++++++++++++++++++++++------- src/ngircd/ngircd.c | 2 + src/ngircd/parse.c | 2 +- 8 files changed, 126 insertions(+), 16 deletions(-)
diff --git a/src/ngircd/client.h b/src/ngircd/client.h index ff4ff2f..fecf5d9 100644 --- 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 index 32461f3..452f744 100644 --- 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 */ @@ -1249,6 +1257,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) 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); } /* Handle_GLOBAL */ diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index 305ccaa..a183fce 100644 --- 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 index 63093c2..275215d 100644 --- 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 index 4228c9e..c813729 100644 --- 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 index 92d54ab..2e99d66 100644 --- 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 index 4b49ec6..74a9988 100644 --- 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 index 31f048c..8f5e601 100644 --- 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 },
ngircd-commits@lists.barton.de