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