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_SERVICE 64 /* client is a service */
|
||||||
#define CLIENT_UNKNOWNSERVER 128 /* unregistered server connection */
|
#define CLIENT_UNKNOWNSERVER 128 /* unregistered server connection */
|
||||||
#define CLIENT_GOTPASS_2813 256 /* client did send PASS, RFC 2813 style */
|
#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
|
#define CLIENT_TYPE int
|
||||||
|
|
||||||
|
|
|
@ -353,9 +353,12 @@ Conf_Test( void )
|
||||||
printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
|
printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
|
||||||
printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
|
printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
|
||||||
printf(" CloakHost = %s\n", Conf_CloakHost);
|
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(" DNS = %s\n", yesno_to_str(Conf_DNS));
|
||||||
printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
|
printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
|
||||||
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
|
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
|
||||||
|
@ -641,6 +644,11 @@ Set_Defaults(bool InitServers)
|
||||||
Conf_SyslogFacility = 0;
|
Conf_SyslogFacility = 0;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STRICT_RFC
|
||||||
|
Conf_AuthPing = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
Set_Defaults_Optional();
|
Set_Defaults_Optional();
|
||||||
|
|
||||||
/* Initialize server configuration structures */
|
/* Initialize server configuration structures */
|
||||||
|
@ -1248,6 +1256,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
|
||||||
Conf_SyslogFacility);
|
Conf_SyslogFacility);
|
||||||
return;
|
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
|
#endif
|
||||||
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
|
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
|
||||||
NGIRCd_ConfFile, Line, Var);
|
NGIRCd_ConfFile, Line, Var);
|
||||||
|
|
|
@ -199,6 +199,13 @@ GLOBAL int Conf_MaxConnectionsIP;
|
||||||
/** Maximum length of a nick name */
|
/** Maximum length of a nick name */
|
||||||
GLOBAL unsigned int Conf_MaxNickLength;
|
GLOBAL unsigned int Conf_MaxNickLength;
|
||||||
|
|
||||||
|
#ifndef STRICT_RFC
|
||||||
|
|
||||||
|
/** Require "AUTH PING-PONG" on login */
|
||||||
|
GLOBAL bool Conf_AuthPing;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SYSLOG
|
#ifdef SYSLOG
|
||||||
|
|
||||||
/* Syslog "facility" */
|
/* Syslog "facility" */
|
||||||
|
|
|
@ -2283,6 +2283,25 @@ Conn_GetFromProc(int fd)
|
||||||
} /* Conn_GetFromProc */
|
} /* 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
|
#ifdef SSL_SUPPORT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -91,6 +91,9 @@ typedef struct _Connection
|
||||||
#ifdef SSL_SUPPORT
|
#ifdef SSL_SUPPORT
|
||||||
struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */
|
struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef STRICT_RFC
|
||||||
|
long auth_ping; /** PING response expected on login */
|
||||||
|
#endif
|
||||||
} CONNECTION;
|
} CONNECTION;
|
||||||
|
|
||||||
GLOBAL CONNECTION *My_Connections;
|
GLOBAL CONNECTION *My_Connections;
|
||||||
|
@ -132,6 +135,11 @@ GLOBAL long Conn_Count PARAMS((void));
|
||||||
GLOBAL long Conn_CountMax PARAMS((void));
|
GLOBAL long Conn_CountMax PARAMS((void));
|
||||||
GLOBAL long Conn_CountAccepted 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
|
#ifdef DEBUG
|
||||||
GLOBAL void Conn_DebugDump PARAMS((void));
|
GLOBAL void Conn_DebugDump PARAMS((void));
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -271,6 +271,17 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|
||||||
/* Register new nickname of this client */
|
/* Register new nickname of this client */
|
||||||
Client_SetID( target, Req->argv[0] );
|
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
|
/* If we received a valid USER command already then
|
||||||
* register the new client! */
|
* register the new client! */
|
||||||
if( Client_Type( Client ) == CLIENT_GOTUSER )
|
if( Client_Type( Client ) == CLIENT_GOTUSER )
|
||||||
|
@ -797,18 +808,32 @@ GLOBAL bool
|
||||||
IRC_PONG(CLIENT *Client, REQUEST *Req)
|
IRC_PONG(CLIENT *Client, REQUEST *Req)
|
||||||
{
|
{
|
||||||
CLIENT *target, *from;
|
CLIENT *target, *from;
|
||||||
|
CONN_ID conn;
|
||||||
|
#ifndef STRICT_RFC
|
||||||
|
long auth_ping;
|
||||||
|
#endif
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
assert(Client != NULL);
|
assert(Client != NULL);
|
||||||
assert(Req != NULL);
|
assert(Req != NULL);
|
||||||
|
|
||||||
/* Wrong number of arguments? */
|
/* Wrong number of arguments? */
|
||||||
if (Req->argc < 1)
|
if (Req->argc < 1) {
|
||||||
return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
|
if (Client_Type(Client) == CLIENT_USER)
|
||||||
Client_ID(Client));
|
return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
|
||||||
if (Req->argc > 2)
|
Client_ID(Client));
|
||||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
else
|
||||||
Client_ID(Client), Req->command);
|
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? */
|
/* Forward? */
|
||||||
if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
|
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
|
/* 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. */
|
* 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
|
#ifdef DEBUG
|
||||||
if (Client_Conn(Client) > NONE)
|
if (conn > NONE)
|
||||||
Log(LOG_DEBUG,
|
Log(LOG_DEBUG,
|
||||||
"Connection %d: received PONG. Lag: %ld seconds.",
|
"Connection %d: received PONG. Lag: %ld seconds.", conn,
|
||||||
Client_Conn(Client),
|
|
||||||
time(NULL) - Conn_LastPing(Client_Conn(Client)));
|
time(NULL) - Conn_LastPing(Client_Conn(Client)));
|
||||||
else
|
else
|
||||||
Log(LOG_DEBUG,
|
Log(LOG_DEBUG,
|
||||||
"Connection %d: received PONG.", Client_Conn(Client));
|
"Connection %d: received PONG.", conn);
|
||||||
#endif
|
#endif
|
||||||
return CONNECTED;
|
return CONNECTED;
|
||||||
} /* IRC_PONG */
|
} /* IRC_PONG */
|
||||||
|
@ -867,12 +912,25 @@ Hello_User(CLIENT * Client)
|
||||||
{
|
{
|
||||||
#ifdef PAM
|
#ifdef PAM
|
||||||
int pipefd[2], result;
|
int pipefd[2], result;
|
||||||
CONN_ID conn;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
#endif
|
||||||
|
CONN_ID conn;
|
||||||
|
|
||||||
assert(Client != NULL);
|
assert(Client != NULL);
|
||||||
conn = Client_Conn(Client);
|
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) {
|
if (!Conf_PAM) {
|
||||||
/* Don't do any PAM authentication at all, instead emulate
|
/* Don't do any PAM authentication at all, instead emulate
|
||||||
* the beahiour of the daemon compiled without PAM support:
|
* the beahiour of the daemon compiled without PAM support:
|
||||||
|
@ -903,8 +961,6 @@ Hello_User(CLIENT * Client)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
assert(Client != NULL);
|
|
||||||
|
|
||||||
/* Check global server password ... */
|
/* Check global server password ... */
|
||||||
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
|
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
|
||||||
/* Bad password! */
|
/* Bad password! */
|
||||||
|
|
|
@ -289,6 +289,8 @@ main( int argc, const char *argv[] )
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srandom(getpid());
|
||||||
|
|
||||||
/* Create protocol and server identification. The syntax
|
/* Create protocol and server identification. The syntax
|
||||||
* used by ngIRCd in PASS commands and the known "extended
|
* used by ngIRCd in PASS commands and the known "extended
|
||||||
* flags" are described in doc/Protocol.txt. */
|
* 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 },
|
{ "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||||
{ "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
|
{ "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 },
|
||||||
{ "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 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 },
|
{ "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||||
{ "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
|
{ "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 },
|
||||||
{ "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
|
{ "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 },
|
||||||
|
|
Loading…
Reference in New Issue