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