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 ...
This commit is contained in:
parent
f1a4a4dc88
commit
162433398e
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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" */
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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! */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 },
|
||||
|
|
Loading…
Reference in New Issue