1 /************************************************************************
2  *   IRC - Internet Relay Chat, umodes.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 "struct.h"
24 #include "common.h"
25 #include "sys.h"
26 #include "numeric.h"
27 #include "msg.h"
28 #include "proto.h"
29 #include "channel.h"
30 #include "version.h"
31 #include <time.h>
32 #ifdef _WIN32
33 #include <sys/timeb.h>
34 #endif
35 #include <sys/stat.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #ifdef _WIN32
40 #include <io.h>
41 #endif
42 #include <fcntl.h>
43 #include "h.h"
44 
45 char umodestring[UMODETABLESZ+1];
46 
47 Umode *Usermode_Table = NULL;
48 short	 Usermode_highest = 0;
49 
50 Snomask *Snomask_Table = NULL;
51 short	 Snomask_highest = 0;
52 
53 /* cptr->umodes (32 bits): 26 used, 6 free */
54 long UMODE_INVISIBLE = 0L;     /* makes user invisible */
55 long UMODE_OPER = 0L;          /* Operator */
56 long UMODE_WALLOP = 0L;        /* send wallops to them */
57 long UMODE_FAILOP = 0L;        /* Shows some global messages */
58 long UMODE_HELPOP = 0L;        /* Help system operator */
59 long UMODE_REGNICK = 0L;       /* Nick set by services as registered */
60 long UMODE_SADMIN = 0L;        /* Services Admin */
61 long UMODE_ADMIN = 0L;         /* Admin */
62 long UMODE_SERVNOTICE = 0L;    /* server notices such as kill */
63 long UMODE_LOCOP = 0L;         /* Local operator -- SRB */
64 long UMODE_RGSTRONLY = 0L;     /* Only reg nick message */
65 long UMODE_WEBTV = 0L;         /* WebTV Client */
66 long UMODE_SERVICES = 0L;      /* services */
67 long UMODE_HIDE = 0L;          /* Hide from Nukes */
68 long UMODE_NETADMIN = 0L;      /* Network Admin */
69 long UMODE_COADMIN = 0L;       /* Co Admin */
70 long UMODE_WHOIS = 0L;         /* gets notice on /whois */
71 long UMODE_KIX = 0L;           /* usermode +q */
72 long UMODE_BOT = 0L;           /* User is a bot */
73 long UMODE_SECURE = 0L;        /* User is a secure connect */
74 long UMODE_VICTIM = 0L;        /* Intentional Victim */
75 long UMODE_DEAF = 0L;          /* Deaf */
76 long UMODE_HIDEOPER = 0L;      /* Hide oper mode */
77 long UMODE_SETHOST = 0L;       /* Used sethost */
78 long UMODE_STRIPBADWORDS = 0L; /* Strip badwords */
79 long UMODE_HIDEWHOIS = 0L;     /* Hides channels in /whois */
80 long UMODE_NOCTCP = 0L;	       /* Blocks ctcp (except dcc and action) */
81 long UMODE_HIDLE = 0L;         /* Hides the idle time of opers */
82 
83 long SNO_KILLS = 0L;
84 long SNO_CLIENT = 0L;
85 long SNO_FLOOD = 0L;
86 long SNO_FCLIENT = 0L;
87 long SNO_JUNK = 0L;
88 long SNO_VHOST = 0L;
89 long SNO_EYES = 0L;
90 long SNO_TKL = 0L;
91 long SNO_NICKCHANGE = 0L;
92 long SNO_FNICKCHANGE = 0L;
93 long SNO_QLINE = 0L;
94 long SNO_SPAMF = 0L;
95 long SNO_SNOTICE = 0L;
96 long SNO_OPER = 0L;
97 
98 long AllUmodes;		/* All umodes */
99 long SendUmodes;	/* All umodes which are sent to other servers (global umodes) */
100 
umode_init(void)101 void	umode_init(void)
102 {
103 	long val = 1;
104 	int	i;
105 	Usermode_Table = MyMalloc(sizeof(Umode) * UMODETABLESZ);
106 	bzero(Usermode_Table, sizeof(Umode) * UMODETABLESZ);
107 	for (i = 0; i < UMODETABLESZ; i++)
108 	{
109 		Usermode_Table[i].mode = val;
110 		val *= 2;
111 	}
112 	Usermode_highest = 0;
113 
114 	Snomask_Table = MyMalloc(sizeof(Snomask) * UMODETABLESZ);
115 	bzero(Snomask_Table, sizeof(Snomask) * UMODETABLESZ);
116 	val = 1;
117 	for (i = 0; i < UMODETABLESZ; i++)
118 	{
119 		Snomask_Table[i].mode = val;
120 		val *= 2;
121 	}
122 	Snomask_highest = 0;
123 
124 	/* Set up modes */
125 	/* 2004-02-11: note: TODO: 'umode_allow_opers' is in most cases
126 	 * not completely correct since even opers shouldn't be allowed
127 	 * to set most of these flags (eg locop trying to set +N),
128 	 * it is currently handled by the m_umode() routine however,
129 	 * but it would be better if we get rid of that and switch
130 	 * completely to this umode->allowed system :). -- Syzop.
131 	 */
132 	UmodeAdd(NULL, 'i', UMODE_GLOBAL, NULL, &UMODE_INVISIBLE);
133 	UmodeAdd(NULL, 'o', UMODE_GLOBAL, umode_allow_opers, &UMODE_OPER);
134 	UmodeAdd(NULL, 'w', UMODE_GLOBAL, NULL, &UMODE_WALLOP);
135 	UmodeAdd(NULL, 'g', UMODE_GLOBAL, umode_allow_opers, &UMODE_FAILOP);
136 	UmodeAdd(NULL, 'h', UMODE_GLOBAL, NULL, &UMODE_HELPOP);
137 	UmodeAdd(NULL, 'r', UMODE_GLOBAL, NULL, &UMODE_REGNICK);
138 	UmodeAdd(NULL, 'a', UMODE_GLOBAL, umode_allow_opers, &UMODE_SADMIN);
139 	UmodeAdd(NULL, 'A', UMODE_GLOBAL, umode_allow_opers, &UMODE_ADMIN);
140 	UmodeAdd(NULL, 's', UMODE_LOCAL, NULL, &UMODE_SERVNOTICE);
141 	UmodeAdd(NULL, 'O', UMODE_LOCAL, umode_allow_opers, &UMODE_LOCOP);
142 	UmodeAdd(NULL, 'R', UMODE_GLOBAL, NULL, &UMODE_RGSTRONLY);
143 	UmodeAdd(NULL, 'T', UMODE_GLOBAL, NULL, &UMODE_NOCTCP);
144 	UmodeAdd(NULL, 'V', UMODE_GLOBAL, NULL, &UMODE_WEBTV);
145 	UmodeAdd(NULL, 'S', UMODE_GLOBAL, umode_allow_opers, &UMODE_SERVICES);
146 	UmodeAdd(NULL, 'x', UMODE_GLOBAL, NULL, &UMODE_HIDE);
147 	UmodeAdd(NULL, 'N', UMODE_GLOBAL, umode_allow_opers, &UMODE_NETADMIN);
148 	UmodeAdd(NULL, 'C', UMODE_GLOBAL, umode_allow_opers, &UMODE_COADMIN);
149 	UmodeAdd(NULL, 'W', UMODE_GLOBAL, NULL, &UMODE_WHOIS);
150 	UmodeAdd(NULL, 'q', UMODE_GLOBAL, umode_allow_opers, &UMODE_KIX);
151 	UmodeAdd(NULL, 'B', UMODE_GLOBAL, NULL, &UMODE_BOT);
152 	UmodeAdd(NULL, 'z', UMODE_GLOBAL, NULL, &UMODE_SECURE);
153 	UmodeAdd(NULL, 'v', UMODE_GLOBAL, umode_allow_opers, &UMODE_VICTIM);
154 	UmodeAdd(NULL, 'd', UMODE_GLOBAL, NULL, &UMODE_DEAF);
155 	UmodeAdd(NULL, 'H', UMODE_GLOBAL, umode_allow_opers, &UMODE_HIDEOPER);
156 	UmodeAdd(NULL, 't', UMODE_GLOBAL, NULL, &UMODE_SETHOST);
157 	UmodeAdd(NULL, 'G', UMODE_GLOBAL, NULL, &UMODE_STRIPBADWORDS);
158 	UmodeAdd(NULL, 'p', UMODE_GLOBAL, NULL, &UMODE_HIDEWHOIS);
159 	UmodeAdd(NULL, 'I', UMODE_GLOBAL, umode_allow_opers, &UMODE_HIDLE);
160 	SnomaskAdd(NULL, 'k', umode_allow_all, &SNO_KILLS);
161 	SnomaskAdd(NULL, 'c', umode_allow_opers, &SNO_CLIENT);
162 	SnomaskAdd(NULL, 'f', umode_allow_opers, &SNO_FLOOD);
163 	SnomaskAdd(NULL, 'F', umode_allow_opers, &SNO_FCLIENT);
164 	SnomaskAdd(NULL, 'j', umode_allow_opers, &SNO_JUNK);
165 	SnomaskAdd(NULL, 'v', umode_allow_opers, &SNO_VHOST);
166 	SnomaskAdd(NULL, 'e', umode_allow_opers, &SNO_EYES);
167 	SnomaskAdd(NULL, 'G', umode_allow_opers, &SNO_TKL);
168 	SnomaskAdd(NULL, 'n', umode_allow_opers, &SNO_NICKCHANGE);
169 	SnomaskAdd(NULL, 'N', umode_allow_opers, &SNO_FNICKCHANGE);
170 	SnomaskAdd(NULL, 'q', umode_allow_opers, &SNO_QLINE);
171 	SnomaskAdd(NULL, 'S', umode_allow_opers, &SNO_SPAMF);
172 	SnomaskAdd(NULL, 's', umode_allow_all, &SNO_SNOTICE);
173 	SnomaskAdd(NULL, 'o', umode_allow_opers, &SNO_OPER);
174 }
175 
make_umodestr(void)176 void make_umodestr(void)
177 {
178 	int i;
179 	char *m;
180 
181 	m = umodestring;
182 	for (i = 0; i <= Usermode_highest; i++)
183 	{
184 		if (Usermode_Table[i].flag)
185 			*m++ = Usermode_Table[i].flag;
186 	}
187 	*m = '\0';
188 }
189 
190 /* umode_get:
191  * Add a usermode with character 'ch', if global is set to 1 the usermode is global
192  * (sent to other servers) otherwise it's a local usermode
193  */
UmodeAdd(Module * module,char ch,int global,int (* allowed)(aClient * sptr,int what),long * mode)194 Umode *UmodeAdd(Module *module, char ch, int global, int (*allowed)(aClient *sptr, int what), long *mode)
195 {
196 	short	 i = 0;
197 	short	 j = 0;
198 	short 	 save = -1;
199 	while (i < UMODETABLESZ)
200 	{
201 		if (!Usermode_Table[i].flag && save == -1)
202 			save = i;
203 		else if (Usermode_Table[i].flag == ch)
204 		{
205 			if (Usermode_Table[i].unloaded)
206 			{
207 				save = i;
208 				Usermode_Table[i].unloaded = 0;
209 				break;
210 			}
211 			else
212 			{
213 				if (module)
214 					module->errorcode = MODERR_EXISTS;
215 				return NULL;
216 			}
217 		}
218 		i++;
219 	}
220 	i = save;
221 	if (i != UMODETABLESZ)
222 	{
223 		Usermode_Table[i].flag = ch;
224 		Usermode_Table[i].allowed = allowed;
225 		Debug((DEBUG_DEBUG, "umode_get(%c) returning %04x",
226 			ch, Usermode_Table[i].mode));
227 		/* Update usermode table highest */
228 		for (j = 0; j < UMODETABLESZ; j++)
229 			if (Usermode_Table[i].flag)
230 				if (i > Usermode_highest)
231 					Usermode_highest = i;
232 		make_umodestr();
233 		AllUmodes |= Usermode_Table[i].mode;
234 		if (global)
235 			SendUmodes |= Usermode_Table[i].mode;
236 		*mode = Usermode_Table[i].mode;
237 		Usermode_Table[i].owner = module;
238 		if (module)
239 		{
240 			ModuleObject *umodeobj = MyMallocEx(sizeof(ModuleObject));
241 			umodeobj->object.umode = &(Usermode_Table[i]);
242 			umodeobj->type = MOBJ_UMODE;
243 			AddListItem(umodeobj, module->objects);
244 			module->errorcode = MODERR_NOERROR;
245 		}
246 		return &(Usermode_Table[i]);
247 	}
248 	else
249 	{
250 		Debug((DEBUG_DEBUG, "UmodeAdd failed, no space"));
251 		if (module)
252 			module->errorcode = MODERR_NOSPACE;
253 		return NULL;
254 	}
255 }
256 
257 
UmodeDel(Umode * umode)258 void UmodeDel(Umode *umode)
259 {
260 	if (loop.ircd_rehashing)
261 		umode->unloaded = 1;
262 	else
263 	{
264 		aClient *cptr;
265 		for (cptr = client; cptr; cptr = cptr->next)
266 		{
267 			long oldumode = 0;
268 			if (!IsPerson(cptr))
269 				continue;
270 			oldumode = cptr->umodes;
271 			cptr->umodes &= ~umode->mode;
272 			if (MyClient(cptr))
273 				send_umode_out(cptr, cptr, oldumode);
274 		}
275 		umode->flag = '\0';
276 		AllUmodes &= ~(umode->mode);
277 		SendUmodes &= ~(umode->mode);
278 		make_umodestr();
279 	}
280 
281 	if (umode->owner) {
282 		ModuleObject *umodeobj;
283 		for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next) {
284 			if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode) {
285 				DelListItem(umodeobj, umode->owner->objects);
286 				MyFree(umodeobj);
287 				break;
288 			}
289 		}
290 		umode->owner = NULL;
291 	}
292 	return;
293 }
294 
SnomaskAdd(Module * module,char ch,int (* allowed)(aClient * sptr,int what),long * mode)295 Snomask *SnomaskAdd(Module *module, char ch, int (*allowed)(aClient *sptr, int what), long *mode)
296 {
297 	short	 i = 0;
298 	short	 j = 0;
299 	short 	 save = -1;
300 	while (i < UMODETABLESZ)
301 	{
302 		if (!Snomask_Table[i].flag && save == -1)
303 			save = i;
304 		else if (Snomask_Table[i].flag == ch)
305 		{
306 			if (Snomask_Table[i].unloaded)
307 			{
308 				save = i;
309 				Snomask_Table[i].unloaded = 0;
310 				break;
311 			}
312 			else
313 			{
314 				if (module)
315 					module->errorcode = MODERR_EXISTS;
316 				return NULL;
317 			}
318 		}
319 		i++;
320 	}
321 	i = save;
322 	if (i != UMODETABLESZ)
323 	{
324 		Snomask_Table[i].flag = ch;
325 		Snomask_Table[i].allowed = allowed;
326 		/* Update usermode table highest */
327 		for (j = 0; j < UMODETABLESZ; j++)
328 			if (Snomask_Table[i].flag)
329 				if (i > Snomask_highest)
330 					Snomask_highest = i;
331 		*mode = Snomask_Table[i].mode;
332 		Snomask_Table[i].owner = module;
333 		if (module)
334 		{
335 			ModuleObject *snoobj = MyMallocEx(sizeof(ModuleObject));
336 			snoobj->object.snomask = &(Snomask_Table[i]);
337 			snoobj->type = MOBJ_SNOMASK;
338 			AddListItem(snoobj, module->objects);
339 			module->errorcode = MODERR_NOERROR;
340 		}
341 		return &(Snomask_Table[i]);
342 	}
343 	else
344 	{
345 		Debug((DEBUG_DEBUG, "SnomaskAdd failed, no space"));
346 		*mode = 0;
347 		if (module)
348 			module->errorcode = MODERR_NOSPACE;
349 		return NULL;
350 	}
351 }
352 
SnomaskDel(Snomask * sno)353 void SnomaskDel(Snomask *sno)
354 {
355 	if (loop.ircd_rehashing)
356 		sno->unloaded = 1;
357 	else
358 	{
359 		int i;
360 		for (i = 0; i <= LastSlot; i++)
361 		{
362 			aClient *cptr = local[i];
363 			long oldsno;
364 			if (!cptr || !IsPerson(cptr))
365 				continue;
366 			oldsno = cptr->user->snomask;
367 			cptr->user->snomask &= ~sno->mode;
368 			if (oldsno != cptr->user->snomask)
369 				sendto_one(cptr, rpl_str(RPL_SNOMASK), me.name,
370 					cptr->name, get_snostr(cptr->user->snomask));
371 		}
372 		sno->flag = '\0';
373 	}
374 	if (sno->owner) {
375 		ModuleObject *snoobj;
376 		for (snoobj = sno->owner->objects; snoobj; snoobj = snoobj->next) {
377 			if (snoobj->type == MOBJ_SNOMASK && snoobj->object.snomask == sno) {
378 				DelListItem(snoobj, sno->owner->objects);
379 				MyFree(snoobj);
380 				break;
381 			}
382 		}
383 		sno->owner = NULL;
384 	}
385 	return;
386 }
387 
umode_allow_all(aClient * sptr,int what)388 int umode_allow_all(aClient *sptr, int what)
389 {
390 	return 1;
391 }
392 
umode_allow_opers(aClient * sptr,int what)393 int umode_allow_opers(aClient *sptr, int what)
394 {
395 	if (MyClient(sptr))
396 		return IsAnOper(sptr) ? 1 : 0;
397 	else
398 		return 1;
399 }
400 
unload_all_unused_umodes()401 void unload_all_unused_umodes()
402 {
403 	long removed_umode = 0;
404 	int i;
405 	aClient *cptr;
406 	for (i = 0; i < UMODETABLESZ; i++)
407 	{
408 		if (Usermode_Table[i].unloaded)
409 			removed_umode |= Usermode_Table[i].mode;
410 	}
411 	if (!removed_umode) /* Nothing was unloaded */
412 		return;
413 	for (cptr = client; cptr; cptr = cptr->next)
414 	{
415 		long oldumode = 0;
416 		if (!IsPerson(cptr))
417 			continue;
418 		oldumode = cptr->umodes;
419 		cptr->umodes &= ~(removed_umode);
420 		if (MyClient(cptr))
421 			send_umode_out(cptr, cptr, oldumode);
422 	}
423 	for (i = 0; i < UMODETABLESZ; i++)
424 	{
425 		if (Usermode_Table[i].unloaded)
426 		{
427 			AllUmodes &= ~(Usermode_Table[i].mode);
428 			SendUmodes &= ~(Usermode_Table[i].mode);
429 			Usermode_Table[i].flag = '\0';
430 			Usermode_Table[i].unloaded = 0;
431 		}
432 	}
433 	make_umodestr();
434 }
435 
unload_all_unused_snomasks()436 void unload_all_unused_snomasks()
437 {
438 	long removed_sno = 0;
439 	int i;
440 
441 	for (i = 0; i < UMODETABLESZ; i++)
442 	{
443 		if (Snomask_Table[i].unloaded)
444 		{
445 			removed_sno |= Snomask_Table[i].mode;
446 			Snomask_Table[i].flag = '\0';
447 			Snomask_Table[i].unloaded = 0;
448 		}
449 	}
450 	if (!removed_sno) /* Nothing was unloaded */
451 		return;
452 	for (i = 0; i <= LastSlot; i++)
453 	{
454 		aClient *cptr = local[i];
455 		long oldsno;
456 		if (!cptr || !IsPerson(cptr))
457 			continue;
458 		oldsno = cptr->user->snomask;
459 		cptr->user->snomask &= ~(removed_sno);
460 		if (oldsno != cptr->user->snomask)
461 			sendto_one(cptr, rpl_str(RPL_SNOMASK), me.name,
462 				cptr->name, get_snostr(cptr->user->snomask));
463 
464 	}
465 }
466 
umode_get(char ch,int options,int (* allowed)(aClient * sptr,int what))467 long umode_get(char ch, int options, int (*allowed)(aClient *sptr, int what))
468 {
469 	long flag;
470 	if (UmodeAdd(NULL, ch, options, allowed, &flag))
471 		return flag;
472 	return 0;
473 }
474 
umode_delete(char ch,long val)475 int umode_delete(char ch, long val)
476 {
477 	int i;
478 	for (i = 0; i < UMODETABLESZ; i++)
479 	{
480 		if (Usermode_Table[i].flag == ch && Usermode_Table[i].mode == val)
481 		{
482 			UmodeDel(&Usermode_Table[i]);
483 			return 1;
484 		}
485 	}
486 	return -1;
487 }
488 
489 /**
490  * Simply non-perfect function to remove all oper-snomasks,
491  * it's at least better than manually doing a .. &= ~SNO_BLAH everywhere.
492  *
493  * Also unsets all snomasks and UMODE_SERVNOTICE if it would seem the
494  * user doesn't deserve to have snomask after being deopered. This is
495  * simpler, but hackier, than actually recording whether or not the
496  * user already had some snomasks set before OPERing and then reset
497  * his stuff to that... --binki
498  */
remove_oper_snomasks(aClient * sptr)499 void remove_oper_snomasks(aClient *sptr)
500 {
501 int i;
502 	/*
503 	 * See #3329
504 	 */
505 	if (sptr->umodes & UMODE_SERVNOTICE
506 	    && RESTRICT_USERMODES
507 	    && strchr(RESTRICT_USERMODES, 's')
508 	    && !(CONN_MODES & UMODE_SERVNOTICE))
509 	{
510 		sptr->umodes &= ~UMODE_SERVNOTICE;
511 		sptr->user->snomask = 0;
512 		/* we unset all snomasks, so short-circuit */
513 		return;
514 	}
515 
516 	for (i = 0; i <= Snomask_highest; i++)
517 	{
518 		if (!Snomask_Table[i].flag)
519 			continue;
520 		if (Snomask_Table[i].allowed == umode_allow_opers)
521 			sptr->user->snomask &= ~Snomask_Table[i].mode;
522 	}
523 }
524 
525 /*
526  * Strip all 'oper only modes' from the user.
527  * This function is NOT PERFECT, see comments from the
528  * remove_oper_snomasks above.
529  */
remove_oper_modes(aClient * sptr)530 void remove_oper_modes(aClient *sptr)
531 {
532 int i;
533 
534 	for (i = 0; i <= Usermode_highest; i++)
535 	{
536 		if (!Usermode_Table[i].flag)
537 			continue;
538 		if (Usermode_Table[i].allowed == umode_allow_opers)
539 			sptr->umodes &= ~Usermode_Table[i].mode;
540 	}
541 }
542