mirror of
				https://github.com/osmarks/ngircd.git
				synced 2025-10-31 05:52:59 +00:00 
			
		
		
		
	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:
		| @@ -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) { | ||||||
|  | 		if (Client_Type(Client) == CLIENT_USER) | ||||||
| 			return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG, | 			return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG, | ||||||
| 						  Client_ID(Client)); | 						  Client_ID(Client)); | ||||||
| 	if (Req->argc > 2) | 		else | ||||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | 			return CONNECTED; | ||||||
| 					  Client_ID(Client), Req->command); | 	} | ||||||
|  | 	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 }, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Alexander Barton
					Alexander Barton