unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

secureonly.c (5276B)

      1 /*
      2  * Only allow secure users to join UnrealIRCd Module (Channel Mode +z)
      3  * (C) Copyright 2014 Travis McArthur (Heero) and the UnrealIRCd team
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 1, or (at your option)
      8  * any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #include "unrealircd.h"
     21 
     22 ModuleHeader MOD_HEADER
     23   = {
     24 	"chanmodes/secureonly",
     25 	"4.2",
     26 	"Channel Mode +z",
     27 	"UnrealIRCd Team",
     28 	"unrealircd-6",
     29     };
     30 
     31 Cmode_t EXTCMODE_SECUREONLY;
     32 
     33 #define IsSecureOnly(channel)    (channel->mode.mode & EXTCMODE_SECUREONLY)
     34 
     35 int secureonly_check_join(Client *client, Channel *channel, const char *key, char **errmsg);
     36 int secureonly_channel_sync (Channel *channel, int merge, int removetheirs, int nomode);
     37 int secureonly_check_secure(Channel *channel);
     38 int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester);
     39 int secureonly_pre_local_join(Client *client, Channel *channel, const char *key);
     40 
     41 MOD_TEST()
     42 {
     43 	return MOD_SUCCESS;
     44 }
     45 
     46 MOD_INIT()
     47 {
     48 	CmodeInfo req;
     49 
     50 	memset(&req, 0, sizeof(req));
     51 	req.paracount = 0;
     52 	req.letter = 'z';
     53 	req.is_ok = extcmode_default_requirechop;
     54 	CmodeAdd(modinfo->handle, req, &EXTCMODE_SECUREONLY);
     55 
     56 	HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_JOIN, 0, secureonly_pre_local_join);
     57 	HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, secureonly_check_join);
     58 	HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_SYNCED, 0, secureonly_channel_sync);
     59 	HookAdd(modinfo->handle, HOOKTYPE_IS_CHANNEL_SECURE, 0, secureonly_check_secure);
     60 	HookAdd(modinfo->handle, HOOKTYPE_CAN_SAJOIN, 0, secureonly_check_sajoin);
     61 
     62 
     63 	MARK_AS_OFFICIAL_MODULE(modinfo);
     64 	return MOD_SUCCESS;
     65 }
     66 
     67 MOD_LOAD()
     68 {
     69 	return MOD_SUCCESS;
     70 }
     71 
     72 MOD_UNLOAD()
     73 {
     74 	return MOD_SUCCESS;
     75 }
     76 
     77 
     78 /** Kicks all insecure users on a +z channel
     79  * Returns 1 if the channel was destroyed as a result of this.
     80  */
     81 static int secureonly_kick_insecure_users(Channel *channel)
     82 {
     83 	Member *member, *mb2;
     84 	Client *client;
     85 	int i = 0;
     86 	Hook *h;
     87 	char *comment = "Insecure user not allowed on secure channel (+z)";
     88 
     89 	if (!IsSecureOnly(channel))
     90 		return 0;
     91 
     92 	for (member = channel->members; member; member = mb2)
     93 	{
     94 		mb2 = member->next;
     95 		client = member->client;
     96 		if (MyUser(client) && !IsSecureConnect(client) && !IsULine(client))
     97 		{
     98 			char *prefix = NULL;
     99 			MessageTag *mtags = NULL;
    100 
    101 			if (invisible_user_in_channel(client, channel))
    102 			{
    103 				/* Send only to chanops */
    104 				prefix = "ho";
    105 			}
    106 
    107 			new_message(&me, NULL, &mtags);
    108 
    109 			RunHook(HOOKTYPE_LOCAL_KICK, &me, &me, client, channel, mtags, comment);
    110 
    111 			sendto_channel(channel, &me, client,
    112 				       prefix, 0,
    113 				       SEND_LOCAL, mtags,
    114 				       ":%s KICK %s %s :%s",
    115 				       me.name, channel->name, client->name, comment);
    116 
    117 			sendto_prefix_one(client, &me, mtags, ":%s KICK %s %s :%s", me.name, channel->name, client->name, comment);
    118 
    119 			sendto_server(NULL, 0, 0, mtags, ":%s KICK %s %s :%s", me.id, channel->name, client->id, comment);
    120 
    121 			free_message_tags(mtags);
    122 
    123 			if (remove_user_from_channel(client, channel, 0) == 1)
    124 				return 1; /* channel was destroyed */
    125 		}
    126 	}
    127 	return 0;
    128 }
    129 
    130 int secureonly_check_join(Client *client, Channel *channel, const char *key, char **errmsg)
    131 {
    132 	Link *lp;
    133 
    134 	if (IsSecureOnly(channel) && !(client->umodes & UMODE_SECURE))
    135 	{
    136 		if (ValidatePermissionsForPath("channel:override:secureonly",client,NULL,channel,NULL))
    137 		{
    138 			/* if the channel is +z we still allow an ircop to bypass it
    139 			 * if they are invited.
    140 			 */
    141 			if (is_invited(client, channel))
    142 				return HOOK_CONTINUE;
    143 		}
    144 		*errmsg = STR_ERR_SECUREONLYCHAN;
    145 		return ERR_SECUREONLYCHAN;
    146 	}
    147 	return 0;
    148 }
    149 
    150 int secureonly_check_secure(Channel *channel)
    151 {
    152 	if (IsSecureOnly(channel))
    153 	{
    154 		return 1;
    155 	}
    156 
    157 	return 0;
    158 }
    159 
    160 int secureonly_channel_sync(Channel *channel, int merge, int removetheirs, int nomode)
    161 {
    162 	if (!merge && !removetheirs && !nomode)
    163 		return secureonly_kick_insecure_users(channel); /* may return 1, meaning channel is destroyed */
    164 	return 0;
    165 }
    166 
    167 int secureonly_check_sajoin(Client *target, Channel *channel, Client *requester)
    168 {
    169 	if (IsSecureOnly(channel) && !IsSecure(target))
    170 	{
    171 		sendnotice(requester, "You cannot SAJOIN %s to %s because the channel is +z and the user is not connected via TLS",
    172 			target->name, channel->name);
    173 		return HOOK_DENY;
    174 	}
    175 
    176 	return HOOK_CONTINUE;
    177 }
    178 
    179 /* Special check for +z in set::modes-on-join. Needs to be done early.
    180  * Perhaps one day this will be properly handled in the core so this can be removed.
    181  */
    182 int secureonly_pre_local_join(Client *client, Channel *channel, const char *key)
    183 {
    184 	if ((channel->users == 0) && (MODES_ON_JOIN & EXTCMODE_SECUREONLY) && !IsSecure(client) && !IsOper(client))
    185 	{
    186 		sendnumeric(client, ERR_SECUREONLYCHAN, channel->name);
    187 		return HOOK_DENY;
    188 	}
    189 	return HOOK_CONTINUE;
    190 }