コード例 #1
0
ファイル: irc-mode.c プロジェクト: LucentW/ngircd
/**
 * Add entries to channel invite, ban and exception lists.
 *
 * @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
 * @param Prefix The originator of the command.
 * @param Client The sender of the command.
 * @param Channel The channel of which the list should be modified.
 * @param Pattern The pattern to add to the list.
 * @return CONNECTED or DISCONNECTED.
 */
static bool
Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
	    const char *Pattern)
{
	char mask[MASK_LEN];
	struct list_head *list = NULL;
	long int current_count;

	assert(Client != NULL);
	assert(Channel != NULL);
	assert(Pattern != NULL);
	assert(what == 'I' || what == 'b' || what == 'e');

	Lists_MakeMask(Pattern, mask, sizeof(mask));
	current_count = Lists_Count(Channel_GetListInvites(Channel))
			+ Lists_Count(Channel_GetListExcepts(Channel))
			+ Lists_Count(Channel_GetListBans(Channel));

	switch(what) {
		case 'I':
			list = Channel_GetListInvites(Channel);
			break;
		case 'b':
			list = Channel_GetListBans(Channel);
			break;
		case 'e':
			list = Channel_GetListExcepts(Channel);
			break;
	}

	if (Lists_CheckDupeMask(list, mask))
		return CONNECTED;
	if (Client_Type(Client) == CLIENT_USER &&
	    current_count >= MAX_HNDL_CHANNEL_LISTS)
		return IRC_WriteErrClient(Client, ERR_LISTFULL_MSG,
					  Client_ID(Client),
					  Channel_Name(Channel), mask,
					  MAX_HNDL_CHANNEL_LISTS);

	switch (what) {
		case 'I':
			if (!Channel_AddInvite(Channel, mask, false, Client_ID(Client)))
				return CONNECTED;
			break;
		case 'b':
			if (!Channel_AddBan(Channel, mask, Client_ID(Client)))
				return CONNECTED;
			break;
		case 'e':
			if (!Channel_AddExcept(Channel, mask, Client_ID(Client)))
				return CONNECTED;
			break;
	}
	return Send_ListChange(true, what, Prefix, Client, Channel, mask);
}
コード例 #2
0
ファイル: irc-mode.c プロジェクト: LucentW/ngircd
/**
 * Delete entries from channel invite, ban and exception lists.
 *
 * @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
 * @param Prefix The originator of the command.
 * @param Client The sender of the command.
 * @param Channel The channel of which the list should be modified.
 * @param Pattern The pattern to add to the list.
 * @return CONNECTED or DISCONNECTED.
 */
static bool
Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
	      const char *Pattern)
{
	char mask[MASK_LEN];
	struct list_head *list = NULL;

	assert(Client != NULL);
	assert(Channel != NULL);
	assert(Pattern != NULL);
	assert(what == 'I' || what == 'b' || what == 'e');

	Lists_MakeMask(Pattern, mask, sizeof(mask));

	switch (what) {
		case 'I':
			list = Channel_GetListInvites(Channel);
			break;
		case 'b':
			list = Channel_GetListBans(Channel);
			break;
		case 'e':
			list = Channel_GetListExcepts(Channel);
			break;
	}

	if (!Lists_CheckDupeMask(list, mask))
		return CONNECTED;
	Lists_Del(list, mask);

	return Send_ListChange(false, what, Prefix, Client, Channel, mask);
}
コード例 #3
0
ファイル: channel.c プロジェクト: Flupsy/ngircd
GLOBAL bool
Channel_AddBan(CHANNEL *c, const char *mask, const char *who )
{
	struct list_head *h = Channel_GetListBans(c);
	LogDebug("Adding \"%s\" to \"%s\" ban list", mask, Channel_Name(c));
	return Lists_Add(h, mask, time(NULL), who, false);
}
コード例 #4
0
ファイル: numeric.c プロジェクト: LucentW/ngircd
/**
 * Synchronize invite, ban, except, and G-Line lists between servers.
 *
 * @param Client New server.
 * @return CONNECTED or DISCONNECTED.
 */
