]>
Commit | Line | Data |
---|---|---|
212380e3 AC |
1 | /* |
2 | * ircd-ratbox: A slightly useful ircd. | |
3 | * m_gline.c: Votes towards globally banning a mask. | |
4 | * | |
5 | * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center | |
6 | * Copyright (C) 1996-2002 Hybrid Development Team | |
7 | * Copyright (C) 2002-2005 ircd-ratbox development team | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
22 | * USA | |
23 | * | |
61569b65 | 24 | * $Id: m_gline.c 3225 2007-03-04 23:42:55Z jilles $ |
212380e3 AC |
25 | */ |
26 | ||
27 | #include "stdinc.h" | |
212380e3 AC |
28 | #include "s_gline.h" |
29 | #include "channel.h" | |
30 | #include "client.h" | |
31 | #include "common.h" | |
32 | #include "config.h" | |
33 | #include "irc_string.h" | |
34 | #include "sprintf_irc.h" | |
35 | #include "ircd.h" | |
36 | #include "hostmask.h" | |
37 | #include "numeric.h" | |
212380e3 AC |
38 | #include "s_conf.h" |
39 | #include "s_newconf.h" | |
40 | #include "scache.h" | |
41 | #include "send.h" | |
42 | #include "msg.h" | |
43 | #include "s_serv.h" | |
44 | #include "hash.h" | |
45 | #include "parse.h" | |
46 | #include "modules.h" | |
47 | #include "s_log.h" | |
35f6f850 | 48 | #include "reject.h" |
212380e3 AC |
49 | |
50 | static int mo_gline(struct Client *, struct Client *, int, const char **); | |
51 | static int mc_gline(struct Client *, struct Client *, int, const char **); | |
52 | static int ms_gline(struct Client *, struct Client *, int, const char **); | |
53 | static int mo_ungline(struct Client *, struct Client *, int, const char **); | |
54 | ||
55 | struct Message gline_msgtab = { | |
56 | "GLINE", 0, 0, 0, MFLG_SLOW, | |
57 | {mg_unreg, mg_not_oper, {mc_gline, 3}, {ms_gline, 7}, mg_ignore, {mo_gline, 3}} | |
58 | }; | |
59 | struct Message ungline_msgtab = { | |
60 | "UNGLINE", 0, 0, 0, MFLG_SLOW, | |
61 | {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_ungline, 2}} | |
62 | }; | |
63 | ||
64 | mapi_clist_av1 gline_clist[] = { &gline_msgtab, &ungline_msgtab, NULL }; | |
61569b65 | 65 | DECLARE_MODULE_AV1(gline, NULL, NULL, gline_clist, NULL, NULL, "$Revision: 3225 $"); |
212380e3 AC |
66 | |
67 | static int majority_gline(struct Client *source_p, const char *user, | |
68 | const char *host, const char *reason); | |
69 | static void set_local_gline(struct Client *source_p, const char *user, | |
70 | const char *host, const char *reason); | |
71 | ||
72 | static int check_wild_gline(const char *, const char *); | |
73 | static int invalid_gline(struct Client *, const char *, const char *, char *); | |
74 | ||
75 | static int remove_temp_gline(const char *, const char *); | |
76 | ||
77 | ||
78 | /* mo_gline() | |
79 | * | |
80 | * inputs - The usual for a m_ function | |
81 | * output - | |
82 | * side effects - place a gline if 3 opers agree | |
83 | */ | |
84 | static int | |
85 | mo_gline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) | |
86 | { | |
87 | const char *user = NULL; | |
88 | char *host = NULL; /* user and host of GLINE "victim" */ | |
89 | char *reason = NULL; /* reason for "victims" demise */ | |
90 | char splat[] = "*"; | |
91 | char *ptr; | |
92 | ||
93 | if(!ConfigFileEntry.glines) | |
94 | { | |
5366977b | 95 | sendto_one_notice(source_p, ":GLINE disabled, perhaps you want a clustered or remote KLINE?"); |
212380e3 AC |
96 | return 0; |
97 | } | |
98 | ||
99 | if(!IsOperGline(source_p)) | |
100 | { | |
101 | sendto_one(source_p, form_str(ERR_NOPRIVS), | |
102 | me.name, source_p->name, "gline"); | |
103 | return 0; | |
104 | } | |
105 | ||
106 | host = strchr(parv[1], '@'); | |
107 | ||
108 | /* specific user@host */ | |
109 | if(host != NULL) | |
110 | { | |
111 | user = parv[1]; | |
112 | *(host++) = '\0'; | |
113 | ||
114 | /* gline for "@host", use *@host */ | |
115 | if(*user == '\0') | |
116 | user = splat; | |
117 | } | |
118 | /* just a host? */ | |
119 | else | |
120 | { | |
121 | /* ok, its not a host.. abort */ | |
122 | if(strchr(parv[1], '.') == NULL) | |
123 | { | |
5366977b | 124 | sendto_one_notice(source_p, ":Invalid parameters"); |
212380e3 AC |
125 | return 0; |
126 | } | |
127 | ||
128 | user = splat; | |
129 | host = LOCAL_COPY(parv[1]); | |
130 | } | |
131 | ||
132 | reason = LOCAL_COPY(parv[2]); | |
133 | ||
134 | if(invalid_gline(source_p, user, host, reason)) | |
135 | return 0; | |
136 | ||
137 | /* Not enough non-wild characters were found, assume they are trying to gline *@*. */ | |
138 | if(check_wild_gline(user, host)) | |
139 | { | |
140 | if(MyClient(source_p)) | |
5366977b AC |
141 | sendto_one_notice(source_p, |
142 | ":Please include at least %d non-wildcard characters with the user@host", | |
212380e3 AC |
143 | ConfigFileEntry.min_nonwildcard); |
144 | return 0; | |
145 | } | |
146 | ||
147 | if((ptr = strchr(host, '/')) != NULL) | |
148 | { | |
149 | int bitlen; | |
150 | bitlen = strtol(++ptr, NULL, 10); | |
151 | ||
152 | /* ipv4? */ | |
153 | if(strchr(host, ':') == NULL) | |
154 | { | |
155 | if(bitlen < ConfigFileEntry.gline_min_cidr) | |
156 | { | |
5366977b | 157 | sendto_one_notice(source_p, ":Cannot set G-Lines with cidr length < %d", |
212380e3 AC |
158 | ConfigFileEntry.gline_min_cidr); |
159 | return 0; | |
160 | } | |
161 | } | |
162 | /* ipv6 */ | |
163 | else if(bitlen < ConfigFileEntry.gline_min_cidr6) | |
164 | { | |
5366977b | 165 | sendto_one_notice(source_p, ":Cannot set G-Lines with cidr length < %d", |
212380e3 AC |
166 | ConfigFileEntry.gline_min_cidr6); |
167 | return 0; | |
168 | } | |
169 | } | |
170 | ||
171 | /* inform users about the gline before we call majority_gline() | |
172 | * so already voted comes below gline request --fl | |
173 | */ | |
174 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
175 | "%s!%s@%s on %s is requesting gline for [%s@%s] [%s]", | |
176 | source_p->name, source_p->username, | |
177 | source_p->host, me.name, user, host, reason); | |
178 | ilog(L_GLINE, "R %s %s %s %s %s %s %s", | |
179 | source_p->name, source_p->username, source_p->host, | |
c88cdb00 | 180 | source_p->servptr->name, user, host, reason); |
212380e3 AC |
181 | |
182 | /* If at least 3 opers agree this user should be G lined then do it */ | |
183 | majority_gline(source_p, user, host, reason); | |
184 | ||
185 | /* 4 param version for hyb-7 servers */ | |
186 | sendto_server(NULL, NULL, CAP_GLN|CAP_TS6, NOCAPS, | |
187 | ":%s GLINE %s %s :%s", | |
188 | use_id(source_p), user, host, reason); | |
189 | sendto_server(NULL, NULL, CAP_GLN, CAP_TS6, | |
190 | ":%s GLINE %s %s :%s", | |
191 | source_p->name, user, host, reason); | |
192 | ||
193 | /* 8 param for hyb-6 */ | |
194 | sendto_server(NULL, NULL, NOCAPS, CAP_GLN, | |
195 | ":%s GLINE %s %s %s %s %s %s :%s", | |
196 | me.name, source_p->name, source_p->username, | |
c88cdb00 | 197 | source_p->host, source_p->servptr->name, |
212380e3 AC |
198 | user, host, reason); |
199 | return 0; | |
200 | } | |
201 | ||
202 | /* mc_gline() | |
203 | */ | |
204 | static int | |
205 | mc_gline(struct Client *client_p, struct Client *source_p, | |
206 | int parc, const char *parv[]) | |
207 | { | |
208 | struct Client *acptr; | |
209 | const char *user; | |
210 | const char *host; | |
211 | char *reason; | |
212 | char *ptr; | |
213 | ||
214 | /* hyb6 allows empty gline reasons */ | |
215 | if(parc < 4 || EmptyString(parv[3])) | |
216 | return 0; | |
217 | ||
218 | acptr = source_p; | |
219 | ||
220 | user = parv[1]; | |
221 | host = parv[2]; | |
222 | reason = LOCAL_COPY(parv[3]); | |
223 | ||
224 | if(invalid_gline(acptr, user, host, reason)) | |
225 | return 0; | |
226 | ||
227 | sendto_server(client_p, NULL, CAP_GLN|CAP_TS6, NOCAPS, | |
228 | ":%s GLINE %s %s :%s", | |
229 | use_id(acptr), user, host, reason); | |
230 | sendto_server(client_p, NULL, CAP_GLN, CAP_TS6, | |
231 | ":%s GLINE %s %s :%s", | |
232 | acptr->name, user, host, reason); | |
233 | sendto_server(client_p, NULL, NOCAPS, CAP_GLN, | |
234 | ":%s GLINE %s %s %s %s %s %s :%s", | |
c88cdb00 | 235 | acptr->servptr->name, acptr->name, |
212380e3 | 236 | acptr->username, acptr->host, |
c88cdb00 | 237 | acptr->servptr->name, user, host, reason); |
212380e3 AC |
238 | |
239 | if(!ConfigFileEntry.glines) | |
240 | return 0; | |
241 | ||
242 | /* check theres enough non-wildcard chars */ | |
243 | if(check_wild_gline(user, host)) | |
244 | { | |
245 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
246 | "%s!%s@%s on %s is requesting a gline without " | |
247 | "%d non-wildcard characters for [%s@%s] [%s]", | |
248 | acptr->name, acptr->username, | |
c88cdb00 | 249 | acptr->host, acptr->servptr->name, |
212380e3 AC |
250 | ConfigFileEntry.min_nonwildcard, |
251 | user, host, reason); | |
252 | return 0; | |
253 | } | |
254 | ||
255 | if((ptr = strchr(host, '/')) != NULL) | |
256 | { | |
257 | int bitlen; | |
258 | bitlen = strtol(++ptr, NULL, 10); | |
259 | ||
260 | /* ipv4? */ | |
261 | if(strchr(host, ':') == NULL) | |
262 | { | |
263 | if(bitlen < ConfigFileEntry.gline_min_cidr) | |
264 | { | |
265 | sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s!%s@%s on %s is requesting a " | |
266 | "gline with a cidr mask < %d for [%s@%s] [%s]", | |
267 | acptr->name, acptr->username, acptr->host, | |
c88cdb00 | 268 | acptr->servptr->name, |
212380e3 AC |
269 | ConfigFileEntry.gline_min_cidr, |
270 | user, host, reason); | |
271 | return 0; | |
272 | } | |
273 | } | |
274 | /* ipv6 */ | |
275 | else if(bitlen < ConfigFileEntry.gline_min_cidr6) | |
276 | { | |
277 | sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s!%s@%s on %s is requesting a " | |
278 | "gline with a cidr mask < %d for [%s@%s] [%s]", | |
279 | acptr->name, acptr->username, acptr->host, | |
c88cdb00 | 280 | acptr->servptr->name, |
212380e3 AC |
281 | ConfigFileEntry.gline_min_cidr6, |
282 | user, host, reason); | |
283 | return 0; | |
284 | } | |
285 | } | |
286 | ||
287 | ||
288 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
289 | "%s!%s@%s on %s is requesting gline for [%s@%s] [%s]", | |
290 | acptr->name, acptr->username, acptr->host, | |
c88cdb00 | 291 | acptr->servptr->name, user, host, reason); |
212380e3 AC |
292 | |
293 | ilog(L_GLINE, "R %s %s %s %s %s %s %s", | |
294 | source_p->name, source_p->username, source_p->host, | |
c88cdb00 | 295 | source_p->servptr->name, user, host, reason); |
212380e3 AC |
296 | |
297 | /* If at least 3 opers agree this user should be G lined then do it */ | |
298 | majority_gline(acptr, user, host, reason); | |
299 | ||
300 | return 0; | |
301 | } | |
302 | ||
303 | ||
304 | /* ms_gline() | |
305 | * | |
306 | * inputs - The usual for a m_ function | |
307 | * output - | |
308 | * side effects - attempts to place a gline, if 3 opers agree | |
309 | */ | |
310 | static int | |
311 | ms_gline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) | |
312 | { | |
313 | struct Client *acptr; | |
314 | const char *user; | |
315 | const char *host; | |
316 | char *reason; | |
317 | ||
318 | /* hyb6 allows empty gline reasons */ | |
319 | if(parc < 8 || EmptyString(parv[7])) | |
320 | return 0; | |
321 | ||
322 | /* client doesnt exist.. someones messing */ | |
323 | if((acptr = find_client(parv[1])) == NULL) | |
324 | return 0; | |
325 | ||
326 | /* client that sent the gline, isnt on the server that sent | |
327 | * the gline out. somethings fucked. | |
328 | */ | |
329 | if(acptr->servptr != source_p) | |
330 | return 0; | |
331 | ||
332 | user = parv[5]; | |
333 | host = parv[6]; | |
334 | reason = LOCAL_COPY(parv[7]); | |
335 | ||
336 | if(invalid_gline(acptr, user, host, reason)) | |
337 | return 0; | |
338 | ||
339 | sendto_server(client_p, NULL, CAP_GLN|CAP_TS6, NOCAPS, | |
340 | ":%s GLINE %s %s :%s", | |
341 | use_id(acptr), user, host, reason); | |
342 | sendto_server(client_p, NULL, CAP_GLN, CAP_TS6, | |
343 | ":%s GLINE %s %s :%s", | |
344 | acptr->name, user, host, reason); | |
345 | sendto_server(client_p, NULL, NOCAPS, CAP_GLN, | |
346 | ":%s GLINE %s %s %s %s %s %s :%s", | |
c88cdb00 | 347 | acptr->servptr->name, acptr->name, |
212380e3 | 348 | acptr->username, acptr->host, |
c88cdb00 | 349 | acptr->servptr->name, user, host, reason); |
212380e3 AC |
350 | |
351 | if(!ConfigFileEntry.glines) | |
352 | return 0; | |
353 | ||
354 | /* check theres enough non-wildcard chars */ | |
355 | if(check_wild_gline(user, host)) | |
356 | { | |
357 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
358 | "%s!%s@%s on %s is requesting a gline without " | |
359 | "%d non-wildcard characters for [%s@%s] [%s]", | |
360 | acptr->name, acptr->username, | |
c88cdb00 | 361 | acptr->host, acptr->servptr->name, |
212380e3 AC |
362 | ConfigFileEntry.min_nonwildcard, |
363 | user, host, reason); | |
364 | return 0; | |
365 | } | |
366 | ||
367 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
368 | "%s!%s@%s on %s is requesting gline for [%s@%s] [%s]", | |
369 | acptr->name, acptr->username, acptr->host, | |
c88cdb00 | 370 | acptr->servptr->name, user, host, reason); |
212380e3 AC |
371 | |
372 | ilog(L_GLINE, "R %s %s %s %s %s %s %s", | |
373 | acptr->name, acptr->username, acptr->host, | |
c88cdb00 | 374 | acptr->servptr->name, user, host, reason); |
212380e3 AC |
375 | |
376 | /* If at least 3 opers agree this user should be G lined then do it */ | |
377 | majority_gline(acptr, user, host, reason); | |
378 | ||
379 | return 0; | |
380 | } | |
381 | ||
382 | /* mo_ungline() | |
383 | * | |
384 | * parv[0] = sender nick | |
385 | * parv[1] = gline to remove | |
386 | */ | |
387 | static int | |
388 | mo_ungline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) | |
389 | { | |
390 | const char *user; | |
391 | char *h = LOCAL_COPY(parv[1]); | |
392 | char *host; | |
393 | char splat[] = "*"; | |
394 | ||
395 | if(!ConfigFileEntry.glines) | |
396 | { | |
5366977b | 397 | sendto_one_notice(source_p, ":UNGLINE disabled, perhaps you want UNKLINE?"); |
212380e3 AC |
398 | return 0; |
399 | } | |
400 | ||
401 | if(!IsOperUnkline(source_p) || !IsOperGline(source_p)) | |
402 | { | |
403 | sendto_one(source_p, form_str(ERR_NOPRIVS), | |
404 | me.name, source_p->name, "unkline"); | |
405 | return 0; | |
406 | } | |
407 | ||
408 | if((host = strchr(h, '@')) || *h == '*') | |
409 | { | |
410 | /* Explicit user@host mask given */ | |
411 | ||
412 | if(host) | |
413 | { | |
414 | *host++ = '\0'; | |
415 | ||
416 | /* check for @host */ | |
417 | if(*h) | |
418 | user = h; | |
419 | else | |
420 | user = splat; | |
421 | ||
422 | if(!*host) | |
423 | host = splat; | |
424 | } | |
425 | else | |
426 | { | |
427 | user = splat; | |
428 | host = h; | |
429 | } | |
430 | } | |
431 | else | |
432 | { | |
5366977b | 433 | sendto_one_notice(source_p, ":Invalid parameters"); |
212380e3 AC |
434 | return 0; |
435 | } | |
436 | ||
437 | if(remove_temp_gline(user, host)) | |
438 | { | |
5366977b | 439 | sendto_one_notice(source_p, ":Un-glined [%s@%s]", user, host); |
212380e3 AC |
440 | sendto_realops_snomask(SNO_GENERAL, L_ALL, |
441 | "%s has removed the G-Line for: [%s@%s]", | |
442 | get_oper_name(source_p), user, host); | |
443 | ilog(L_GLINE, "U %s %s %s %s %s %s", | |
444 | source_p->name, source_p->username, source_p->host, | |
c88cdb00 | 445 | source_p->servptr->name, user, host); |
212380e3 AC |
446 | } |
447 | else | |
448 | { | |
5366977b | 449 | sendto_one_notice(source_p, ":No G-Line for %s@%s", user, host); |
212380e3 AC |
450 | } |
451 | ||
452 | return 0; | |
453 | } | |
454 | ||
455 | /* | |
456 | * check_wild_gline | |
457 | * | |
458 | * inputs - user, host of gline | |
459 | * output - 1 if not enough non-wildchar char's, 0 if ok | |
460 | * side effects - NONE | |
461 | */ | |
462 | static int | |
463 | check_wild_gline(const char *user, const char *host) | |
464 | { | |
465 | const char *p; | |
466 | char tmpch; | |
467 | int nonwild; | |
468 | ||
469 | nonwild = 0; | |
470 | p = user; | |
471 | ||
472 | while ((tmpch = *p++)) | |
473 | { | |
474 | if(!IsKWildChar(tmpch)) | |
475 | { | |
476 | /* enough of them, break */ | |
477 | if(++nonwild >= ConfigFileEntry.min_nonwildcard) | |
478 | break; | |
479 | } | |
480 | } | |
481 | ||
482 | if(nonwild < ConfigFileEntry.min_nonwildcard) | |
483 | { | |
484 | /* user doesnt, try host */ | |
485 | p = host; | |
486 | while ((tmpch = *p++)) | |
487 | { | |
488 | if(!IsKWildChar(tmpch)) | |
489 | if(++nonwild >= ConfigFileEntry.min_nonwildcard) | |
490 | break; | |
491 | } | |
492 | } | |
493 | ||
494 | if(nonwild < ConfigFileEntry.min_nonwildcard) | |
495 | return 1; | |
496 | else | |
497 | return 0; | |
498 | } | |
499 | ||
500 | /* invalid_gline | |
501 | * | |
502 | * inputs - pointer to source client, ident, host and reason | |
503 | * outputs - 1 if invalid, 0 if valid | |
504 | * side effects - | |
505 | */ | |
506 | static int | |
507 | invalid_gline(struct Client *source_p, const char *luser, | |
508 | const char *lhost, char *lreason) | |
509 | { | |
510 | if(strchr(luser, '!')) | |
511 | { | |
5366977b | 512 | sendto_one_notice(source_p, ":Invalid character '!' in gline"); |
212380e3 AC |
513 | return 1; |
514 | } | |
515 | ||
61569b65 JT |
516 | if(strlen(lreason) > BANREASONLEN) |
517 | lreason[BANREASONLEN] = '\0'; | |
212380e3 AC |
518 | |
519 | return 0; | |
520 | } | |
521 | ||
522 | /* | |
523 | * set_local_gline | |
524 | * | |
525 | * inputs - pointer to oper nick/username/host/server, | |
526 | * victim user/host and reason | |
527 | * output - NONE | |
528 | * side effects - | |
529 | */ | |
530 | static void | |
531 | set_local_gline(struct Client *source_p, const char *user, | |
532 | const char *host, const char *reason) | |
533 | { | |
534 | char buffer[IRCD_BUFSIZE]; | |
535 | struct ConfItem *aconf; | |
536 | const char *current_date; | |
537 | char *my_reason; | |
538 | char *oper_reason; | |
539 | ||
540 | current_date = smalldate(); | |
541 | ||
542 | my_reason = LOCAL_COPY(reason); | |
543 | ||
544 | aconf = make_conf(); | |
545 | aconf->status = CONF_GLINE; | |
546 | aconf->flags |= CONF_FLAGS_TEMPORARY; | |
547 | ||
61569b65 JT |
548 | if(strlen(my_reason) > BANREASONLEN) |
549 | my_reason[BANREASONLEN-1] = '\0'; | |
212380e3 AC |
550 | |
551 | if((oper_reason = strchr(my_reason, '|')) != NULL) | |
552 | { | |
553 | *oper_reason = '\0'; | |
554 | oper_reason++; | |
555 | ||
556 | if(!EmptyString(oper_reason)) | |
47a03750 | 557 | aconf->spasswd = rb_strdup(oper_reason); |
212380e3 AC |
558 | } |
559 | ||
7cdb0a09 | 560 | rb_snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date); |
212380e3 | 561 | |
47a03750 VY |
562 | aconf->passwd = rb_strdup(buffer); |
563 | aconf->user = rb_strdup(user); | |
564 | aconf->host = rb_strdup(host); | |
212380e3 AC |
565 | aconf->hold = CurrentTime + ConfigFileEntry.gline_time; |
566 | add_gline(aconf); | |
567 | ||
568 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
569 | "%s!%s@%s on %s has triggered gline for [%s@%s] [%s]", | |
570 | source_p->name, source_p->username, | |
c88cdb00 | 571 | source_p->host, source_p->servptr->name, |
212380e3 AC |
572 | user, host, reason); |
573 | ilog(L_GLINE, "T %s %s %s %s %s %s %s", | |
574 | source_p->name, source_p->username, source_p->host, | |
c88cdb00 | 575 | source_p->servptr->name, user, host, reason); |
212380e3 AC |
576 | |
577 | check_glines(); | |
578 | } | |
579 | ||
580 | /* majority_gline() | |
581 | * | |
582 | * input - client doing gline, user, host and reason of gline | |
583 | * output - YES if there are 3 different opers/servers agree, else NO | |
584 | * side effects - | |
585 | */ | |
586 | static int | |
587 | majority_gline(struct Client *source_p, const char *user, | |
588 | const char *host, const char *reason) | |
589 | { | |
5b96d9a6 | 590 | rb_dlink_node *pending_node; |
212380e3 AC |
591 | struct gline_pending *pending; |
592 | ||
593 | /* to avoid desync.. --fl */ | |
594 | cleanup_glines(NULL); | |
595 | ||
596 | /* if its already glined, why bother? :) -- fl_ */ | |
597 | if(find_is_glined(host, user)) | |
598 | return NO; | |
599 | ||
5b96d9a6 | 600 | RB_DLINK_FOREACH(pending_node, pending_glines.head) |
212380e3 AC |
601 | { |
602 | pending = pending_node->data; | |
603 | ||
604 | if((irccmp(pending->user, user) == 0) && | |
605 | (irccmp(pending->host, host) == 0)) | |
606 | { | |
607 | /* check oper or server hasnt already voted */ | |
608 | if(((irccmp(pending->oper_user1, source_p->username) == 0) || | |
609 | (irccmp(pending->oper_host1, source_p->host) == 0))) | |
610 | { | |
611 | sendto_realops_snomask(SNO_GENERAL, L_ALL, "oper has already voted"); | |
612 | return NO; | |
613 | } | |
c88cdb00 | 614 | else if(irccmp(pending->oper_server1, source_p->servptr->name) == 0) |
212380e3 AC |
615 | { |
616 | sendto_realops_snomask(SNO_GENERAL, L_ALL, "server has already voted"); | |
617 | return NO; | |
618 | } | |
619 | ||
620 | if(pending->oper_user2[0] != '\0') | |
621 | { | |
622 | /* if two other opers on two different servers have voted yes */ | |
623 | if(((irccmp(pending->oper_user2, source_p->username) == 0) || | |
624 | (irccmp(pending->oper_host2, source_p->host) == 0))) | |
625 | { | |
626 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
627 | "oper has already voted"); | |
628 | return NO; | |
629 | } | |
c88cdb00 | 630 | else if(irccmp(pending->oper_server2, source_p->servptr->name) == 0) |
212380e3 AC |
631 | { |
632 | sendto_realops_snomask(SNO_GENERAL, L_ALL, | |
633 | "server has already voted"); | |
634 | return NO; | |
635 | } | |
636 | ||
637 | /* trigger the gline using the original reason --fl */ | |
638 | set_local_gline(source_p, user, host, | |
639 | pending->reason1); | |
640 | ||
641 | cleanup_glines(NULL); | |
642 | return YES; | |
643 | } | |
644 | else | |
645 | { | |
646 | strlcpy(pending->oper_nick2, source_p->name, | |
647 | sizeof(pending->oper_nick2)); | |
648 | strlcpy(pending->oper_user2, source_p->username, | |
649 | sizeof(pending->oper_user2)); | |
650 | strlcpy(pending->oper_host2, source_p->host, | |
651 | sizeof(pending->oper_host2)); | |
47a03750 | 652 | pending->reason2 = rb_strdup(reason); |
994544c2 | 653 | pending->oper_server2 = scache_get_name(source_p->servptr->serv->nameinfo); |
212380e3 AC |
654 | pending->last_gline_time = CurrentTime; |
655 | pending->time_request2 = CurrentTime; | |
656 | return NO; | |
657 | } | |
658 | } | |
659 | } | |
660 | ||
661 | /* no pending gline, create a new one */ | |
662 | pending = (struct gline_pending *) | |
eddc2ab6 | 663 | rb_malloc(sizeof(struct gline_pending)); |
212380e3 AC |
664 | |
665 | strlcpy(pending->oper_nick1, source_p->name, | |
666 | sizeof(pending->oper_nick1)); | |
667 | strlcpy(pending->oper_user1, source_p->username, | |
668 | sizeof(pending->oper_user1)); | |
669 | strlcpy(pending->oper_host1, source_p->host, | |
670 | sizeof(pending->oper_host1)); | |
671 | ||
994544c2 | 672 | pending->oper_server1 = scache_get_name(source_p->servptr->serv->nameinfo); |
212380e3 AC |
673 | |
674 | strlcpy(pending->user, user, sizeof(pending->user)); | |
675 | strlcpy(pending->host, host, sizeof(pending->host)); | |
47a03750 | 676 | pending->reason1 = rb_strdup(reason); |
212380e3 AC |
677 | pending->reason2 = NULL; |
678 | ||
679 | pending->last_gline_time = CurrentTime; | |
680 | pending->time_request1 = CurrentTime; | |
681 | ||
7018b86a | 682 | rb_dlinkAddAlloc(pending, &pending_glines); |
212380e3 AC |
683 | |
684 | return NO; | |
685 | } | |
686 | ||
687 | /* remove_temp_gline() | |
688 | * | |
689 | * inputs - username, hostname to ungline | |
690 | * outputs - | |
691 | * side effects - tries to ungline anything that matches | |
692 | */ | |
693 | static int | |
694 | remove_temp_gline(const char *user, const char *host) | |
695 | { | |
696 | struct ConfItem *aconf; | |
5b96d9a6 | 697 | rb_dlink_node *ptr; |
212380e3 AC |
698 | struct irc_sockaddr_storage addr, caddr; |
699 | int bits, cbits; | |
700 | int mtype, gtype; | |
701 | ||
702 | mtype = parse_netmask(host, (struct sockaddr *)&addr, &bits); | |
703 | ||
5b96d9a6 | 704 | RB_DLINK_FOREACH(ptr, glines.head) |
212380e3 AC |
705 | { |
706 | aconf = ptr->data; | |
707 | ||
708 | gtype = parse_netmask(aconf->host, (struct sockaddr *)&caddr, &cbits); | |
709 | ||
710 | if(gtype != mtype || (user && irccmp(user, aconf->user))) | |
711 | continue; | |
712 | ||
713 | if(gtype == HM_HOST) | |
714 | { | |
715 | if(irccmp(aconf->host, host)) | |
716 | continue; | |
717 | } | |
718 | else if(bits != cbits || | |
719 | !comp_with_mask_sock((struct sockaddr *)&addr, | |
720 | (struct sockaddr *)&caddr, bits)) | |
721 | continue; | |
722 | ||
555ac41f | 723 | rb_dlinkDestroy(ptr, &glines); |
35f6f850 | 724 | remove_reject_mask(aconf->user, aconf->host); |
212380e3 AC |
725 | delete_one_address_conf(aconf->host, aconf); |
726 | return YES; | |
727 | } | |
728 | ||
729 | return NO; | |
730 | } |