]> arthur.barton.de Git - ngircd-alex.git/commitdiff
New configuration option "RequireAuthPing": PING-PONG on login
authorAlexander Barton <alex@barton.de>
Sun, 27 Mar 2011 17:33:48 +0000 (19:33 +0200)
committerAlexander Barton <alex@barton.de>
Sun, 27 Mar 2011 17:33:48 +0000 (19:33 +0200)
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
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/conn.c
src/ngircd/conn.h
src/ngircd/irc-login.c
src/ngircd/ngircd.c
src/ngircd/parse.c

index ff4ff2ffa6285a2af8937b6df5bc1049edbe3bdc..fecf5d9798d97a03d5d12482a9becbfe0764b16f 100644 (file)
@@ -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
 
index 32461f3550ffb127332754e44ae0033bfbd73c86..452f744f0d103d906b8bfe905176848f687f2de8 100644 (file)
@@ -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);
index 305ccaa1ff8c36540253f6283b43266d16fc043f..a183fcec56a0b010cb35b4bba134079f74b177de 100644 (file)
@@ -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" */
index 63093c25f64462b1468cc99bac2e4b7cea22e5a5..275215d6745ed9288c504c636014a11a1d8f175c 100644 (file)
@@ -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
 
 /**
index 4228c9e41b933a3de5bd60e2638a78ecc895fc39..c813729f9331e1c3897ed32f44505f851f782604 100644 (file)
@@ -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
index 92d54ab15e42ad64d2e7d05bd605bccc1cd7f734..2e99d66eeade7dfa36c25b6dd36f88a9c94f1c1e 100644 (file)
@@ -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! */
index 4b49ec6cce56ba599616dce9049b1b15f99fad39..74a998800f364376a87efb290cd2d0dc030a2ab4 100644 (file)
@@ -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. */
index 31f048cf673408f08737647d66b8aba0bc807612..8f5e6019694a53807d023b4df9010c281ad10d0b 100644 (file)
@@ -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 },