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