mirror of
				https://github.com/osmarks/ngircd.git
				synced 2025-11-04 07:52:59 +00:00 
			
		
		
		
	Merge branch 'bug113-SrvPrefix'
* bug113-SrvPrefix: Slightly change (and document!) IRC_KILL() calling convention Spoofed prefixes: close connection on non-server links only
This commit is contained in:
		@@ -1102,20 +1102,22 @@ Hello_User_PostAuth(CLIENT *Client)
 | 
			
		||||
 * @param Reason	Reason for the KILL.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
Kill_Nick( char *Nick, char *Reason )
 | 
			
		||||
Kill_Nick(char *Nick, char *Reason)
 | 
			
		||||
{
 | 
			
		||||
	REQUEST r;
 | 
			
		||||
 | 
			
		||||
	assert( Nick != NULL );
 | 
			
		||||
	assert( Reason != NULL );
 | 
			
		||||
	assert (Nick != NULL);
 | 
			
		||||
	assert (Reason != NULL);
 | 
			
		||||
 | 
			
		||||
	r.prefix = (char *)Client_ThisServer( );
 | 
			
		||||
	r.prefix = NULL;
 | 
			
		||||
	r.argv[0] = Nick;
 | 
			
		||||
	r.argv[1] = Reason;
 | 
			
		||||
	r.argc = 2;
 | 
			
		||||
 | 
			
		||||
	Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
 | 
			
		||||
	IRC_KILL( Client_ThisServer( ), &r );
 | 
			
		||||
	Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
 | 
			
		||||
	    Nick, Reason);
 | 
			
		||||
 | 
			
		||||
	IRC_KILL(Client_ThisServer(), &r);
 | 
			
		||||
} /* Kill_Nick */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -63,13 +63,21 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Kill client on request.
 | 
			
		||||
 * Handler for the IRC "KILL" command.
 | 
			
		||||
 *
 | 
			
		||||
 * This function implements the IRC command "KILL" wich is used to selectively
 | 
			
		||||
 * disconnect clients. It can be used by IRC operators and servers, for example
 | 
			
		||||
 * to "solve" nick collisions after netsplits.
 | 
			
		||||
 * to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1.
 | 
			
		||||
 *
 | 
			
		||||
 * Please note that this function is also called internally, without a real
 | 
			
		||||
 * KILL command being received over the network! Client is Client_ThisServer()
 | 
			
		||||
 * in this case. */
 | 
			
		||||
 * in this case, and the prefix in Req is NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * @param Client	The client from which this command has been received
 | 
			
		||||
 *			or Client_ThisServer() when generated interanlly.
 | 
			
		||||
 * @param Req		Request structure with prefix and all parameters.
 | 
			
		||||
 * @returns		CONNECTED or DISCONNECTED.
 | 
			
		||||
 */
 | 
			
		||||
GLOBAL bool
 | 
			
		||||
