Exemplo n.º 1
0
Arquivo: irc.c Projeto: ngircd/ngircd
/**
 * Handler for the IRC "KILL" command.
 *
 * This function implements the IRC command "KILL" which is used to selectively
 * disconnect clients. It can be used by IRC operators and servers, for example
 * 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, 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.
 * @return CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_KILL(CLIENT *Client, REQUEST *Req)
{
	CLIENT *prefix;
	char reason[COMMAND_LEN];

	assert (Client != NULL);
	assert (Req != NULL);

	if (Client_Type(Client) != CLIENT_SERVER && !Op_Check(Client, Req))
		return Op_NoPrivileges(Client, Req);

	/* Get prefix (origin); use the client if no prefix is given. */
	if (Req->prefix)
		prefix = Client_Search(Req->prefix);
	else
		prefix = Client;

	/* Log a warning message and use this server as origin when the
	 * prefix (origin) is invalid. And this is the reason why we don't
	 * use the _IRC_GET_SENDER_OR_RETURN_ macro above! */
	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));

	return IRC_KillClient(Client, prefix, Req->argv[0], reason);
}
Exemplo n.º 2
0
/**
 * Handler for the IRC command "SQUIT".
 * See RFC 2813 section 4.1.2 and RFC 2812 section 3.1.8.
 */
GLOBAL bool
IRC_SQUIT(CLIENT * Client, REQUEST * Req)
{
	char msg[COMMAND_LEN], logmsg[COMMAND_LEN];
	CLIENT *from, *target;
	CONN_ID con;
	int loglevel;

	assert(Client != NULL);
	assert(Req != NULL);

	if (Client_Type(Client) != CLIENT_SERVER
	    && !Client_HasMode(Client, 'o'))
		return Op_NoPrivileges(Client, Req);

	/* Bad number of arguments? */
	if (Req->argc != 2)
		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
					  Client_ID(Client), Req->command);

	if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) {
		from = Client_Search(Req->prefix);
		if (Client_Type(from) != CLIENT_SERVER
		    && !Op_Check(Client, Req))
			return Op_NoPrivileges(Client, Req);
	} else
		from = Client;
	if (!from)
		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
					  Client_ID(Client), Req->prefix);

	if (Client_Type(Client) == CLIENT_USER)
		loglevel = LOG_NOTICE | LOG_snotice;
	else
		loglevel = LOG_DEBUG;
	Log(loglevel, "Got SQUIT from %s for \"%s\": \"%s\" ...",
	    Client_ID(from), Req->argv[0], Req->argv[1]);

	target = Client_Search(Req->argv[0]);
	if (Client_Type(Client) != CLIENT_SERVER &&
	    target == Client_ThisServer())
		return Op_NoPrivileges(Client, Req);
	if (!target) {
		/* The server is (already) unknown */
		Log(LOG_WARNING,
		    "Got SQUIT from %s for unknown server \"%s\"!?",
		    Client_ID(Client), Req->argv[0]);
		return CONNECTED;
	}

	con = Client_Conn(target);

	if (Req->argv[1][0])
		if (Client_NextHop(from) != Client || con > NONE)
			snprintf(msg, sizeof(msg), "%s (SQUIT from %s)",
				 Req->argv[1], Client_ID(from));
		else
			strlcpy(msg, Req->argv[1], sizeof(msg));
	else
		snprintf(msg, sizeof(msg), "Got SQUIT from %s",
			 Client_ID(from));

	if (con > NONE) {
		/* We are directly connected to the target server, so we
		 * have to tear down the connection and to inform all the
		 * other remaining servers in the network */
		IRC_SendWallops(Client_ThisServer(), Client_ThisServer(),
				"Received SQUIT %s from %s: %s",
				Req->argv[0], Client_ID(from),
				Req->argv[1][0] ? Req->argv[1] : "-");
		Conn_Close(con, NULL, msg, true);
		if (con == Client_Conn(Client))
			return DISCONNECTED;
	} else {
		/* This server is not directly connected, so the SQUIT must
		 * be forwarded ... */
		if (Client_Type(from) != CLIENT_SERVER) {
			/* The origin is not an IRC server, so don't evaluate
			 * this SQUIT but simply forward it */
			IRC_WriteStrClientPrefix(Client_NextHop(target),
			    from, "SQUIT %s :%s", Req->argv[0], Req->argv[1]);
		} else {
			/* SQUIT has been generated by another server, so
			 * remove the target server from the network! */
			logmsg[0] = '\0';
			if (!strchr(msg, '('))
				snprintf(logmsg, sizeof(logmsg),
					 "%s (SQUIT from %s)", Req->argv[1],
					 Client_ID(from));
			Client_Destroy(target, logmsg[0] ? logmsg : msg,
				       msg, false);
		}
	}
	return CONNECTED;
} /* IRC_SQUIT */