static bool
Synchronize_Lists(CLIENT * Client)
{
	CHANNEL *c;
	struct list_head *head;
	struct list_elem *elem;
	time_t t;

	assert(Client != NULL);

	/* g-lines */
	head = Class_GetList(CLASS_GLINE);
	elem = Lists_GetFirst(head);
	while (elem) {
		t = Lists_GetValidity(elem) - time(NULL);
		if (!IRC_WriteStrClient(Client, "GLINE %s %ld :%s",
					Lists_GetMask(elem),
					t > 0 ? (long)t : 0,
					Lists_GetReason(elem)))
			return DISCONNECTED;
		elem = Lists_GetNext(elem);
	}

	c = Channel_First();
	while (c) {
		if (!Send_List(Client, c, Channel_GetListExcepts(c), 'e'))
			return DISCONNECTED;
		if (!Send_List(Client, c, Channel_GetListBans(c), 'b'))
			return DISCONNECTED;
		if (!Send_List(Client, c, Channel_GetListInvites(c), 'I'))
			return DISCONNECTED;
		c = Channel_Next(c);
	}
	return CONNECTED;
}
コード例 #5
0
ファイル: channel.c プロジェクト: Flupsy/ngircd
GLOBAL bool
Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
{
	struct list_head *h;

	assert( Channel != NULL );

	h = Channel_GetListBans(Channel);
	return ShowChannelList(h, Client, Channel, RPL_BANLIST_MSG,
			       RPL_ENDOFBANLIST_MSG);
}
コード例 #6
0
ファイル: irc-op.c プロジェクト: cofyc/ngircd
/**
 * Handler for the IRC command "INVITE".
 *
 * @param Client The client from which this command has been received.
 * @param Req Request structure with prefix and all parameters.
 * @return CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_INVITE(CLIENT *Client, REQUEST *Req)
{
	CHANNEL *chan;
	CLIENT *target, *from;
	const char *colon_if_necessary;
	bool remember = false;

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

	_IRC_ARGC_EQ_OR_RETURN_(Client, Req, 2)
	_IRC_GET_SENDER_OR_RETURN_(from, Req, Client)

	/* Search user */
	target = Client_Search(Req->argv[0]);
	if (!target || (Client_Type(target) != CLIENT_USER))
		return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
				Client_ID(Client), Req->argv[0]);

	chan = Channel_Search(Req->argv[1]);
	if (chan) {
		/* Channel exists. Is the user a valid member of the channel? */
		if (!Channel_IsMemberOf(chan, from))
			return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Req->argv[1]);

		/* Is the channel "invite-disallow"? */
		if (strchr(Channel_Modes(chan), 'V'))
			return IRC_WriteStrClient(from, ERR_NOINVITE_MSG,
				Client_ID(from), Channel_Name(chan));

		/* Is the channel "invite-only"? */
		if (strchr(Channel_Modes(chan), 'i')) {
			/* Yes. The user must be channel owner/admin/operator/halfop! */
			if (!strchr(Channel_UserModes(chan, from), 'q') &&
			    !strchr(Channel_UserModes(chan, from), 'a') &&
			    !strchr(Channel_UserModes(chan, from), 'o') &&
			    !strchr(Channel_UserModes(chan, from), 'h'))
				return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG,
						Client_ID(from), Channel_Name(chan));
			remember = true;
		}

		/* Is the target user already member of the channel? */
		if (Channel_IsMemberOf(chan, target))
			return IRC_WriteStrClient(from, ERR_USERONCHANNEL_MSG,
					Client_ID(from), Req->argv[0], Req->argv[1]);

		/* If the target user is banned on that channel: remember invite */
		if (Lists_Check(Channel_GetListBans(chan), target))
			remember = true;

		if (remember) {
			/* We must remember this invite */
			if (!Channel_AddInvite(chan, Client_Mask(target), true))
				return CONNECTED;
		}
	}

	LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from),
		 Req->argv[0], Req->argv[1]);

	/*
	 * RFC 2812 says:
	 * 'There is no requirement that the channel [..] must exist or be a valid channel'
	 * The problem with this is that this allows the "channel" to contain spaces,
	 * in which case we must prefix its name with a colon to make it clear that
	 * it is only a single argument.
	 */
	colon_if_necessary = strchr(Req->argv[1], ' ') ? ":":"";
	/* Inform target client */
	IRC_WriteStrClientPrefix(target, from, "INVITE %s %s%s", Req->argv[0],
					colon_if_necessary, Req->argv[1]);

	if (Client_Conn(target) > NONE) {
		/* The target user is local, so we have to send the status code */
		if (!IRC_WriteStrClientPrefix(from, target, RPL_INVITING_MSG,
			Client_ID(from), Req->argv[0], colon_if_necessary, Req->argv[1]))
			return DISCONNECTED;

		if (strchr(Client_Modes(target), 'a') &&
			!IRC_WriteStrClient(from, RPL_AWAY_MSG, Client_ID(from),
					Client_ID(target), Client_Away(target)))
				return DISCONNECTED;
	}
	return CONNECTED;
} /* IRC_INVITE */
コード例 #7
0
ファイル: irc-channel.c プロジェクト: andinue/ngircd
/**
 * Check weather a local client is allowed to join an already existing
 * channel or not.
 *
 * @param Client	Client that sent the JOIN command
 * @param chan		Channel to check
 * @param channame	Name of the channel
 * @param key		Provided channel key (or NULL)
 * @returns		true if client is allowed to join, false otherwise
 */
