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