Merge branch 'AuthPing'

* AuthPing:
  Add documentation for "RequireAuthPing" configuration option
  New configuration option "RequireAuthPing": PING-PONG on login
This commit is contained in:
Alexander Barton 2011-03-27 20:58:18 +02:00
commit d61fbfc6e3
10 changed files with 136 additions and 16 deletions

View File

@ -159,6 +159,11 @@
# messages to clients while connecting. # messages to clients while connecting.
;NoticeAuth = no ;NoticeAuth = no
# Let ngIRCd send an "authentication PING" when a new client connects,
# and register this client only after receiving the corresponding
# "PONG" reply.
;RequireAuthPing = no
# Set this hostname for every client instead of the real one. # Set this hostname for every client instead of the real one.
# Please note: don't use the percentage sign ("%"), it is reserved for # Please note: don't use the percentage sign ("%"), it is reserved for
# future extensions! # future extensions!

View File

@ -256,6 +256,11 @@ Normally ngIRCd doesn't send any messages to a client until it is registered.
Enable this option to let the daemon send "NOTICE AUTH" messages to clients Enable this option to let the daemon send "NOTICE AUTH" messages to clients
while connecting. Default: no. while connecting. Default: no.
.TP .TP
\fBRequireAuthPing\fR (boolean)
Let ngIRCd send an "authentication PING" when a new client connects, and
register this client only after receiving the corresponding "PONG" reply.
Default: no.
.TP
\fBCloakHost\fR (string) \fBCloakHost\fR (string)
Set this hostname for every client instead of the real one. Default: empty, Set this hostname for every client instead of the real one. Default: empty,
don't change. don't change.

View File

@ -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

View File

@ -354,9 +354,12 @@ Conf_Test( void )
printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1); printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1);
printf(" NoticeAuth = %s\n", yesno_to_str(Conf_NoticeAuth)); printf(" NoticeAuth = %s\n", yesno_to_str(Conf_NoticeAuth));
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));
@ -643,6 +646,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 */
@ -1255,6 +1263,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);

View File

@ -202,6 +202,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" */

View File

@ -2303,6 +2303,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
/** /**

View File

@ -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

View File

@ -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! */

View File

@ -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. */

View File

@ -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 },