static bool
join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
	     const char *key)
{
	bool is_invited, is_banned, is_exception;

	/* Allow IRC operators to overwrite channel limits */
	if (Client_HasMode(Client, 'o'))
		return true;

	is_banned = Lists_Check(Channel_GetListBans(chan), Client);
	is_exception = Lists_Check(Channel_GetListExcepts(chan), Client);
	is_invited = Lists_Check(Channel_GetListInvites(chan), Client);

	if (is_banned && !is_invited && !is_exception) {
		/* Client is banned from channel (and not on invite list) */
		IRC_WriteErrClient(Client, ERR_BANNEDFROMCHAN_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (Channel_HasMode(chan, 'i') && !is_invited) {
		/* Channel is "invite-only" and client is not on invite list */
		IRC_WriteErrClient(Client, ERR_INVITEONLYCHAN_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (!Channel_CheckKey(chan, Client, key ? key : "")) {
		/* Channel is protected by a channel key and the client
		 * didn't specify the correct one */
		IRC_WriteErrClient(Client, ERR_BADCHANNELKEY_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (Channel_HasMode(chan, 'l') &&
	    (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) {
		/* There are more clints joined to this channel than allowed */
		IRC_WriteErrClient(Client, ERR_CHANNELISFULL_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (Channel_HasMode(chan, 'z') && !Conn_UsesSSL(Client_Conn(Client))) {
		/* Only "secure" clients are allowed, but clients doesn't
		 * use SSL encryption */
		IRC_WriteErrClient(Client, ERR_SECURECHANNEL_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (Channel_HasMode(chan, 'O') && !Client_HasMode(Client, 'o')) {
		/* Only IRC operators are allowed! */
		IRC_WriteErrClient(Client, ERR_OPONLYCHANNEL_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	if (Channel_HasMode(chan, 'R') && !Client_HasMode(Client, 'R')) {
		/* Only registered users are allowed! */
		IRC_WriteErrClient(Client, ERR_REGONLYCHANNEL_MSG,
				   Client_ID(Client), channame);
		return false;
	}

	return true;
} /* join_allowed */