unrealircd

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

api-usermode.c (9943B)

      1 /************************************************************************
      2  *   IRC - Internet Relay Chat, src/api-usermode.c
      3  *   (C) 1999-2000 Carsten Munk (Techie/Stskeeps) <stskeeps@tspre.org>
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers. 
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 char umodestring[UMODETABLESZ+1];
     26 
     27 /** User modes and their handlers */
     28 Umode *usermodes = NULL;
     29 
     30 long UMODE_INVISIBLE = 0L;     /* makes user invisible */
     31 long UMODE_OPER = 0L;          /* Operator */
     32 long UMODE_REGNICK = 0L;       /* Nick set by services as registered */
     33 long UMODE_SERVNOTICE = 0L;    /* server notices such as kill */
     34 long UMODE_HIDE = 0L;          /* Hide from Nukes */
     35 long UMODE_SECURE = 0L;        /* User is a secure connect */
     36 long UMODE_DEAF = 0L;          /* Deaf */
     37 long UMODE_HIDEOPER = 0L;      /* Hide oper mode */
     38 long UMODE_SETHOST = 0L;       /* Used sethost */
     39 long UMODE_HIDLE = 0L;         /* Hides the idle time of opers */
     40 
     41 long SNO_KILLS = 0L;
     42 long SNO_CLIENT = 0L;
     43 long SNO_FLOOD = 0L;
     44 long SNO_FCLIENT = 0L;
     45 long SNO_JUNK = 0L;
     46 long SNO_VHOST = 0L;
     47 long SNO_EYES = 0L;
     48 long SNO_TKL = 0L;
     49 long SNO_NICKCHANGE = 0L;
     50 long SNO_FNICKCHANGE = 0L;
     51 long SNO_QLINE = 0L;
     52 long SNO_SPAMF = 0L;
     53 long SNO_SNOTICE = 0L;
     54 long SNO_OPER = 0L;
     55 
     56 long AllUmodes;		/* All umodes */
     57 long SendUmodes;	/* All umodes which are sent to other servers (global umodes) */
     58 
     59 /* Forward declarations */
     60 int umode_hidle_allow(Client *client, int what);
     61 static void unload_usermode_commit(Umode *m);
     62 
     63 void umode_init(void)
     64 {
     65 	/* Some built-in modes */
     66 	UmodeAdd(NULL, 'i', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_INVISIBLE);
     67 	UmodeAdd(NULL, 'o', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_OPER);
     68 	UmodeAdd(NULL, 'r', UMODE_GLOBAL, 0, umode_allow_none, &UMODE_REGNICK);
     69 	UmodeAdd(NULL, 's', UMODE_LOCAL, 0, umode_allow_all, &UMODE_SERVNOTICE);
     70 	UmodeAdd(NULL, 'x', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_HIDE);
     71 	UmodeAdd(NULL, 'z', UMODE_GLOBAL, 0, umode_allow_none, &UMODE_SECURE);
     72 	UmodeAdd(NULL, 'd', UMODE_GLOBAL, 0, umode_allow_all, &UMODE_DEAF);
     73 	UmodeAdd(NULL, 'H', UMODE_GLOBAL, 1, umode_allow_opers, &UMODE_HIDEOPER);
     74 	UmodeAdd(NULL, 't', UMODE_GLOBAL, 0, umode_allow_unset, &UMODE_SETHOST);
     75 	UmodeAdd(NULL, 'I', UMODE_GLOBAL, 0, umode_hidle_allow, &UMODE_HIDLE);
     76 }
     77 
     78 void make_umodestr(void)
     79 {
     80 	Umode *um;
     81 	char *p = umodestring;
     82 
     83 	for (um=usermodes; um; um = um->next)
     84 		if (um->letter)
     85 			*p++ = um->letter;
     86 	*p = '\0';
     87 }
     88 
     89 static char previous_umodestring[256];
     90 
     91 void umodes_check_for_changes(void)
     92 {
     93 	make_umodestr();
     94 	safe_strdup(me.server->features.usermodes, umodestring);
     95 
     96 	if (!*previous_umodestring)
     97 	{
     98 		strlcpy(previous_umodestring, umodestring, sizeof(previous_umodestring));
     99 		return; /* not booted yet. then we are done here. */
    100 	}
    101 
    102 	if (*previous_umodestring && strcmp(umodestring, previous_umodestring))
    103 	{
    104 		unreal_log(ULOG_INFO, "mode", "USER_MODES_CHANGED", NULL,
    105 		           "User modes changed at runtime: $old_user_modes -> $new_user_modes",
    106 		           log_data_string("old_user_modes", previous_umodestring),
    107 		           log_data_string("new_user_modes", umodestring));
    108 		/* Broadcast change to all (locally connected) servers */
    109 		sendto_server(NULL, 0, 0, NULL, "PROTOCTL USERMODES=%s", umodestring);
    110 	}
    111 
    112 	strlcpy(previous_umodestring, umodestring, sizeof(previous_umodestring));
    113 }
    114 
    115 void usermode_add_sorted(Umode *n)
    116 {
    117 	Umode *m;
    118 
    119 	if (usermodes == NULL)
    120 	{
    121 		usermodes = n;
    122 		return;
    123 	}
    124 
    125 	for (m = usermodes; m; m = m->next)
    126 	{
    127 		if (m->letter == '\0')
    128 			abort();
    129 		if (sort_character_lowercase_before_uppercase(n->letter, m->letter))
    130 		{
    131 			/* Insert us before */
    132 			if (m->prev)
    133 				m->prev->next = n;
    134 			else
    135 				usermodes = n; /* new head */
    136 			n->prev = m->prev;
    137 
    138 			n->next = m;
    139 			m->prev = n;
    140 			return;
    141 		}
    142 		if (!m->next)
    143 		{
    144 			/* Append us at end */
    145 			m->next = n;
    146 			n->prev = m;
    147 			return;
    148 		}
    149 	}
    150 }
    151 
    152 
    153 /* UmodeAdd:
    154  * Add a usermode with character 'ch', if global is set to 1 the usermode is global
    155  * (sent to other servers) otherwise it's a local usermode
    156  */
    157 Umode *UmodeAdd(Module *module, char ch, int global, int unset_on_deoper, int (*allowed)(Client *client, int what), long *mode)
    158 {
    159 	Umode *um;
    160 	int existing = 0;
    161 
    162 	for (um=usermodes; um; um = um->next)
    163 	{
    164 		if (um->letter == ch)
    165 		{
    166 			if (um->unloaded)
    167 			{
    168 				um->unloaded = 0;
    169 				existing = 1;
    170 				break;
    171 			} else {
    172 				if (module)
    173 					module->errorcode = MODERR_EXISTS;
    174 				return NULL;
    175 			}
    176 		}
    177 	}
    178 
    179 	if (!um)
    180 	{
    181 		/* Not found, create */
    182 		long l, found = 0;
    183 		for (l = 1; l < LONG_MAX/2; l *= 2)
    184 		{
    185 			found = 0;
    186 			for (um=usermodes; um; um = um->next)
    187 			{
    188 				if (um->mode == l)
    189 				{
    190 					found = 1;
    191 					break;
    192 				}
    193 			}
    194 			if (!found)
    195 				break;
    196 		}
    197 		/* If 'found' is still true, then we are out of space */
    198 		if (found)
    199 		{
    200 			unreal_log(ULOG_ERROR, "module", "USER_MODE_OUT_OF_SPACE", NULL,
    201 				   "UmodeAdd: out of space!!!");
    202 			if (module)
    203 				module->errorcode = MODERR_NOSPACE;
    204 			return NULL;
    205 		}
    206 		um = safe_alloc(sizeof(Umode));
    207 		um->letter = ch;
    208 		um->mode = l;
    209 		usermode_add_sorted(um);
    210 	}
    211 
    212 	um->letter = ch;
    213 	um->allowed = allowed;
    214 	um->unset_on_deoper = unset_on_deoper;
    215 	make_umodestr();
    216 	AllUmodes |= um->mode;
    217 	if (global)
    218 		SendUmodes |= um->mode;
    219 	*mode = um->mode;
    220 	um->owner = module;
    221 	if (module)
    222 	{
    223 		ModuleObject *umodeobj = safe_alloc(sizeof(ModuleObject));
    224 		umodeobj->object.umode = um;
    225 		umodeobj->type = MOBJ_UMODE;
    226 		AddListItem(umodeobj, module->objects);
    227 		module->errorcode = MODERR_NOERROR;
    228 	}
    229 	return um;
    230 }
    231 
    232 
    233 void UmodeDel(Umode *umode)
    234 {
    235 	/* Always free the module object */
    236 	if (umode->owner)
    237 	{
    238 		ModuleObject *umodeobj;
    239 		for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next)
    240 		{
    241 			if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode)
    242 			{
    243 				DelListItem(umodeobj, umode->owner->objects);
    244 				safe_free(umodeobj);
    245 				break;
    246 			}
    247 		}
    248 		umode->owner = NULL;
    249 	}
    250 
    251 	/* Whether we can actually (already) free the Umode depends... */
    252 
    253 	if (loop.rehashing)
    254 		umode->unloaded = 1;
    255 	else
    256 		unload_usermode_commit(umode);
    257 }
    258 
    259 int umode_allow_all(Client *client, int what)
    260 {
    261 	return 1;
    262 }
    263 
    264 int umode_allow_unset(Client *client, int what)
    265 {
    266 	if (!MyUser(client))
    267 		return 1;
    268 	if (what == MODE_DEL)
    269 		return 1;
    270 	return 0;
    271 }
    272 
    273 int umode_allow_none(Client *client, int what)
    274 {
    275 	if (MyUser(client))
    276 		return 0;
    277 	return 1;
    278 }
    279 
    280 int umode_allow_opers(Client *client, int what)
    281 {
    282 	if (MyUser(client))
    283 		return IsOper(client) ? 1 : 0;
    284 	else
    285 		return 1;
    286 }
    287 
    288 int umode_hidle_allow(Client *client, int what)
    289 {
    290 	if (!MyUser(client))
    291 		return 1;
    292 	if (iConf.hide_idle_time == HIDE_IDLE_TIME_OPER_USERMODE)
    293 		return IsOper(client) ? 1 : 0;
    294 	if (iConf.hide_idle_time == HIDE_IDLE_TIME_USERMODE)
    295 		return 1;
    296 	return 0; /* if set::hide-idle-time is 'never' or 'always' then +I makes no sense */
    297 }
    298 
    299 static void unload_usermode_commit(Umode *um)
    300 {
    301 	Client *client;
    302 	long removed_umode;
    303 
    304 	if (!um)
    305 		return;
    306 
    307 	removed_umode = um->mode;
    308 
    309 	/* First send the -mode regarding all users */
    310 	list_for_each_entry(client, &lclient_list, lclient_node)
    311 	{
    312 		if (MyUser(client) && (client->umodes & removed_umode))
    313 		{
    314 			long oldumode = client->umodes;
    315 			client->umodes &= ~(removed_umode);
    316 			send_umode_out(client, 1, oldumode);
    317 		}
    318 	}
    319 
    320 	/* Then unload the mode */
    321 	DelListItem(um, usermodes);
    322 	safe_free(um);
    323 	make_umodestr();
    324 }
    325 
    326 void unload_all_unused_umodes(void)
    327 {
    328 	Umode *um, *um_next;
    329 
    330 	for (um=usermodes; um; um = um_next)
    331 	{
    332 		um_next = um->next;
    333 		if (um->letter && um->unloaded)
    334 			unload_usermode_commit(um);
    335 	}
    336 }
    337 
    338 /**
    339  * This function removes any oper-only snomasks when the user is no
    340  * longer an IRC Operator.
    341  * This used to be a bit more complex but nowadays we just erase all
    342  * snomasks since all of them are IRCOp-only. Easy.
    343  */
    344 void remove_all_snomasks(Client *client)
    345 {
    346 	safe_free(client->user->snomask);
    347 	client->umodes &= ~UMODE_SERVNOTICE;
    348 }
    349 
    350 /*
    351  * This function removes any oper-only user modes from the user.
    352  * You may also want to call remove_all_snomasks(), see above.
    353  */
    354 void remove_oper_modes(Client *client)
    355 {
    356 	Umode *um;
    357 
    358 	for (um = usermodes; um; um = um->next)
    359 	{
    360 		if (um->unset_on_deoper)
    361 			client->umodes &= ~um->mode;
    362 	}
    363 
    364 	/* Bit of a hack, since this is a dynamic permission umode */
    365 	if (iConf.hide_idle_time == HIDE_IDLE_TIME_OPER_USERMODE)
    366 		client->umodes &= ~UMODE_HIDLE;
    367 }
    368 
    369 void remove_oper_privileges(Client *client, int broadcast_mode_change)
    370 {
    371 	long oldumodes = client->umodes;
    372 	remove_oper_modes(client);
    373 	remove_all_snomasks(client);
    374 	if (broadcast_mode_change && (client->umodes != oldumodes))
    375 		send_umode_out(client, 1, oldumodes);
    376 	if (MyUser(client)) /* only do if it's our client, remote servers will send a SWHOIS cmd */
    377 		swhois_delete(client, "oper", "*", &me, NULL);
    378 }
    379 
    380 /** Return long integer mode for a user mode character (eg: 'x' -> 0x10) */
    381 long find_user_mode(char letter)
    382 {
    383 	Umode *um;
    384 
    385 	for (um = usermodes; um; um = um->next)
    386 		if ((um->letter == letter) && !um->unloaded)
    387 			return um->mode;
    388 
    389 	return 0;
    390 }
    391 
    392 /** Returns 1 if user has this user mode set and 0 if not */
    393 int has_user_mode(Client *client, char mode)
    394 {
    395 	long m = find_user_mode(mode);
    396 
    397 	if (client->umodes & m)
    398 		return 1; /* Yes, user has this mode */
    399 
    400 	return 0; /* Mode does not exist or not set */
    401 }