unrealircd

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

key.c (5235B)

      1 /*
      2  * Channel Mode +k
      3  * (C) Copyright 2021 Syzop 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/key",
     25 	"6.0",
     26 	"Channel Mode +k",
     27 	"UnrealIRCd Team",
     28 	"unrealircd-6",
     29     };
     30 
     31 typedef struct ChannelKey ChannelKey;
     32 struct ChannelKey {
     33 	char key[KEYLEN+1];
     34 };
     35 
     36 /* Global variables */
     37 ModDataInfo *mdkey = NULL;
     38 Cmode_t EXTMODE_KEY = 0L;
     39 
     40 #define IsKey(x)	((x)->mode.mode & EXTMODE_KEY)
     41 
     42 /* Forward declarations */
     43 int key_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
     44 int cmode_key_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
     45 void *cmode_key_put_param(void *r_in, const char *param);
     46 const char *cmode_key_get_param(void *r_in);
     47 const char *cmode_key_conv_param(const char *param_in, Client *client, Channel *channel);
     48 int cmode_key_free_param(void *r, int soft);
     49 void *cmode_key_dup_struct(void *r_in);
     50 int cmode_key_sjoin_check(Channel *channel, void *ourx, void *theirx);
     51 int is_valid_key(const char *key);
     52 void transform_channel_key(const char *i, char *o, int n);
     53 
     54 MOD_INIT()
     55 {
     56 	CmodeInfo creq;
     57 	ModDataInfo mreq;
     58 
     59 	MARK_AS_OFFICIAL_MODULE(modinfo);
     60 
     61 	memset(&creq, 0, sizeof(creq));
     62 	creq.paracount = 1;
     63 	creq.is_ok = cmode_key_is_ok;
     64 	creq.letter = 'k';
     65 	creq.unset_with_param = 1; /* yeah... +k is like this */
     66 	creq.put_param = cmode_key_put_param;
     67 	creq.get_param = cmode_key_get_param;
     68 	creq.conv_param = cmode_key_conv_param;
     69 	creq.free_param = cmode_key_free_param;
     70 	creq.dup_struct = cmode_key_dup_struct;
     71 	creq.sjoin_check = cmode_key_sjoin_check;
     72 	CmodeAdd(modinfo->handle, creq, &EXTMODE_KEY);
     73 
     74 	HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, key_can_join);
     75 	return MOD_SUCCESS;
     76 }
     77 
     78 MOD_LOAD()
     79 {
     80 	return MOD_SUCCESS;
     81 }
     82 
     83 MOD_UNLOAD()
     84 {
     85 	return MOD_SUCCESS;
     86 }
     87 
     88 /** Can the user join the channel? */
     89 int key_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
     90 {
     91 	ChannelKey *r = (ChannelKey *)GETPARASTRUCT(channel, 'k');
     92 
     93 	/* Is the channel +k? */
     94 	if (r && *r->key)
     95 	{
     96 		if (key && !strcmp(r->key, key))
     97 			return 0;
     98 		*errmsg = STR_ERR_BADCHANNELKEY;
     99 		return ERR_BADCHANNELKEY;
    100 	}
    101 
    102 	return 0;
    103 }
    104 
    105 int cmode_key_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
    106 {
    107 	if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
    108 	{
    109 		/* Permitted for +hoaq */
    110 		if (IsUser(client) && check_channel_access(client, channel, "hoaq"))
    111 			return EX_ALLOW;
    112 		return EX_DENY;
    113 	} else
    114 	if (type == EXCHK_PARAM)
    115 	{
    116 		if (!is_valid_key(param))
    117 		{
    118 			sendnumeric(client, ERR_INVALIDMODEPARAM,
    119 				channel->name, 'k', "*", "Channel key contains forbidden characters or is too long");
    120 			return EX_DENY;
    121 		}
    122 		return EX_ALLOW;
    123 	}
    124 
    125 	/* fallthrough -- should not be used */
    126 	return EX_DENY;
    127 }
    128 
    129 void *cmode_key_put_param(void *k_in, const char *param)
    130 {
    131 	ChannelKey *fld = (ChannelKey *)k_in;
    132 
    133 	if (!fld)
    134 		fld = safe_alloc(sizeof(ChannelKey));
    135 
    136 	transform_channel_key(param, fld->key, sizeof(fld->key));
    137 
    138 	return fld;
    139 }
    140 
    141 const char *cmode_key_get_param(void *r_in)
    142 {
    143 	ChannelKey *r = (ChannelKey *)r_in;
    144 	static char retbuf[KEYLEN+1];
    145 
    146 	if (!r)
    147 		return NULL;
    148 
    149 	strlcpy(retbuf, r->key, sizeof(retbuf));
    150 	return retbuf;
    151 }
    152 
    153 const char *cmode_key_conv_param(const char *param, Client *client, Channel *channel)
    154 {
    155 	static char retbuf[KEYLEN+1];
    156 
    157 	transform_channel_key(param, retbuf, sizeof(retbuf));
    158 
    159 	if (!*retbuf)
    160 		return NULL; /* entire key was invalid */
    161 
    162 	return retbuf;
    163 }
    164 
    165 int cmode_key_free_param(void *r, int soft)
    166 {
    167 	safe_free(r);
    168 	return 0;
    169 }
    170 
    171 void *cmode_key_dup_struct(void *r_in)
    172 {
    173 	ChannelKey *r = (ChannelKey *)r_in;
    174 	ChannelKey *w = safe_alloc(sizeof(ChannelKey));
    175 
    176 	memcpy(w, r, sizeof(ChannelKey));
    177 
    178 	return (void *)w;
    179 }
    180 
    181 int cmode_key_sjoin_check(Channel *channel, void *ourx, void *theirx)
    182 {
    183 	ChannelKey *our = (ChannelKey *)ourx;
    184 	ChannelKey *their = (ChannelKey *)theirx;
    185 	int i;
    186 	int r;
    187 
    188 	r = strcmp(our->key, their->key);
    189 	if (r == 0)
    190 		return EXSJ_SAME;
    191 	else if (r > 0)
    192 		return EXSJ_WEWON;
    193 	else
    194 		return EXSJ_THEYWON;
    195 }
    196 
    197 int valid_key_char(char c)
    198 {
    199 	if (strchr(" :,", c))
    200 		return 0;
    201 	if (c <= 32)
    202 		return 0;
    203 	return 1;
    204 }
    205 
    206 #define BADKEYCHARS " :,"
    207 int is_valid_key(const char *key)
    208 {
    209 	const char *p;
    210 
    211 	if (strlen(key) > KEYLEN)
    212 		return 0;
    213 	for (p = key; *p; p++)
    214 		if (!valid_key_char(*p))
    215 			return 0;
    216 	return 1;
    217 }
    218 
    219 void transform_channel_key(const char *i, char *o, int n)
    220 {
    221 	n--; /* reserve one for final nul byte */
    222 
    223 	for (; *i; i++)
    224 	{
    225 		if (!valid_key_char(*i))
    226 			break;
    227 		if (n <= 0)
    228 			break;
    229 		*o++ = *i;
    230 		n--;
    231 	}
    232 	*o = '\0';
    233 }