IRC_KILL( CLIENT *Client, REQUEST *Req )
 | 
			
		||||
{
 | 
			
		||||
@@ -77,55 +85,47 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
 | 
			
		||||
	char reason[COMMAND_LEN], *msg;
 | 
			
		||||
	CONN_ID my_conn, conn;
 | 
			
		||||
 | 
			
		||||
	assert( Client != NULL );
 | 
			
		||||
	assert( Req != NULL );
 | 
			
		||||
	assert (Client != NULL);
 | 
			
		||||
	assert (Req != NULL);
 | 
			
		||||
 | 
			
		||||
	if(( Client_Type( Client ) != CLIENT_SERVER ) &&
 | 
			
		||||
	   ( ! Client_OperByMe( Client )))
 | 
			
		||||
	{
 | 
			
		||||
		/* The originator of the KILL is neither an IRC operator of
 | 
			
		||||
		 * this server nor a server. */
 | 
			
		||||
		return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG,
 | 
			
		||||
					   Client_ID( Client ));
 | 
			
		||||
	}
 | 
			
		||||
	if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
 | 
			
		||||
		return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
 | 
			
		||||
					  Client_ID(Client));
 | 
			
		||||
 | 
			
		||||
	if( Req->argc != 2 )
 | 
			
		||||
	{
 | 
			
		||||
		/* This command requires exactly 2 parameters! */
 | 
			
		||||
		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
 | 
			
		||||
					   Client_ID( Client ), Req->command );
 | 
			
		||||
	}
 | 
			
		||||
	if (Req->argc != 2)
 | 
			
		||||
		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
 | 
			
		||||
					  Client_ID(Client), Req->command);
 | 
			
		||||
 | 
			
		||||
	if( Req->prefix ) prefix = Client_Search( Req->prefix );
 | 
			
		||||
	else prefix = Client;
 | 
			
		||||
	if( ! prefix )
 | 
			
		||||
	{
 | 
			
		||||
		Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
 | 
			
		||||
		     Req->prefix );
 | 
			
		||||
		prefix = Client_ThisServer( );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( Client != Client_ThisServer( ))
 | 
			
		||||
	{
 | 
			
		||||
		/* This is a "real" KILL received from the network. */
 | 
			
		||||
		Log( LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s",
 | 
			
		||||
		     Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build reason string */
 | 
			
		||||
	if( Client_Type( Client ) == CLIENT_USER )
 | 
			
		||||
	{
 | 
			
		||||
		/* Prefix the "reason" if the originator is a regular user,
 | 
			
		||||
		 * so users can't spoof KILLs of servers. */
 | 
			
		||||
		snprintf( reason, sizeof( reason ), "KILLed by %s: %s",
 | 
			
		||||
			  Client_ID( Client ), Req->argv[1] );
 | 
			
		||||
	}
 | 
			
		||||
	/* Get prefix (origin); use the client if no prefix is given. */
 | 
			
		||||
	if (Req->prefix)
 | 
			
		||||
		prefix = Client_Search(Req->prefix);
 | 
			
		||||
	else
 | 
			
		||||
		strlcpy( reason, Req->argv[1], sizeof( reason ));
 | 
			
		||||
		prefix = Client;
 | 
			
		||||
 | 
			
		||||
	/* Log a warning message and use this server as origin when the
 | 
			
		||||
	 * prefix (origin) is invalid. */
 | 
			
		||||
	if (!prefix) {
 | 
			
		||||
		Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
 | 
			
		||||
		    Req->prefix );
 | 
			
		||||
		prefix = Client_ThisServer();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (Client != Client_ThisServer())
 | 
			
		||||
		Log(LOG_NOTICE|LOG_snotice,
 | 
			
		||||
		    "Got KILL command from \"%s\" for \"%s\": %s",
 | 
			
		||||
		    Client_Mask(prefix), Req->argv[0], Req->argv[1]);
 | 
			
		||||
 | 
			
		||||
	/* Build reason string: Prefix the "reason" if the originator is a
 | 
			
		||||
	 * regular user, so users can't spoof KILLs of servers. */
 | 
			
		||||
	if (Client_Type(Client) == CLIENT_USER)
 | 
			
		||||
		snprintf(reason, sizeof(reason), "KILLed by %s: %s",
 | 
			
		||||
			 Client_ID(Client), Req->argv[1]);
 | 
			
		||||
	else
 | 
			
		||||
		strlcpy(reason, Req->argv[1], sizeof(reason));
 | 
			
		||||
 | 
			
		||||
	/* Inform other servers */
 | 
			
		||||
	IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s",
 | 
			
		||||
				   Req->argv[0], reason );
 | 
			
		||||
	IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
 | 
			
		||||
				  Req->argv[0], reason);
 | 
			
		||||
 | 
			
		||||
	/* Save ID of this connection */
 | 
			
		||||
	my_conn = Client_Conn( Client );
 | 
			
		||||
 
 | 
			
		||||
@@ -325,13 +325,21 @@ Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
 | 
			
		||||
	/* check if the client named in the prefix is expected
 | 
			
		||||
	 * to come from that direction */
 | 
			
		||||
	if (Client_NextHop(c) != client) {
 | 
			
		||||
		Log(LOG_ERR,
 | 
			
		||||
		    "Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
 | 
			
		||||
		    Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
 | 
			
		||||
		    Req->command);
 | 
			
		||||
		Conn_Close(Idx, NULL, "Spoofed prefix", true);
 | 
			
		||||
		*Closed = true;
 | 
			
		||||
		if (Client_Type(c) != CLIENT_SERVER) {
 | 
			
		||||
			Log(LOG_ERR,
 | 
			
		||||
			    "Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
 | 
			
		||||
			    Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
 | 
			
		||||
			    Req->command);
 | 
			
		||||
			Conn_Close(Idx, NULL, "Spoofed prefix", true);
 | 
			
		||||
			*Closed = true;
 | 
			
		||||
		} else {
 | 
			
		||||
			Log(LOG_INFO,
 | 
			
		||||
			    "Ignoring spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\").",
 | 
			
		||||
			    Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
 | 
			
		||||
			    Req->command);
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user