/[svn]/ircd-hybrid-8/src/conf.c
ViewVC logotype

Contents of /ircd-hybrid-8/src/conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1417 - (show annotations)
Sat May 26 11:51:19 2012 UTC (8 years, 2 months ago) by michael
File MIME type: text/x-chdr
File size: 93520 byte(s)
- "STATS Y|y" now reports CIDR limits as well

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * conf.c: Configuration file functions.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h"
27 #include "ircd_defs.h"
28 #include "balloc.h"
29 #include "conf.h"
30 #include "s_serv.h"
31 #include "resv.h"
32 #include "channel.h"
33 #include "client.h"
34 #include "event.h"
35 #include "hook.h"
36 #include "irc_string.h"
37 #include "s_bsd.h"
38 #include "ircd.h"
39 #include "listener.h"
40 #include "hostmask.h"
41 #include "modules.h"
42 #include "numeric.h"
43 #include "fdlist.h"
44 #include "log.h"
45 #include "send.h"
46 #include "s_gline.h"
47 #include "memory.h"
48 #include "irc_res.h"
49 #include "userhost.h"
50 #include "s_user.h"
51 #include "channel_mode.h"
52 #include "parse.h"
53 #include "s_misc.h"
54
55 struct Callback *client_check_cb = NULL;
56 struct config_server_hide ConfigServerHide;
57
58 /* general conf items link list root, other than k lines etc. */
59 dlink_list service_items = { NULL, NULL, 0 };
60 dlink_list server_items = { NULL, NULL, 0 };
61 dlink_list cluster_items = { NULL, NULL, 0 };
62 dlink_list oconf_items = { NULL, NULL, 0 };
63 dlink_list uconf_items = { NULL, NULL, 0 };
64 dlink_list xconf_items = { NULL, NULL, 0 };
65 dlink_list rxconf_items = { NULL, NULL, 0 };
66 dlink_list rkconf_items = { NULL, NULL, 0 };
67 dlink_list nresv_items = { NULL, NULL, 0 };
68 dlink_list class_items = { NULL, NULL, 0 };
69 dlink_list gdeny_items = { NULL, NULL, 0 };
70
71 dlink_list temporary_xlines = { NULL, NULL, 0 };
72 dlink_list temporary_resv = { NULL, NULL, 0 };
73
74 extern unsigned int lineno;
75 extern char linebuf[];
76 extern char conffilebuf[IRCD_BUFSIZE];
77 extern int yyparse(); /* defined in y.tab.c */
78
79 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
80
81 /* internally defined functions */
82 static void read_conf(FILE *);
83 static void clear_out_old_conf(void);
84 static void flush_deleted_I_P(void);
85 static void expire_tklines(dlink_list *);
86 static void garbage_collect_ip_entries(void);
87 static int hash_ip(struct irc_ssaddr *);
88 static int verify_access(struct Client *, const char *);
89 static int attach_iline(struct Client *, struct ConfItem *);
90 static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
91 static void parse_conf_file(int, int);
92 static dlink_list *map_to_list(ConfType);
93 static struct AccessItem *find_regexp_kline(const char *[]);
94 static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
95
96 /*
97 * bit_len
98 */
99 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
100 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
101 static void destroy_cidr_class(struct ClassItem *);
102
103 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
104
105 /* address of default class conf */
106 static struct ConfItem *class_default;
107
108 /* usually, with hash tables, you use a prime number...
109 * but in this case I am dealing with ip addresses,
110 * not ascii strings.
111 */
112 #define IP_HASH_SIZE 0x1000
113
114 struct ip_entry
115 {
116 struct irc_ssaddr ip;
117 int count;
118 time_t last_attempt;
119 struct ip_entry *next;
120 };
121
122 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
123 static BlockHeap *ip_entry_heap = NULL;
124 static int ip_entries_count = 0;
125
126
127 void *
128 map_to_conf(struct ConfItem *aconf)
129 {
130 void *conf;
131 conf = (void *)((uintptr_t)aconf +
132 (uintptr_t)sizeof(struct ConfItem));
133 return(conf);
134 }
135
136 struct ConfItem *
137 unmap_conf_item(void *aconf)
138 {
139 struct ConfItem *conf;
140
141 conf = (struct ConfItem *)((uintptr_t)aconf -
142 (uintptr_t)sizeof(struct ConfItem));
143 return(conf);
144 }
145
146 /* conf_dns_callback()
147 *
148 * inputs - pointer to struct AccessItem
149 * - pointer to DNSReply reply
150 * output - none
151 * side effects - called when resolver query finishes
152 * if the query resulted in a successful search, hp will contain
153 * a non-null pointer, otherwise hp will be null.
154 * if successful save hp in the conf item it was called with
155 */
156 static void
157 conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
158 {
159 struct AccessItem *aconf = vptr;
160
161 aconf->dns_pending = 0;
162
163 if (addr != NULL)
164 memcpy(&aconf->addr, addr, sizeof(aconf->addr));
165 else
166 aconf->dns_failed = 1;
167 }
168
169 /* conf_dns_lookup()
170 *
171 * do a nameserver lookup of the conf host
172 * if the conf entry is currently doing a ns lookup do nothing, otherwise
173 * allocate a dns_query and start ns lookup.
174 */
175 static void
176 conf_dns_lookup(struct AccessItem *aconf)
177 {
178 if (!aconf->dns_pending)
179 {
180 aconf->dns_pending = 1;
181 gethost_byname(conf_dns_callback, aconf, aconf->host);
182 }
183 }
184
185 /* make_conf_item()
186 *
187 * inputs - type of item
188 * output - pointer to new conf entry
189 * side effects - none
190 */
191 struct ConfItem *
192 make_conf_item(ConfType type)
193 {
194 struct ConfItem *conf = NULL;
195 struct AccessItem *aconf = NULL;
196 struct ClassItem *aclass = NULL;
197 int status = 0;
198
199 switch (type)
200 {
201 case DLINE_TYPE:
202 case EXEMPTDLINE_TYPE:
203 case GLINE_TYPE:
204 case KLINE_TYPE:
205 case CLIENT_TYPE:
206 case OPER_TYPE:
207 case SERVER_TYPE:
208 conf = MyMalloc(sizeof(struct ConfItem) +
209 sizeof(struct AccessItem));
210 aconf = map_to_conf(conf);
211 aconf->aftype = AF_INET;
212
213 /* Yes, sigh. switch on type again */
214 switch (type)
215 {
216 case EXEMPTDLINE_TYPE:
217 status = CONF_EXEMPTDLINE;
218 break;
219
220 case DLINE_TYPE:
221 status = CONF_DLINE;
222 break;
223
224 case KLINE_TYPE:
225 status = CONF_KLINE;
226 break;
227
228 case GLINE_TYPE:
229 status = CONF_GLINE;
230 break;
231
232 case CLIENT_TYPE:
233 status = CONF_CLIENT;
234 break;
235
236 case OPER_TYPE:
237 status = CONF_OPERATOR;
238 dlinkAdd(conf, &conf->node, &oconf_items);
239 break;
240
241 case SERVER_TYPE:
242 status = CONF_SERVER;
243 dlinkAdd(conf, &conf->node, &server_items);
244 break;
245
246 default:
247 break;
248 }
249 aconf->status = status;
250 break;
251
252 case ULINE_TYPE:
253 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
254 sizeof(struct MatchItem));
255 dlinkAdd(conf, &conf->node, &uconf_items);
256 break;
257
258 case GDENY_TYPE:
259 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
260 sizeof(struct AccessItem));
261 dlinkAdd(conf, &conf->node, &gdeny_items);
262 break;
263
264 case XLINE_TYPE:
265 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
266 sizeof(struct MatchItem));
267 dlinkAdd(conf, &conf->node, &xconf_items);
268 break;
269 #ifdef HAVE_LIBPCRE
270 case RXLINE_TYPE:
271 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
272 sizeof(struct MatchItem));
273 dlinkAdd(conf, &conf->node, &rxconf_items);
274 break;
275
276 case RKLINE_TYPE:
277 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
278 sizeof(struct AccessItem));
279 aconf = map_to_conf(conf);
280 aconf->status = CONF_KLINE;
281 dlinkAdd(conf, &conf->node, &rkconf_items);
282 break;
283 #endif
284 case CLUSTER_TYPE:
285 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem));
286 dlinkAdd(conf, &conf->node, &cluster_items);
287 break;
288
289 case CRESV_TYPE:
290 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
291 sizeof(struct ResvChannel));
292 break;
293
294 case NRESV_TYPE:
295 conf = (struct ConfItem *)MyMalloc(sizeof(struct ConfItem) +
296 sizeof(struct MatchItem));
297 dlinkAdd(conf, &conf->node, &nresv_items);
298 break;
299
300 case SERVICE_TYPE:
301 status = CONF_SERVICE;
302 conf = MyMalloc(sizeof(struct ConfItem));
303 dlinkAdd(conf, &conf->node, &service_items);
304 break;
305
306 case CLASS_TYPE:
307 conf = MyMalloc(sizeof(struct ConfItem) +
308 sizeof(struct ClassItem));
309 dlinkAdd(conf, &conf->node, &class_items);
310
311 aclass = map_to_conf(conf);
312 aclass->active = 1;
313 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
314 aclass->ping_freq = DEFAULT_PINGFREQUENCY;
315 aclass->max_total = MAXIMUM_LINKS_DEFAULT;
316 aclass->max_sendq = DEFAULT_SENDQ;
317
318 break;
319
320 default:
321 conf = NULL;
322 break;
323 }
324
325 /* XXX Yes, this will core if default is hit. I want it to for now - db */
326 conf->type = type;
327
328 return conf;
329 }
330
331 void
332 delete_conf_item(struct ConfItem *conf)
333 {
334 dlink_node *m = NULL, *m_next = NULL;
335 struct MatchItem *match_item;
336 struct AccessItem *aconf;
337 ConfType type = conf->type;
338
339 MyFree(conf->name);
340 conf->name = NULL;
341
342 switch(type)
343 {
344 case DLINE_TYPE:
345 case EXEMPTDLINE_TYPE:
346 case GLINE_TYPE:
347 case KLINE_TYPE:
348 case CLIENT_TYPE:
349 case OPER_TYPE:
350 case SERVER_TYPE:
351 aconf = map_to_conf(conf);
352
353 if (aconf->dns_pending)
354 delete_resolver_queries(aconf);
355 if (aconf->passwd != NULL)
356 memset(aconf->passwd, 0, strlen(aconf->passwd));
357 if (aconf->spasswd != NULL)
358 memset(aconf->spasswd, 0, strlen(aconf->spasswd));
359 aconf->class_ptr = NULL;
360
361 MyFree(aconf->passwd);
362 MyFree(aconf->spasswd);
363 MyFree(aconf->reason);
364 MyFree(aconf->oper_reason);
365 MyFree(aconf->user);
366 MyFree(aconf->host);
367 #ifdef HAVE_LIBCRYPTO
368 MyFree(aconf->cipher_list);
369
370 if (aconf->rsa_public_key)
371 RSA_free(aconf->rsa_public_key);
372 MyFree(aconf->rsa_public_key_file);
373 #endif
374
375 /* Yes, sigh. switch on type again */
376 switch(type)
377 {
378 case EXEMPTDLINE_TYPE:
379 case DLINE_TYPE:
380 case GLINE_TYPE:
381 case KLINE_TYPE:
382 case CLIENT_TYPE:
383 MyFree(conf);
384 break;
385
386 case OPER_TYPE:
387 aconf = map_to_conf(conf);
388 if (!IsConfIllegal(aconf))
389 dlinkDelete(&conf->node, &oconf_items);
390 MyFree(conf);
391 break;
392
393 case SERVER_TYPE:
394 aconf = map_to_conf(conf);
395
396 DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
397 {
398 MyFree(m->data);
399 free_dlink_node(m);
400 }
401
402 DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
403 {
404 MyFree(m->data);
405 free_dlink_node(m);
406 }
407
408 if (!IsConfIllegal(aconf))
409 dlinkDelete(&conf->node, &server_items);
410 MyFree(conf);
411 break;
412
413 default:
414 break;
415 }
416 break;
417
418 case ULINE_TYPE:
419 match_item = map_to_conf(conf);
420 MyFree(match_item->user);
421 MyFree(match_item->host);
422 MyFree(match_item->reason);
423 MyFree(match_item->oper_reason);
424 dlinkDelete(&conf->node, &uconf_items);
425 MyFree(conf);
426 break;
427
428 case XLINE_TYPE:
429 match_item = map_to_conf(conf);
430 MyFree(match_item->user);
431 MyFree(match_item->host);
432 MyFree(match_item->reason);
433 MyFree(match_item->oper_reason);
434 dlinkDelete(&conf->node, &xconf_items);
435 MyFree(conf);
436 break;
437 #ifdef HAVE_LIBPCRE
438 case RKLINE_TYPE:
439 aconf = map_to_conf(conf);
440 MyFree(aconf->regexuser);
441 MyFree(aconf->regexhost);
442 MyFree(aconf->user);
443 MyFree(aconf->host);
444 MyFree(aconf->reason);
445 MyFree(aconf->oper_reason);
446 dlinkDelete(&conf->node, &rkconf_items);
447 MyFree(conf);
448 break;
449
450 case RXLINE_TYPE:
451 MyFree(conf->regexpname);
452 match_item = map_to_conf(conf);
453 MyFree(match_item->user);
454 MyFree(match_item->host);
455 MyFree(match_item->reason);
456 MyFree(match_item->oper_reason);
457 dlinkDelete(&conf->node, &rxconf_items);
458 MyFree(conf);
459 break;
460 #endif
461 case NRESV_TYPE:
462 match_item = map_to_conf(conf);
463 MyFree(match_item->user);
464 MyFree(match_item->host);
465 MyFree(match_item->reason);
466 MyFree(match_item->oper_reason);
467 dlinkDelete(&conf->node, &nresv_items);
468
469 if (conf->flags & CONF_FLAGS_TEMPORARY)
470 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
471 free_dlink_node(m);
472
473 MyFree(conf);
474 break;
475
476 case GDENY_TYPE:
477 aconf = map_to_conf(conf);
478 MyFree(aconf->user);
479 MyFree(aconf->host);
480 dlinkDelete(&conf->node, &gdeny_items);
481 MyFree(conf);
482 break;
483
484 case CLUSTER_TYPE:
485 dlinkDelete(&conf->node, &cluster_items);
486 MyFree(conf);
487 break;
488
489 case CRESV_TYPE:
490 if (conf->flags & CONF_FLAGS_TEMPORARY)
491 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
492 free_dlink_node(m);
493
494 MyFree(conf);
495 break;
496
497 case CLASS_TYPE:
498 dlinkDelete(&conf->node, &class_items);
499 MyFree(conf);
500 break;
501
502 case SERVICE_TYPE:
503 dlinkDelete(&conf->node, &service_items);
504 MyFree(conf);
505 break;
506
507 default:
508 break;
509 }
510 }
511
512 /* free_access_item()
513 *
514 * inputs - pointer to conf to free
515 * output - none
516 * side effects - crucial password fields are zeroed, conf is freed
517 */
518 void
519 free_access_item(struct AccessItem *aconf)
520 {
521 struct ConfItem *conf;
522
523 if (aconf == NULL)
524 return;
525 conf = unmap_conf_item(aconf);
526 delete_conf_item(conf);
527 }
528
529 static const unsigned int shared_bit_table[] =
530 { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
531
532 /* report_confitem_types()
533 *
534 * inputs - pointer to client requesting confitem report
535 * - ConfType to report
536 * output - none
537 * side effects -
538 */
539 void
540 report_confitem_types(struct Client *source_p, ConfType type)
541 {
542 dlink_node *ptr = NULL, *dptr = NULL;
543 struct ConfItem *conf = NULL;
544 struct AccessItem *aconf = NULL;
545 struct MatchItem *matchitem = NULL;
546 struct ClassItem *classitem = NULL;
547 char buf[12];
548 char *p = NULL;
549
550 switch (type)
551 {
552 case GDENY_TYPE:
553 DLINK_FOREACH(ptr, gdeny_items.head)
554 {
555 conf = ptr->data;
556 aconf = map_to_conf(conf);
557
558 p = buf;
559
560 if (aconf->flags & GDENY_BLOCK)
561 *p++ = 'B';
562 else
563 *p++ = 'b';
564
565 if (aconf->flags & GDENY_REJECT)
566 *p++ = 'R';
567 else
568 *p++ = 'r';
569
570 *p = '\0';
571
572 sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
573 me.name, RPL_STATSDEBUG, source_p->name,
574 aconf->user, aconf->host, conf->name, buf);
575 }
576 break;
577
578 case XLINE_TYPE:
579 DLINK_FOREACH(ptr, xconf_items.head)
580 {
581 conf = ptr->data;
582 matchitem = map_to_conf(conf);
583
584 sendto_one(source_p, form_str(RPL_STATSXLINE),
585 me.name, source_p->name,
586 matchitem->hold ? "x": "X", matchitem->count,
587 conf->name, matchitem->reason);
588 }
589 break;
590
591 #ifdef HAVE_LIBPCRE
592 case RXLINE_TYPE:
593 DLINK_FOREACH(ptr, rxconf_items.head)
594 {
595 conf = ptr->data;
596 matchitem = map_to_conf(conf);
597
598 sendto_one(source_p, form_str(RPL_STATSXLINE),
599 me.name, source_p->name,
600 "XR", matchitem->count,
601 conf->name, matchitem->reason);
602 }
603 break;
604
605 case RKLINE_TYPE:
606 DLINK_FOREACH(ptr, rkconf_items.head)
607 {
608 aconf = map_to_conf((conf = ptr->data));
609
610 sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
611 source_p->name, "KR", aconf->host, aconf->user,
612 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
613 }
614 break;
615 #endif
616
617 case ULINE_TYPE:
618 DLINK_FOREACH(ptr, uconf_items.head)
619 {
620 conf = ptr->data;
621 matchitem = map_to_conf(conf);
622
623 p = buf;
624
625 /* some of these are redundant for the sake of
626 * consistency with cluster{} flags
627 */
628 *p++ = 'c';
629 flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
630
631 sendto_one(source_p, form_str(RPL_STATSULINE),
632 me.name, source_p->name, conf->name,
633 matchitem->user?matchitem->user: "*",
634 matchitem->host?matchitem->host: "*", buf);
635 }
636
637 DLINK_FOREACH(ptr, cluster_items.head)
638 {
639 conf = ptr->data;
640
641 p = buf;
642
643 *p++ = 'C';
644 flags_to_ascii(conf->flags, shared_bit_table, p, 0);
645
646 sendto_one(source_p, form_str(RPL_STATSULINE),
647 me.name, source_p->name, conf->name,
648 "*", "*", buf);
649 }
650
651 break;
652
653 case OPER_TYPE:
654 DLINK_FOREACH(ptr, oconf_items.head)
655 {
656 conf = ptr->data;
657 aconf = map_to_conf(conf);
658
659 /* Don't allow non opers to see oper privs */
660 if (HasUMode(source_p, UMODE_OPER))
661 sendto_one(source_p, form_str(RPL_STATSOLINE),
662 me.name, source_p->name, 'O', aconf->user, aconf->host,
663 conf->name, oper_privs_as_string(aconf->port),
664 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
665 else
666 sendto_one(source_p, form_str(RPL_STATSOLINE),
667 me.name, source_p->name, 'O', aconf->user, aconf->host,
668 conf->name, "0",
669 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
670 }
671 break;
672
673 case CLASS_TYPE:
674 DLINK_FOREACH(ptr, class_items.head)
675 {
676 conf = ptr->data;
677 classitem = map_to_conf(conf);
678 sendto_one(source_p, form_str(RPL_STATSYLINE),
679 me.name, source_p->name, 'Y',
680 conf->name, classitem->ping_freq,
681 classitem->con_freq,
682 classitem->max_total, classitem->max_sendq,
683 classitem->curr_user_count,
684 classitem->number_per_cidr, classitem->cidr_bitlen_ipv4,
685 classitem->number_per_cidr, classitem->cidr_bitlen_ipv6,
686 classitem->active ? "active" : "disabled");
687 }
688 break;
689
690 case CONF_TYPE:
691 case CLIENT_TYPE:
692 break;
693
694 case SERVICE_TYPE:
695 DLINK_FOREACH(ptr, service_items.head)
696 {
697 conf = ptr->data;
698 sendto_one(source_p, form_str(RPL_STATSSERVICE),
699 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
700 }
701 break;
702
703 case SERVER_TYPE:
704 DLINK_FOREACH(ptr, server_items.head)
705 {
706 p = buf;
707
708 conf = ptr->data;
709 aconf = map_to_conf(conf);
710
711 buf[0] = '\0';
712
713 if (IsConfAllowAutoConn(aconf))
714 *p++ = 'A';
715 if (IsConfSSL(aconf))
716 *p++ = 'S';
717 if (IsConfTopicBurst(aconf))
718 *p++ = 'T';
719 if (buf[0] == '\0')
720 *p++ = '*';
721
722 *p = '\0';
723
724 /*
725 * Allow admins to see actual ips unless hide_server_ips is enabled
726 */
727 if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
728 sendto_one(source_p, form_str(RPL_STATSCLINE),
729 me.name, source_p->name, 'C', aconf->host,
730 buf, conf->name, aconf->port,
731 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
732 else
733 sendto_one(source_p, form_str(RPL_STATSCLINE),
734 me.name, source_p->name, 'C',
735 "*@127.0.0.1", buf, conf->name, aconf->port,
736 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
737 }
738 break;
739
740 case HUB_TYPE:
741 DLINK_FOREACH(ptr, server_items.head)
742 {
743 conf = ptr->data;
744 aconf = map_to_conf(conf);
745
746 DLINK_FOREACH(dptr, aconf->hub_list.head)
747 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
748 source_p->name, 'H', dptr->data, conf->name, 0, "*");
749 }
750 break;
751
752 case LEAF_TYPE:
753 DLINK_FOREACH(ptr, server_items.head)
754 {
755 conf = ptr->data;
756 aconf = map_to_conf(conf);
757
758 DLINK_FOREACH(dptr, aconf->leaf_list.head)
759 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
760 source_p->name, 'L', dptr->data, conf->name, 0, "*");
761 }
762 break;
763
764 case GLINE_TYPE:
765 case KLINE_TYPE:
766 case DLINE_TYPE:
767 case EXEMPTDLINE_TYPE:
768 case CRESV_TYPE:
769 case NRESV_TYPE:
770 case CLUSTER_TYPE:
771 default:
772 break;
773 }
774 }
775
776 /* check_client()
777 *
778 * inputs - pointer to client
779 * output - 0 = Success
780 * NOT_AUTHORIZED (-1) = Access denied (no I line match)
781 * IRCD_SOCKET_ERROR (-2) = Bad socket.
782 * I_LINE_FULL (-3) = I-line is full
783 * TOO_MANY (-4) = Too many connections from hostname
784 * BANNED_CLIENT (-5) = K-lined
785 * side effects - Ordinary client access check.
786 * Look for conf lines which have the same
787 * status as the flags passed.
788 */
789 static void *
790 check_client(va_list args)
791 {
792 struct Client *source_p = va_arg(args, struct Client *);
793 const char *username = va_arg(args, const char *);
794 int i;
795
796 /* I'm already in big trouble if source_p->localClient is NULL -db */
797 if ((i = verify_access(source_p, username)))
798 ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
799 source_p->name, source_p->sockhost);
800
801 switch (i)
802 {
803 case TOO_MANY:
804 sendto_realops_flags(UMODE_FULL, L_ALL,
805 "Too many on IP for %s (%s).",
806 get_client_name(source_p, SHOW_IP),
807 source_p->sockhost);
808 ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
809 get_client_name(source_p, SHOW_IP));
810 ++ServerStats.is_ref;
811 exit_client(source_p, &me, "No more connections allowed on that IP");
812 break;
813
814 case I_LINE_FULL:
815 sendto_realops_flags(UMODE_FULL, L_ALL,
816 "I-line is full for %s (%s).",
817 get_client_name(source_p, SHOW_IP),
818 source_p->sockhost);
819 ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
820 get_client_name(source_p, SHOW_IP));
821 ++ServerStats.is_ref;
822 exit_client(source_p, &me,
823 "No more connections allowed in your connection class");
824 break;
825
826 case NOT_AUTHORIZED:
827 ++ServerStats.is_ref;
828 /* jdc - lists server name & port connections are on */
829 /* a purely cosmetical change */
830 sendto_realops_flags(UMODE_UNAUTH, L_ALL,
831 "Unauthorized client connection from %s [%s] on [%s/%u].",
832 get_client_name(source_p, SHOW_IP),
833 source_p->sockhost,
834 source_p->localClient->listener->name,
835 source_p->localClient->listener->port);
836 ilog(LOG_TYPE_IRCD,
837 "Unauthorized client connection from %s on [%s/%u].",
838 get_client_name(source_p, SHOW_IP),
839 source_p->localClient->listener->name,
840 source_p->localClient->listener->port);
841
842 /* XXX It is prolematical whether it is better to use the
843 * capture reject code here or rely on the connecting too fast code.
844 * - Dianora
845 */
846 if (REJECT_HOLD_TIME > 0)
847 {
848 sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
849 me.name, source_p->name);
850 source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
851 SetCaptured(source_p);
852 }
853 else
854 exit_client(source_p, &me, "You are not authorized to use this server");
855 break;
856
857 case BANNED_CLIENT:
858 /*
859 * Don't exit them immediately, play with them a bit.
860 * - Dianora
861 */
862 if (REJECT_HOLD_TIME > 0)
863 {
864 source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
865 SetCaptured(source_p);
866 }
867 else
868 exit_client(source_p, &me, "Banned");
869 ++ServerStats.is_ref;
870 break;
871
872 case 0:
873 default:
874 break;
875 }
876
877 return (i < 0 ? NULL : source_p);
878 }
879
880 /* verify_access()
881 *
882 * inputs - pointer to client to verify
883 * - pointer to proposed username
884 * output - 0 if success -'ve if not
885 * side effect - find the first (best) I line to attach.
886 */
887 static int
888 verify_access(struct Client *client_p, const char *username)
889 {
890 struct AccessItem *aconf = NULL, *rkconf = NULL;
891 struct ConfItem *conf = NULL;
892 char non_ident[USERLEN + 1] = { '~', '\0' };
893 const char *uhi[3];
894
895 if (IsGotId(client_p))
896 {
897 aconf = find_address_conf(client_p->host, client_p->username,
898 &client_p->localClient->ip,
899 client_p->localClient->aftype,
900 client_p->localClient->passwd);
901 }
902 else
903 {
904 strlcpy(non_ident+1, username, sizeof(non_ident)-1);
905 aconf = find_address_conf(client_p->host,non_ident,
906 &client_p->localClient->ip,
907 client_p->localClient->aftype,
908 client_p->localClient->passwd);
909 }
910
911 uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
912 uhi[1] = client_p->host;
913 uhi[2] = client_p->sockhost;
914
915 rkconf = find_regexp_kline(uhi);
916
917 if (aconf != NULL)
918 {
919 if (IsConfClient(aconf) && !rkconf)
920 {
921 conf = unmap_conf_item(aconf);
922
923 if (IsConfRedir(aconf))
924 {
925 sendto_one(client_p, form_str(RPL_REDIR),
926 me.name, client_p->name,
927 conf->name ? conf->name : "",
928 aconf->port);
929 return(NOT_AUTHORIZED);
930 }
931
932 if (IsConfDoIdentd(aconf))
933 SetNeedId(client_p);
934
935 /* Thanks for spoof idea amm */
936 if (IsConfDoSpoofIp(aconf))
937 {
938 conf = unmap_conf_item(aconf);
939
940 if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
941 sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
942 client_p->name, client_p->host, conf->name);
943 strlcpy(client_p->host, conf->name, sizeof(client_p->host));
944 SetIPSpoof(client_p);
945 }
946
947 return(attach_iline(client_p, conf));
948 }
949 else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
950 {
951 /* XXX */
952 aconf = rkconf ? rkconf : aconf;
953 if (IsConfGline(aconf))
954 sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
955 client_p->name);
956 if (ConfigFileEntry.kline_with_reason)
957 sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
958 me.name, client_p->name, aconf->reason);
959 return(BANNED_CLIENT);
960 }
961 }
962
963 return(NOT_AUTHORIZED);
964 }
965
966 /* attach_iline()
967 *
968 * inputs - client pointer
969 * - conf pointer
970 * output -
971 * side effects - do actual attach
972 */
973 static int
974 attach_iline(struct Client *client_p, struct ConfItem *conf)
975 {
976 struct AccessItem *aconf;
977 struct ClassItem *aclass;
978 struct ip_entry *ip_found;
979 int a_limit_reached = 0;
980 int local = 0, global = 0, ident = 0;
981
982 ip_found = find_or_add_ip(&client_p->localClient->ip);
983 ip_found->count++;
984 SetIpHash(client_p);
985
986 aconf = map_to_conf(conf);
987 if (aconf->class_ptr == NULL)
988 return NOT_AUTHORIZED; /* If class is missing, this is best */
989
990 aclass = map_to_conf(aconf->class_ptr);
991
992 count_user_host(client_p->username, client_p->host,
993 &global, &local, &ident);
994
995 /* XXX blah. go down checking the various silly limits
996 * setting a_limit_reached if any limit is reached.
997 * - Dianora
998 */
999 if (aclass->max_total != 0 && aclass->curr_user_count >= aclass->max_total)
1000 a_limit_reached = 1;
1001 else if (aclass->max_perip != 0 && ip_found->count > aclass->max_perip)
1002 a_limit_reached = 1;
1003 else if (aclass->max_local != 0 && local >= aclass->max_local)
1004 a_limit_reached = 1;
1005 else if (aclass->max_global != 0 && global >= aclass->max_global)
1006 a_limit_reached = 1;
1007 else if (aclass->max_ident != 0 && ident >= aclass->max_ident &&
1008 client_p->username[0] != '~')
1009 a_limit_reached = 1;
1010
1011 if (a_limit_reached)
1012 {
1013 if (!IsConfExemptLimits(aconf))
1014 return TOO_MANY; /* Already at maximum allowed */
1015
1016 sendto_one(client_p,
1017 ":%s NOTICE %s :*** Your connection class is full, "
1018 "but you have exceed_limit = yes;", me.name, client_p->name);
1019 }
1020
1021 return attach_conf(client_p, conf);
1022 }
1023
1024 /* init_ip_hash_table()
1025 *
1026 * inputs - NONE
1027 * output - NONE
1028 * side effects - allocate memory for ip_entry(s)
1029 * - clear the ip hash table
1030 */
1031 void
1032 init_ip_hash_table(void)
1033 {
1034 ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
1035 2 * hard_fdlimit);
1036 memset(ip_hash_table, 0, sizeof(ip_hash_table));
1037 }
1038
1039 /* find_or_add_ip()
1040 *
1041 * inputs - pointer to struct irc_ssaddr
1042 * output - pointer to a struct ip_entry
1043 * side effects -
1044 *
1045 * If the ip # was not found, a new struct ip_entry is created, and the ip
1046 * count set to 0.
1047 */
1048 static struct ip_entry *
1049 find_or_add_ip(struct irc_ssaddr *ip_in)
1050 {
1051 struct ip_entry *ptr, *newptr;
1052 int hash_index = hash_ip(ip_in), res;
1053 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1054 #ifdef IPV6
1055 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1056 #endif
1057
1058 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1059 {
1060 #ifdef IPV6
1061 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1062 continue;
1063 if (ip_in->ss.ss_family == AF_INET6)
1064 {
1065 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1066 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1067 }
1068 else
1069 #endif
1070 {
1071 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1072 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1073 }
1074 if (res == 0)
1075 {
1076 /* Found entry already in hash, return it. */
1077 return ptr;
1078 }
1079 }
1080
1081 if (ip_entries_count >= 2 * hard_fdlimit)
1082 garbage_collect_ip_entries();
1083
1084 newptr = BlockHeapAlloc(ip_entry_heap);
1085 ip_entries_count++;
1086 memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
1087
1088 newptr->next = ip_hash_table[hash_index];
1089 ip_hash_table[hash_index] = newptr;
1090
1091 return newptr;
1092 }
1093
1094 /* remove_one_ip()
1095 *
1096 * inputs - unsigned long IP address value
1097 * output - NONE
1098 * side effects - The ip address given, is looked up in ip hash table
1099 * and number of ip#'s for that ip decremented.
1100 * If ip # count reaches 0 and has expired,
1101 * the struct ip_entry is returned to the ip_entry_heap
1102 */
1103 void
1104 remove_one_ip(struct irc_ssaddr *ip_in)
1105 {
1106 struct ip_entry *ptr;
1107 struct ip_entry *last_ptr = NULL;
1108 int hash_index = hash_ip(ip_in), res;
1109 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
1110 #ifdef IPV6
1111 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
1112 #endif
1113
1114 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
1115 {
1116 #ifdef IPV6
1117 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
1118 continue;
1119 if (ip_in->ss.ss_family == AF_INET6)
1120 {
1121 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
1122 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
1123 }
1124 else
1125 #endif
1126 {
1127 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
1128 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
1129 }
1130 if (res)
1131 continue;
1132 if (ptr->count > 0)
1133 ptr->count--;
1134 if (ptr->count == 0 &&
1135 (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1136 {
1137 if (last_ptr != NULL)
1138 last_ptr->next = ptr->next;
1139 else
1140 ip_hash_table[hash_index] = ptr->next;
1141
1142 BlockHeapFree(ip_entry_heap, ptr);
1143 ip_entries_count--;
1144 return;
1145 }
1146 last_ptr = ptr;
1147 }
1148 }
1149
1150 /* hash_ip()
1151 *
1152 * input - pointer to an irc_inaddr
1153 * output - integer value used as index into hash table
1154 * side effects - hopefully, none
1155 */
1156 static int
1157 hash_ip(struct irc_ssaddr *addr)
1158 {
1159 if (addr->ss.ss_family == AF_INET)
1160 {
1161 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1162 int hash;
1163 uint32_t ip;
1164
1165 ip = ntohl(v4->sin_addr.s_addr);
1166 hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1167 return hash;
1168 }
1169 #ifdef IPV6
1170 else
1171 {
1172 int hash;
1173 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1174 uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
1175
1176 hash = ip[0] ^ ip[3];
1177 hash ^= hash >> 16;
1178 hash ^= hash >> 8;
1179 hash = hash & (IP_HASH_SIZE - 1);
1180 return hash;
1181 }
1182 #else
1183 return 0;
1184 #endif
1185 }
1186
1187 /* count_ip_hash()
1188 *
1189 * inputs - pointer to counter of number of ips hashed
1190 * - pointer to memory used for ip hash
1191 * output - returned via pointers input
1192 * side effects - NONE
1193 *
1194 * number of hashed ip #'s is counted up, plus the amount of memory
1195 * used in the hash.
1196 */
1197 void
1198 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
1199 {
1200 struct ip_entry *ptr;
1201 int i;
1202
1203 *number_ips_stored = 0;
1204 *mem_ips_stored = 0;
1205
1206 for (i = 0; i < IP_HASH_SIZE; i++)
1207 {
1208 for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1209 {
1210 *number_ips_stored += 1;
1211 *mem_ips_stored += sizeof(struct ip_entry);
1212 }
1213 }
1214 }
1215
1216 /* garbage_collect_ip_entries()
1217 *
1218 * input - NONE
1219 * output - NONE
1220 * side effects - free up all ip entries with no connections
1221 */
1222 static void
1223 garbage_collect_ip_entries(void)
1224 {
1225 struct ip_entry *ptr;
1226 struct ip_entry *last_ptr;
1227 struct ip_entry *next_ptr;
1228 int i;
1229
1230 for (i = 0; i < IP_HASH_SIZE; i++)
1231 {
1232 last_ptr = NULL;
1233
1234 for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1235 {
1236 next_ptr = ptr->next;
1237
1238 if (ptr->count == 0 &&
1239 (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1240 {
1241 if (last_ptr != NULL)
1242 last_ptr->next = ptr->next;
1243 else
1244 ip_hash_table[i] = ptr->next;
1245 BlockHeapFree(ip_entry_heap, ptr);
1246 ip_entries_count--;
1247 }
1248 else
1249 last_ptr = ptr;
1250 }
1251 }
1252 }
1253
1254 /* detach_conf()
1255 *
1256 * inputs - pointer to client to detach
1257 * - type of conf to detach
1258 * output - 0 for success, -1 for failure
1259 * side effects - Disassociate configuration from the client.
1260 * Also removes a class from the list if marked for deleting.
1261 */
1262 int
1263 detach_conf(struct Client *client_p, ConfType type)
1264 {
1265 dlink_node *ptr, *next_ptr;
1266 struct ConfItem *conf;
1267 struct ClassItem *aclass;
1268 struct AccessItem *aconf;
1269 struct ConfItem *aclass_conf;
1270 struct MatchItem *match_item;
1271
1272 DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
1273 {
1274 conf = ptr->data;
1275
1276 if (type == CONF_TYPE || conf->type == type)
1277 {
1278 dlinkDelete(ptr, &client_p->localClient->confs);
1279 free_dlink_node(ptr);
1280
1281 switch (conf->type)
1282 {
1283 case CLIENT_TYPE:
1284 case OPER_TYPE:
1285 case SERVER_TYPE:
1286 aconf = map_to_conf(conf);
1287
1288 assert(aconf->clients > 0);
1289
1290 if ((aclass_conf = aconf->class_ptr) != NULL)
1291 {
1292 aclass = map_to_conf(aclass_conf);
1293
1294 assert(aclass->curr_user_count > 0);
1295
1296 if (conf->type == CLIENT_TYPE)
1297 remove_from_cidr_check(&client_p->localClient->ip, aclass);
1298 if (--aclass->curr_user_count == 0 && aclass->active == 0)
1299 delete_conf_item(aclass_conf);
1300 }
1301
1302 if (--aconf->clients == 0 && IsConfIllegal(aconf))
1303 delete_conf_item(conf);
1304
1305 break;
1306 default:
1307 break;
1308 }
1309
1310 if (type != CONF_TYPE)
1311 return 0;
1312 }
1313 }
1314
1315 return -1;
1316 }
1317
1318 /* attach_conf()
1319 *
1320 * inputs - client pointer
1321 * - conf pointer
1322 * output -
1323 * side effects - Associate a specific configuration entry to a *local*
1324 * client (this is the one which used in accepting the
1325 * connection). Note, that this automatically changes the
1326 * attachment if there was an old one...
1327 */
1328 int
1329 attach_conf(struct Client *client_p, struct ConfItem *conf)
1330 {
1331 struct AccessItem *aconf = map_to_conf(conf);
1332 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1333
1334 if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
1335 return 1;
1336
1337 if (IsConfIllegal(aconf)) /* TBV: can't happen */
1338 return NOT_AUTHORIZED;
1339
1340 if (conf->type == CLIENT_TYPE)
1341 if (cidr_limit_reached(IsConfExemptLimits(aconf),
1342 &client_p->localClient->ip, aclass))
1343 return TOO_MANY; /* Already at maximum allowed */
1344
1345 aclass->curr_user_count++;
1346 aconf->clients++;
1347
1348 dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
1349
1350 return 0;
1351 }
1352
1353 /* attach_connect_block()
1354 *
1355 * inputs - pointer to server to attach
1356 * - name of server
1357 * - hostname of server
1358 * output - true (1) if both are found, otherwise return false (0)
1359 * side effects - find connect block and attach them to connecting client
1360 */
1361 int
1362 attach_connect_block(struct Client *client_p, const char *name,
1363 const char *host)
1364 {
1365 dlink_node *ptr;
1366 struct ConfItem *conf;
1367 struct AccessItem *aconf;
1368
1369 assert(client_p != NULL);
1370 assert(host != NULL);
1371
1372 if (client_p == NULL || host == NULL)
1373 return 0;
1374
1375 DLINK_FOREACH(ptr, server_items.head)
1376 {
1377 conf = ptr->data;
1378 aconf = map_to_conf(conf);
1379
1380 if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1381 continue;
1382
1383 attach_conf(client_p, conf);
1384 return -1;
1385 }
1386
1387 return 0;
1388 }
1389
1390 /* find_conf_exact()
1391 *
1392 * inputs - type of ConfItem
1393 * - pointer to name to find
1394 * - pointer to username to find
1395 * - pointer to host to find
1396 * output - NULL or pointer to conf found
1397 * side effects - find a conf entry which matches the hostname
1398 * and has the same name.
1399 */
1400 struct ConfItem *
1401 find_conf_exact(ConfType type, const char *name, const char *user,
1402 const char *host)
1403 {
1404 dlink_node *ptr;
1405 dlink_list *list_p;
1406 struct ConfItem *conf = NULL;
1407 struct AccessItem *aconf;
1408
1409 /* Only valid for OPER_TYPE and ...? */
1410 list_p = map_to_list(type);
1411
1412 DLINK_FOREACH(ptr, (*list_p).head)
1413 {
1414 conf = ptr->data;
1415
1416 if (conf->name == NULL)
1417 continue;
1418 aconf = map_to_conf(conf);
1419 if (aconf->host == NULL)
1420 continue;
1421 if (irccmp(conf->name, name) != 0)
1422 continue;
1423
1424 /*
1425 ** Accept if the *real* hostname (usually sockethost)
1426 ** socket host) matches *either* host or name field
1427 ** of the configuration.
1428 */
1429 if (!match(aconf->host, host) || !match(aconf->user, user))
1430 continue;
1431 if (type == OPER_TYPE)
1432 {
1433 struct ClassItem *aclass = map_to_conf(aconf->class_ptr);
1434
1435 if (aconf->clients >= aclass->max_total)
1436 continue;
1437 }
1438
1439 return conf;
1440 }
1441
1442 return NULL;
1443 }
1444
1445 /* find_conf_name()
1446 *
1447 * inputs - pointer to conf link list to search
1448 * - pointer to name to find
1449 * - int mask of type of conf to find
1450 * output - NULL or pointer to conf found
1451 * side effects - find a conf entry which matches the name
1452 * and has the given mask.
1453 */
1454 struct ConfItem *
1455 find_conf_name(dlink_list *list, const char *name, ConfType type)
1456 {
1457 dlink_node *ptr;
1458 struct ConfItem* conf;
1459
1460 DLINK_FOREACH(ptr, list->head)
1461 {
1462 conf = ptr->data;
1463
1464 if (conf->type == type)
1465 {
1466 if (conf->name && (irccmp(conf->name, name) == 0 ||
1467 match(conf->name, name)))
1468 return conf;
1469 }
1470 }
1471
1472 return NULL;
1473 }
1474
1475 /* map_to_list()
1476 *
1477 * inputs - ConfType conf
1478 * output - pointer to dlink_list to use
1479 * side effects - none
1480 */
1481 static dlink_list *
1482 map_to_list(ConfType type)
1483 {
1484 switch(type)
1485 {
1486 case RXLINE_TYPE:
1487 return(&rxconf_items);
1488 break;
1489 case XLINE_TYPE:
1490 return(&xconf_items);
1491 break;
1492 case ULINE_TYPE:
1493 return(&uconf_items);
1494 break;
1495 case NRESV_TYPE:
1496 return(&nresv_items);
1497 break;
1498 case OPER_TYPE:
1499 return(&oconf_items);
1500 break;
1501 case CLASS_TYPE:
1502 return(&class_items);
1503 break;
1504 case SERVER_TYPE:
1505 return(&server_items);
1506 break;
1507 case SERVICE_TYPE:
1508 return(&service_items);
1509 break;
1510 case CLUSTER_TYPE:
1511 return(&cluster_items);
1512 break;
1513 case CONF_TYPE:
1514 case GLINE_TYPE:
1515 case KLINE_TYPE:
1516 case DLINE_TYPE:
1517 case CRESV_TYPE:
1518 default:
1519 return NULL;
1520 }
1521 }
1522
1523 /* find_matching_name_conf()
1524 *
1525 * inputs - type of link list to look in
1526 * - pointer to name string to find
1527 * - pointer to user
1528 * - pointer to host
1529 * - optional action to match on as well
1530 * output - NULL or pointer to found struct MatchItem
1531 * side effects - looks for a match on name field
1532 */
1533 struct ConfItem *
1534 find_matching_name_conf(ConfType type, const char *name, const char *user,
1535 const char *host, int action)
1536 {
1537 dlink_node *ptr=NULL;
1538 struct ConfItem *conf=NULL;
1539 struct AccessItem *aconf=NULL;
1540 struct MatchItem *match_item=NULL;
1541 dlink_list *list_p = map_to_list(type);
1542
1543 switch (type)
1544 {
1545 #ifdef HAVE_LIBPCRE
1546 case RXLINE_TYPE:
1547 DLINK_FOREACH(ptr, list_p->head)
1548 {
1549 conf = ptr->data;
1550 assert(conf->regexpname);
1551
1552 if (!ircd_pcre_exec(conf->regexpname, name))
1553 return conf;
1554 }
1555 break;
1556 #endif
1557 case SERVICE_TYPE:
1558 DLINK_FOREACH(ptr, list_p->head)
1559 {
1560 conf = ptr->data;
1561
1562 if (EmptyString(conf->name))
1563 continue;
1564 if ((name != NULL) && !irccmp(name, conf->name))
1565 return conf;
1566 }
1567 break;
1568
1569 case XLINE_TYPE:
1570 case ULINE_TYPE:
1571 case NRESV_TYPE:
1572 DLINK_FOREACH(ptr, list_p->head)
1573 {
1574 conf = ptr->data;
1575
1576 match_item = map_to_conf(conf);
1577 if (EmptyString(conf->name))
1578 continue;
1579 if ((name != NULL) && match_esc(conf->name, name))
1580 {
1581 if ((user == NULL && (host == NULL)))
1582 return conf;
1583 if ((match_item->action & action) != action)
1584 continue;
1585 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1586 return conf;
1587 if (match(match_item->user, user) && match(match_item->host, host))
1588 return conf;
1589 }
1590 }
1591 break;
1592
1593 case SERVER_TYPE:
1594 DLINK_FOREACH(ptr, list_p->head)
1595 {
1596 conf = ptr->data;
1597 aconf = map_to_conf(conf);
1598
1599 if ((name != NULL) && match_esc(name, conf->name))
1600 return conf;
1601 else if ((host != NULL) && match_esc(host, aconf->host))
1602 return conf;
1603 }
1604 break;
1605
1606 default:
1607 break;
1608 }
1609 return NULL;
1610 }
1611
1612 /* find_exact_name_conf()
1613 *
1614 * inputs - type of link list to look in
1615 * - pointer to name string to find
1616 * - pointer to user
1617 * - pointer to host
1618 * output - NULL or pointer to found struct MatchItem
1619 * side effects - looks for an exact match on name field
1620 */
1621 struct ConfItem *
1622 find_exact_name_conf(ConfType type, const struct Client *who, const char *name,
1623 const char *user, const char *host)
1624 {
1625 dlink_node *ptr = NULL;
1626 struct AccessItem *aconf;
1627 struct ConfItem *conf;
1628 struct MatchItem *match_item;
1629 dlink_list *list_p;
1630
1631 list_p = map_to_list(type);
1632
1633 switch(type)
1634 {
1635 case RXLINE_TYPE:
1636 case XLINE_TYPE:
1637 case ULINE_TYPE:
1638 case NRESV_TYPE:
1639
1640 DLINK_FOREACH(ptr, list_p->head)
1641 {
1642 conf = ptr->data;
1643 match_item = (struct MatchItem *)map_to_conf(conf);
1644 if (EmptyString(conf->name))
1645 continue;
1646
1647 if (irccmp(conf->name, name) == 0)
1648 {
1649 if ((user == NULL && (host == NULL)))
1650 return (conf);
1651 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1652 return (conf);
1653 if (match(match_item->user, user) && match(match_item->host, host))
1654 return (conf);
1655 }
1656 }
1657 break;
1658
1659 case OPER_TYPE:
1660 DLINK_FOREACH(ptr, list_p->head)
1661 {
1662 conf = ptr->data;
1663 aconf = map_to_conf(conf);
1664
1665 if (EmptyString(conf->name))
1666 continue;
1667
1668 if (!irccmp(conf->name, name))
1669 {
1670 if (!who)
1671 return conf;
1672 if (EmptyString(aconf->user) || EmptyString(aconf->host))
1673 return conf;
1674 if (match(aconf->user, who->username))
1675 {
1676 switch (aconf->type)
1677 {
1678 case HM_HOST:
1679 if (match(aconf->host, who->host) || match(aconf->host, who->sockhost))
1680 return conf;
1681 break;
1682 case HM_IPV4:
1683 if (who->localClient->aftype == AF_INET)
1684 if (match_ipv4(&who->localClient->ip, &aconf->addr, aconf->bits))
1685 return conf;
1686 break;
1687 #ifdef IPV6
1688 case HM_IPV6:
1689 if (who->localClient->aftype == AF_INET6)
1690 if (match_ipv6(&who->localClient->ip, &aconf->addr, aconf->bits))
1691 return conf;
1692 break;
1693 #endif
1694 default:
1695 assert(0);
1696 }
1697 }
1698 }
1699 }
1700
1701 break;
1702
1703 case SERVER_TYPE:
1704 DLINK_FOREACH(ptr, list_p->head)
1705 {
1706 conf = ptr->data;
1707 aconf = (struct AccessItem *)map_to_conf(conf);
1708 if (EmptyString(conf->name))
1709 continue;
1710
1711 if (name == NULL)
1712 {
1713 if (EmptyString(aconf->host))
1714 continue;
1715 if (irccmp(aconf->host, host) == 0)
1716 return(conf);
1717 }
1718 else if (irccmp(conf->name, name) == 0)
1719 {
1720 return (conf);
1721 }
1722 }
1723 break;
1724
1725 case CLASS_TYPE:
1726 DLINK_FOREACH(ptr, list_p->head)
1727 {
1728 conf = ptr->data;
1729 if (EmptyString(conf->name))
1730 continue;
1731
1732 if (irccmp(conf->name, name) == 0)
1733 return (conf);
1734 }
1735 break;
1736
1737 default:
1738 break;
1739 }
1740 return(NULL);
1741 }
1742
1743 /* rehash()
1744 *
1745 * Actual REHASH service routine. Called with sig == 0 if it has been called
1746 * as a result of an operator issuing this command, else assume it has been
1747 * called as a result of the server receiving a HUP signal.
1748 */
1749 int
1750 rehash(int sig)
1751 {
1752 if (sig != 0)
1753 sendto_realops_flags(UMODE_ALL, L_ALL,
1754 "Got signal SIGHUP, reloading ircd.conf file");
1755
1756 restart_resolver();
1757
1758 /* don't close listeners until we know we can go ahead with the rehash */
1759
1760 /* Check to see if we magically got(or lost) IPv6 support */
1761 check_can_use_v6();
1762
1763 read_conf_files(0);
1764
1765 if (ServerInfo.description != NULL)
1766 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1767
1768 load_conf_modules();
1769
1770 flush_deleted_I_P();
1771
1772 rehashed_klines = 1;
1773 /* XXX */
1774 if (ConfigLoggingEntry.use_logging)
1775 log_close_all();
1776
1777 return(0);
1778 }
1779
1780 /* set_default_conf()
1781 *
1782 * inputs - NONE
1783 * output - NONE
1784 * side effects - Set default values here.
1785 * This is called **PRIOR** to parsing the
1786 * configuration file. If you want to do some validation
1787 * of values later, put them in validate_conf().
1788 */
1789 static void
1790 set_default_conf(void)
1791 {
1792 /* verify init_class() ran, this should be an unnecessary check
1793 * but its not much work.
1794 */
1795 assert(class_default == (struct ConfItem *) class_items.tail->data);
1796
1797 #ifdef HAVE_LIBCRYPTO
1798 ServerInfo.rsa_private_key = NULL;
1799 ServerInfo.rsa_private_key_file = NULL;
1800 #endif
1801
1802 /* ServerInfo.name is not rehashable */
1803 /* ServerInfo.name = ServerInfo.name; */
1804 ServerInfo.description = NULL;
1805 DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1806 DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1807
1808 memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1809 ServerInfo.specific_ipv4_vhost = 0;
1810 memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1811 ServerInfo.specific_ipv6_vhost = 0;
1812
1813 ServerInfo.max_clients = MAXCLIENTS_MAX;
1814
1815 ServerInfo.hub = 0;
1816 ServerInfo.dns_host.sin_addr.s_addr = 0;
1817 ServerInfo.dns_host.sin_port = 0;
1818 AdminInfo.name = NULL;
1819 AdminInfo.email = NULL;
1820 AdminInfo.description = NULL;
1821
1822 log_close_all();
1823
1824 ConfigLoggingEntry.use_logging = 1;
1825
1826 ConfigChannel.disable_fake_channels = 0;
1827 ConfigChannel.restrict_channels = 0;
1828 ConfigChannel.disable_local_channels = 0;
1829 ConfigChannel.use_invex = 1;
1830 ConfigChannel.use_except = 1;
1831 ConfigChannel.use_knock = 1;
1832 ConfigChannel.knock_delay = 300;
1833 ConfigChannel.knock_delay_channel = 60;
1834 ConfigChannel.max_chans_per_user = 15;
1835 ConfigChannel.quiet_on_ban = 1;
1836 ConfigChannel.max_bans = 25;
1837 ConfigChannel.default_split_user_count = 0;
1838 ConfigChannel.default_split_server_count = 0;
1839 ConfigChannel.no_join_on_split = 0;
1840 ConfigChannel.no_create_on_split = 0;
1841
1842 ConfigServerHide.flatten_links = 0;
1843 ConfigServerHide.links_delay = 300;
1844 ConfigServerHide.hidden = 0;
1845 ConfigServerHide.disable_hidden = 0;
1846 ConfigServerHide.hide_servers = 0;
1847 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1848 ConfigServerHide.hide_server_ips = 0;
1849
1850
1851 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1852 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1853 ConfigFileEntry.gline_min_cidr = 16;
1854 ConfigFileEntry.gline_min_cidr6 = 48;
1855 ConfigFileEntry.invisible_on_connect = 1;
1856 ConfigFileEntry.burst_away = 0;
1857 ConfigFileEntry.use_whois_actually = 1;
1858 ConfigFileEntry.tkline_expire_notices = 1;
1859 ConfigFileEntry.hide_spoof_ips = 1;
1860 ConfigFileEntry.ignore_bogus_ts = 0;
1861 ConfigFileEntry.disable_auth = 0;
1862 ConfigFileEntry.disable_remote = 0;
1863 ConfigFileEntry.kill_chase_time_limit = 90;
1864 ConfigFileEntry.default_floodcount = 8;
1865 ConfigFileEntry.failed_oper_notice = 1;
1866 ConfigFileEntry.dots_in_ident = 0;
1867 ConfigFileEntry.min_nonwildcard = 4;
1868 ConfigFileEntry.min_nonwildcard_simple = 3;
1869 ConfigFileEntry.max_accept = 20;
1870 ConfigFileEntry.anti_nick_flood = 0;
1871 ConfigFileEntry.max_nick_time = 20;
1872 ConfigFileEntry.max_nick_changes = 5;
1873 ConfigFileEntry.anti_spam_exit_message_time = 0;
1874 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1875 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1876 ConfigFileEntry.kline_with_reason = 1;
1877 ConfigFileEntry.kline_reason = NULL;
1878 ConfigFileEntry.warn_no_nline = 1;
1879 ConfigFileEntry.stats_o_oper_only = 0;
1880 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1881 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1882 ConfigFileEntry.stats_P_oper_only = 0;
1883 ConfigFileEntry.caller_id_wait = 60;
1884 ConfigFileEntry.opers_bypass_callerid = 0;
1885 ConfigFileEntry.pace_wait = 10;
1886 ConfigFileEntry.pace_wait_simple = 1;
1887 ConfigFileEntry.short_motd = 0;
1888 ConfigFileEntry.ping_cookie = 0;
1889 ConfigFileEntry.no_oper_flood = 0;
1890 ConfigFileEntry.true_no_oper_flood = 0;
1891 ConfigFileEntry.oper_pass_resv = 1;
1892 ConfigFileEntry.glines = 0;
1893 ConfigFileEntry.gline_time = 12 * 3600;
1894 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1895 ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1896 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1897 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1898 UMODE_OPERWALL | UMODE_WALLOP;
1899 ConfigFileEntry.use_egd = 0;
1900 ConfigFileEntry.egdpool_path = NULL;
1901 ConfigFileEntry.throttle_time = 10;
1902 }
1903
1904 static void
1905 validate_conf(void)
1906 {
1907 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1908 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1909
1910 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1911 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1912
1913 if (ServerInfo.network_name == NULL)
1914 DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1915
1916 if (ServerInfo.network_desc == NULL)
1917 DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1918
1919 if (ConfigFileEntry.service_name == NULL)
1920 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1921
1922 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1923 (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1924 ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1925
1926 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1927 }
1928
1929 /* read_conf()
1930 *
1931 * inputs - file descriptor pointing to config file to use
1932 * output - None
1933 * side effects - Read configuration file.
1934 */
1935 static void
1936 read_conf(FILE *file)
1937 {
1938 lineno = 0;
1939
1940 set_default_conf(); /* Set default values prior to conf parsing */
1941 conf_parser_ctx.pass = 1;
1942 yyparse(); /* pick up the classes first */
1943
1944 rewind(file);
1945
1946 conf_parser_ctx.pass = 2;
1947 yyparse(); /* Load the values from the conf */
1948 validate_conf(); /* Check to make sure some values are still okay. */
1949 /* Some global values are also loaded here. */
1950 check_class(); /* Make sure classes are valid */
1951 }
1952
1953 /* lookup_confhost()
1954 *
1955 * start DNS lookups of all hostnames in the conf
1956 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1957 */
1958 static void
1959 lookup_confhost(struct ConfItem *conf)
1960 {
1961 struct AccessItem *aconf;
1962 struct addrinfo hints, *res;
1963
1964 aconf = map_to_conf(conf);
1965
1966 if (has_wildcards(aconf->host))
1967 {
1968 ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1969 aconf->host, conf->name);
1970 return;
1971 }
1972
1973 /* Do name lookup now on hostnames given and store the
1974 * ip numbers in conf structure.
1975 */
1976 memset(&hints, 0, sizeof(hints));
1977
1978 hints.ai_family = AF_UNSPEC;
1979 hints.ai_socktype = SOCK_STREAM;
1980
1981 /* Get us ready for a bind() and don't bother doing dns lookup */
1982 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1983
1984 if (getaddrinfo(aconf->host, NULL, &hints, &res))
1985 {
1986 conf_dns_lookup(aconf);
1987 return;
1988 }
1989
1990 assert(res != NULL);
1991
1992 memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
1993 aconf->addr.ss_len = res->ai_addrlen;
1994 aconf->addr.ss.ss_family = res->ai_family;
1995 freeaddrinfo(res);
1996 }
1997
1998 /* conf_connect_allowed()
1999 *
2000 * inputs - pointer to inaddr
2001 * - int type ipv4 or ipv6
2002 * output - BANNED or accepted
2003 * side effects - none
2004 */
2005 int
2006 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
2007 {
2008 struct ip_entry *ip_found;
2009 struct AccessItem *aconf = find_dline_conf(addr, aftype);
2010
2011 /* DLINE exempt also gets you out of static limits/pacing... */
2012 if (aconf && (aconf->status & CONF_EXEMPTDLINE))
2013 return 0;
2014
2015 if (aconf != NULL)
2016 return BANNED_CLIENT;
2017
2018 ip_found = find_or_add_ip(addr);
2019
2020 if ((CurrentTime - ip_found->last_attempt) <
2021 ConfigFileEntry.throttle_time)
2022 {
2023 ip_found->last_attempt = CurrentTime;
2024 return TOO_FAST;
2025 }
2026
2027 ip_found->last_attempt = CurrentTime;
2028 return 0;
2029 }
2030
2031 static struct AccessItem *
2032 find_regexp_kline(const char *uhi[])
2033 {
2034 #ifdef HAVE_LIBPCRE
2035 const dlink_node *ptr = NULL;
2036
2037 DLINK_FOREACH(ptr, rkconf_items.head)
2038 {
2039 struct AccessItem *aptr = map_to_conf(ptr->data);
2040
2041 assert(aptr->regexuser);
2042 assert(aptr->regexhost);
2043
2044 if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2045 (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2046 !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2047 return aptr;
2048 }
2049 #endif
2050 return NULL;
2051 }
2052
2053 /* find_kill()
2054 *
2055 * inputs - pointer to client structure
2056 * output - pointer to struct AccessItem if found
2057 * side effects - See if this user is klined already,
2058 * and if so, return struct AccessItem pointer
2059 */
2060 struct AccessItem *
2061 find_kill(struct Client *client_p)
2062 {
2063 struct AccessItem *aconf = NULL;
2064 const char *uhi[3];
2065
2066 uhi[0] = client_p->username;
2067 uhi[1] = client_p->host;
2068 uhi[2] = client_p->sockhost;
2069
2070 assert(client_p != NULL);
2071
2072 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2073 CONF_KLINE, client_p->localClient->aftype,
2074 client_p->username, NULL, 1);
2075 if (aconf == NULL)
2076 aconf = find_regexp_kline(uhi);
2077
2078 return aconf;
2079 }
2080
2081 struct AccessItem *
2082 find_gline(struct Client *client_p)
2083 {
2084 struct AccessItem *aconf;
2085
2086 assert(client_p != NULL);
2087
2088 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2089 CONF_GLINE, client_p->localClient->aftype,
2090 client_p->username, NULL, 1);
2091 return aconf;
2092 }
2093
2094 /* add_temp_line()
2095 *
2096 * inputs - pointer to struct ConfItem
2097 * output - none
2098 * Side effects - links in given struct ConfItem into
2099 * temporary *line link list
2100 */
2101 void
2102 add_temp_line(struct ConfItem *conf)
2103 {
2104 if (conf->type == XLINE_TYPE)
2105 {
2106 conf->flags |= CONF_FLAGS_TEMPORARY;
2107 dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2108 }
2109 else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2110 {
2111 conf->flags |= CONF_FLAGS_TEMPORARY;
2112 dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2113 }
2114 }
2115
2116 /* cleanup_tklines()
2117 *
2118 * inputs - NONE
2119 * output - NONE
2120 * side effects - call function to expire temporary k/d lines
2121 * This is an event started off in ircd.c
2122 */
2123 void
2124 cleanup_tklines(void *notused)
2125 {
2126 hostmask_expire_temporary();
2127 expire_tklines(&temporary_xlines);
2128 expire_tklines(&temporary_resv);
2129 }
2130
2131 /* expire_tklines()
2132 *
2133 * inputs - tkline list pointer
2134 * output - NONE
2135 * side effects - expire tklines
2136 */
2137 static void
2138 expire_tklines(dlink_list *tklist)
2139 {
2140 dlink_node *ptr;
2141 dlink_node *next_ptr;
2142 struct ConfItem *conf;
2143 struct MatchItem *xconf;
2144 struct MatchItem *nconf;
2145 struct ResvChannel *cconf;
2146
2147 DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2148 {
2149 conf = ptr->data;
2150
2151 if (conf->type == XLINE_TYPE)
2152 {
2153 xconf = (struct MatchItem *)map_to_conf(conf);
2154 if (xconf->hold <= CurrentTime)
2155 {
2156 if (ConfigFileEntry.tkline_expire_notices)
2157 sendto_realops_flags(UMODE_ALL, L_ALL,
2158 "Temporary X-line for [%s] sexpired", conf->name);
2159 dlinkDelete(ptr, tklist);
2160 free_dlink_node(ptr);
2161 delete_conf_item(conf);
2162 }
2163 }
2164 else if (conf->type == NRESV_TYPE)
2165 {
2166 nconf = (struct MatchItem *)map_to_conf(conf);
2167 if (nconf->hold <= CurrentTime)
2168 {
2169 if (ConfigFileEntry.tkline_expire_notices)
2170 sendto_realops_flags(UMODE_ALL, L_ALL,
2171 "Temporary RESV for [%s] expired", conf->name);
2172 dlinkDelete(ptr, tklist);
2173 free_dlink_node(ptr);
2174 delete_conf_item(conf);
2175 }
2176 }
2177 else if (conf->type == CRESV_TYPE)
2178 {
2179 cconf = (struct ResvChannel *)map_to_conf(conf);
2180 if (cconf->hold <= CurrentTime)
2181 {
2182 if (ConfigFileEntry.tkline_expire_notices)
2183 sendto_realops_flags(UMODE_ALL, L_ALL,
2184 "Temporary RESV for [%s] expired", cconf->name);
2185 delete_channel_resv(cconf);
2186 }
2187 }
2188 }
2189 }
2190
2191 /* oper_privs_as_string()
2192 *
2193 * inputs - pointer to client_p
2194 * output - pointer to static string showing oper privs
2195 * side effects - return as string, the oper privs as derived from port
2196 */
2197 static const struct oper_privs
2198 {
2199 const unsigned int oprivs;
2200 const unsigned char c;
2201 } flag_list[] = {
2202 { OPER_FLAG_ADMIN, 'A' },
2203 { OPER_FLAG_REMOTEBAN, 'B' },
2204 { OPER_FLAG_DIE, 'D' },
2205 { OPER_FLAG_GLINE, 'G' },
2206 { OPER_FLAG_REHASH, 'H' },
2207 { OPER_FLAG_K, 'K' },
2208 { OPER_FLAG_OPERWALL, 'L' },
2209 { OPER_FLAG_N, 'N' },
2210 { OPER_FLAG_GLOBAL_KILL, 'O' },
2211 { OPER_FLAG_REMOTE, 'R' },
2212 { OPER_FLAG_OPER_SPY, 'S' },
2213 { OPER_FLAG_UNKLINE, 'U' },
2214 { OPER_FLAG_X, 'X' },
2215 { 0, '\0' }
2216 };
2217
2218 char *
2219 oper_privs_as_string(const unsigned int port)
2220 {
2221 static char privs_out[16];
2222 char *privs_ptr = privs_out;
2223 unsigned int i = 0;
2224
2225 for (; flag_list[i].oprivs; ++i)
2226 {
2227 if (port & flag_list[i].oprivs)
2228 *privs_ptr++ = flag_list[i].c;
2229 else
2230 *privs_ptr++ = ToLowerTab[flag_list[i].c];
2231 }
2232
2233 *privs_ptr = '\0';
2234
2235 return privs_out;
2236 }
2237
2238 /*
2239 * Input: A client to find the active oper{} name for.
2240 * Output: The nick!user@host{oper} of the oper.
2241 * "oper" is server name for remote opers
2242 * Side effects: None.
2243 */
2244 const char *
2245 get_oper_name(const struct Client *client_p)
2246 {
2247 dlink_node *cnode = NULL;
2248 /* +5 for !,@,{,} and null */
2249 static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
2250
2251 if (MyConnect(client_p))
2252 {
2253 if ((cnode = client_p->localClient->confs.head))
2254 {
2255 struct ConfItem *conf = cnode->data;
2256 const struct AccessItem *aconf = map_to_conf(conf);
2257
2258 if (IsConfOperator(aconf))
2259 {
2260 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2261 client_p->username, client_p->host, conf->name);
2262 return buffer;
2263 }
2264 }
2265
2266 /* Probably should assert here for now. If there is an oper out there
2267 * with no oper{} conf attached, it would be good for us to know...
2268 */
2269 assert(0); /* Oper without oper conf! */
2270 }
2271
2272 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2273 client_p->username, client_p->host, client_p->servptr->name);
2274 return buffer;
2275 }
2276
2277 /* read_conf_files()
2278 *
2279 * inputs - cold start YES or NO
2280 * output - none
2281 * side effects - read all conf files needed, ircd.conf kline.conf etc.
2282 */
2283 void
2284 read_conf_files(int cold)
2285 {
2286 const char *filename;
2287 char chanmodes[32];
2288 char chanlimit[32];
2289
2290 conf_parser_ctx.boot = cold;
2291 filename = get_conf_name(CONF_TYPE);
2292
2293 /* We need to know the initial filename for the yyerror() to report
2294 FIXME: The full path is in conffilenamebuf first time since we
2295 dont know anything else
2296
2297 - Gozem 2002-07-21
2298 */
2299 strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2300
2301 if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
2302 {
2303 if (cold)
2304 {
2305 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2306 filename, strerror(errno));
2307 exit(-1);
2308 }
2309 else
2310 {
2311 sendto_realops_flags(UMODE_ALL, L_ALL,
2312 "Unable to read configuration file '%s': %s",
2313 filename, strerror(errno));
2314 return;
2315 }
2316 }
2317
2318 if (!cold)
2319 clear_out_old_conf();
2320
2321 read_conf(conf_parser_ctx.conf_file);
2322 fclose(conf_parser_ctx.conf_file);
2323
2324 add_isupport("NETWORK", ServerInfo.network_name, -1);
2325 snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
2326 ConfigChannel.use_except ? "e" : "",
2327 ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2328 add_isupport("MAXLIST", chanmodes, -1);
2329 add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2330
2331 if (ConfigChannel.disable_local_channels)
2332 add_isupport("CHANTYPES", "#", -1);
2333 else
2334 add_isupport("CHANTYPES", "#&", -1);
2335
2336 snprintf(chanlimit, sizeof(chanlimit), "%s:%d",
2337 ConfigChannel.disable_local_channels ? "#" : "#&",
2338 ConfigChannel.max_chans_per_user);
2339 add_isupport("CHANLIMIT", chanlimit, -1);
2340 snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2341 ConfigChannel.use_except ? "e" : "",
2342 ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2343 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2344
2345 if (ConfigChannel.use_except)
2346 add_isupport("EXCEPTS", "e", -1);
2347 if (ConfigChannel.use_invex)
2348 add_isupport("INVEX", "I", -1);
2349 add_isupport("CHANMODES", chanmodes, -1);
2350
2351 /*
2352 * message_locale may have changed. rebuild isupport since it relies
2353 * on strlen(form_str(RPL_ISUPPORT))
2354 */
2355 rebuild_isupport_message_line();
2356
2357 #ifdef HAVE_LIBPCRE
2358 parse_conf_file(RKLINE_TYPE, cold);
2359 parse_conf_file(RXLINE_TYPE, cold);
2360 #endif
2361 parse_conf_file(KLINE_TYPE, cold);
2362 parse_conf_file(DLINE_TYPE, cold);
2363 parse_conf_file(XLINE_TYPE, cold);
2364 parse_conf_file(NRESV_TYPE, cold);
2365 parse_conf_file(CRESV_TYPE, cold);
2366 }
2367
2368 /* parse_conf_file()
2369 *
2370 * inputs - type of conf file to parse
2371 * output - none
2372 * side effects - conf file for givenconf type is opened and read then parsed
2373 */
2374 static void
2375 parse_conf_file(int type, int cold)
2376 {
2377 FILE *file = NULL;
2378 const char *filename = get_conf_name(type);
2379
2380 if ((file = fopen(filename, "r")) == NULL)
2381 {
2382 if (cold)
2383 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2384 filename, strerror(errno));
2385 else
2386 sendto_realops_flags(UMODE_ALL, L_ALL,
2387 "Unable to read configuration file '%s': %s",
2388 filename, strerror(errno));
2389 }
2390 else
2391 {
2392 parse_csv_file(file, type);
2393 fclose(file);
2394 }
2395 }
2396
2397 /* clear_out_old_conf()
2398 *
2399 * inputs - none
2400 * output - none
2401 * side effects - Clear out the old configuration
2402 */
2403 static void
2404 clear_out_old_conf(void)
2405 {
2406 dlink_node *ptr = NULL, *next_ptr = NULL;
2407 struct ConfItem *conf;
2408 struct AccessItem *aconf;
2409 struct ClassItem *cltmp;
2410 struct MatchItem *match_item;
2411 dlink_list *free_items [] = {
2412 &server_items, &oconf_items,
2413 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2414 &nresv_items, &cluster_items, &gdeny_items, &service_items, NULL
2415 };
2416
2417 dlink_list ** iterator = free_items; /* C is dumb */
2418
2419 /* We only need to free anything allocated by yyparse() here.
2420 * Resetting structs, etc, is taken care of by set_default_conf().
2421 */
2422
2423 for (; *iterator != NULL; iterator++)
2424 {
2425 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2426 {
2427 conf = ptr->data;
2428 /* XXX This is less than pretty */
2429 if (conf->type == SERVER_TYPE)
2430 {
2431 aconf = map_to_conf(conf);
2432
2433 if (aconf->clients != 0)
2434 {
2435 SetConfIllegal(aconf);
2436 dlinkDelete(&conf->node, &server_items);
2437 }
2438 else
2439 {
2440 delete_conf_item(conf);
2441 }
2442 }
2443 else if (conf->type == OPER_TYPE)
2444 {
2445 aconf = map_to_conf(conf);
2446
2447 if (aconf->clients != 0)
2448 {
2449 SetConfIllegal(aconf);
2450 dlinkDelete(&conf->node, &oconf_items);
2451 }
2452 else
2453 {
2454 delete_conf_item(conf);
2455 }
2456 }
2457 else if (conf->type == XLINE_TYPE ||
2458 conf->type == RXLINE_TYPE ||
2459 conf->type == RKLINE_TYPE)
2460 {
2461 /* temporary (r)xlines are also on
2462 * the (r)xconf items list */
2463 if (conf->flags & CONF_FLAGS_TEMPORARY)
2464 continue;
2465
2466 delete_conf_item(conf);
2467 }
2468 else
2469 {
2470 delete_conf_item(conf);
2471 }
2472 }
2473 }
2474
2475 /*
2476 * don't delete the class table, rather mark all entries
2477 * for deletion. The table is cleaned up by check_class. - avalon
2478 */
2479 DLINK_FOREACH(ptr, class_items.head)
2480 {
2481 cltmp = map_to_conf(ptr->data);
2482
2483 if (ptr != class_items.tail) /* never mark the "default" class */
2484 cltmp->active = 0;
2485 }
2486
2487 clear_out_address_conf();
2488
2489 /* clean out module paths */
2490 mod_clear_paths();
2491
2492 /* clean out ServerInfo */
2493 MyFree(ServerInfo.description);
2494 ServerInfo.description = NULL;
2495 MyFree(ServerInfo.network_name);
2496 ServerInfo.network_name = NULL;
2497 MyFree(ServerInfo.network_desc);
2498 ServerInfo.network_desc = NULL;
2499 MyFree(ConfigFileEntry.egdpool_path);
2500 ConfigFileEntry.egdpool_path = NULL;
2501 #ifdef HAVE_LIBCRYPTO
2502 if (ServerInfo.rsa_private_key != NULL)
2503 {
2504 RSA_free(ServerInfo.rsa_private_key);
2505 ServerInfo.rsa_private_key = NULL;
2506 }
2507
2508 MyFree(ServerInfo.rsa_private_key_file);
2509 ServerInfo.rsa_private_key_file = NULL;
2510
2511 if (ServerInfo.server_ctx)
2512 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2513 SSL_OP_NO_SSLv3|
2514 SSL_OP_NO_TLSv1);
2515 if (ServerInfo.client_ctx)
2516 SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2517 SSL_OP_NO_SSLv3|
2518 SSL_OP_NO_TLSv1);
2519 #endif
2520
2521 /* clean out old resvs from the conf */
2522 clear_conf_resv();
2523
2524 /* clean out AdminInfo */
2525 MyFree(AdminInfo.name);
2526 AdminInfo.name = NULL;
2527 MyFree(AdminInfo.email);
2528 AdminInfo.email = NULL;
2529 MyFree(AdminInfo.description);
2530 AdminInfo.description = NULL;
2531
2532 /* operator{} and class{} blocks are freed above */
2533 /* clean out listeners */
2534 close_listeners();
2535
2536 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2537 * exempt{} and gecos{} blocks are freed above too
2538 */
2539
2540 /* clean out general */
2541 MyFree(ConfigFileEntry.service_name);
2542 ConfigFileEntry.service_name = NULL;
2543
2544 delete_isupport("INVEX");
2545 delete_isupport("EXCEPTS");
2546 }
2547
2548 /* flush_deleted_I_P()
2549 *
2550 * inputs - none
2551 * output - none
2552 * side effects - This function removes I/P conf items
2553 */
2554 static void
2555 flush_deleted_I_P(void)
2556 {
2557 dlink_node *ptr;
2558 dlink_node *next_ptr;
2559 struct ConfItem *conf;
2560 struct AccessItem *aconf;
2561 dlink_list * free_items [] = {
2562 &server_items, &oconf_items, NULL
2563 };
2564 dlink_list ** iterator = free_items; /* C is dumb */
2565
2566 /* flush out deleted I and P lines
2567 * although still in use.
2568 */
2569 for (; *iterator != NULL; iterator++)
2570 {
2571 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2572 {
2573 conf = ptr->data;
2574 aconf = (struct AccessItem *)map_to_conf(conf);
2575
2576 if (IsConfIllegal(aconf))
2577 {
2578 dlinkDelete(ptr, *iterator);
2579
2580 if (aconf->clients == 0)
2581 delete_conf_item(conf);
2582 }
2583 }
2584 }
2585 }
2586
2587 /* get_conf_name()
2588 *
2589 * inputs - type of conf file to return name of file for
2590 * output - pointer to filename for type of conf
2591 * side effects - none
2592 */
2593 const char *
2594 get_conf_name(ConfType type)
2595 {
2596 switch (type)
2597 {
2598 case CONF_TYPE:
2599 return ConfigFileEntry.configfile;
2600 break;
2601 case KLINE_TYPE:
2602 return ConfigFileEntry.klinefile;
2603 break;
2604 case RKLINE_TYPE:
2605 return ConfigFileEntry.rklinefile;
2606 break;
2607 case DLINE_TYPE:
2608 return ConfigFileEntry.dlinefile;
2609 break;
2610 case XLINE_TYPE:
2611 return ConfigFileEntry.xlinefile;
2612 break;
2613 case RXLINE_TYPE:
2614 return ConfigFileEntry.rxlinefile;
2615 break;
2616 case CRESV_TYPE:
2617 return ConfigFileEntry.cresvfile;
2618 break;
2619 case NRESV_TYPE:
2620 return ConfigFileEntry.nresvfile;
2621 break;
2622 case GLINE_TYPE:
2623 return ConfigFileEntry.glinefile;
2624 break;
2625
2626 default:
2627 return NULL; /* This should NEVER HAPPEN since we call this function
2628 only with the above values, this will cause us to core
2629 at some point if this happens so we know where it was */
2630 }
2631 }
2632
2633 #define BAD_PING (-1)
2634
2635 /* get_conf_ping()
2636 *
2637 * inputs - pointer to struct AccessItem
2638 * - pointer to a variable that receives ping warning time
2639 * output - ping frequency
2640 * side effects - NONE
2641 */
2642 static int
2643 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2644 {
2645 struct ClassItem *aclass;
2646 struct AccessItem *aconf;
2647
2648 if (conf != NULL)
2649 {
2650 aconf = (struct AccessItem *)map_to_conf(conf);
2651 if (aconf->class_ptr != NULL)
2652 {
2653 aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2654 *pingwarn = aclass->ping_warning;
2655 return aclass->ping_freq;
2656 }
2657 }
2658
2659 return BAD_PING;
2660 }
2661
2662 /* get_client_class()
2663 *
2664 * inputs - pointer to client struct
2665 * output - pointer to name of class
2666 * side effects - NONE
2667 */
2668 const char *
2669 get_client_class(struct Client *target_p)
2670 {
2671 dlink_node *cnode = NULL;
2672 struct AccessItem *aconf = NULL;
2673
2674 assert(!IsMe(target_p));
2675
2676 if ((cnode = target_p->localClient->confs.head))
2677 {
2678 struct ConfItem *conf = cnode->data;
2679
2680 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2681 (conf->type == OPER_TYPE));
2682
2683 aconf = map_to_conf(conf);
2684 if (aconf->class_ptr != NULL)
2685 return aconf->class_ptr->name;
2686 }
2687
2688 return "default";
2689 }
2690
2691 /* get_client_ping()
2692 *
2693 * inputs - pointer to client struct
2694 * - pointer to a variable that receives ping warning time
2695 * output - ping frequency
2696 * side effects - NONE
2697 */
2698 int
2699 get_client_ping(struct Client *target_p, int *pingwarn)
2700 {
2701 int ping = 0;
2702 dlink_node *cnode = NULL;
2703
2704 if ((cnode = target_p->localClient->confs.head))
2705 {
2706 struct ConfItem *conf = cnode->data;
2707
2708 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2709 (conf->type == OPER_TYPE));
2710
2711 ping = get_conf_ping(conf, pingwarn);
2712 if (ping > 0)
2713 return ping;
2714 }
2715
2716 *pingwarn = 0;
2717 return DEFAULT_PINGFREQUENCY;
2718 }
2719
2720 /* find_class()
2721 *
2722 * inputs - string name of class
2723 * output - corresponding Class pointer
2724 * side effects - NONE
2725 */
2726 struct ConfItem *
2727 find_class(const char *classname)
2728 {
2729 struct ConfItem *conf;
2730
2731 if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2732 return conf;
2733
2734 return class_default;
2735 }
2736
2737 /* check_class()
2738 *
2739 * inputs - NONE
2740 * output - NONE
2741 * side effects -
2742 */
2743 void
2744 check_class(void)
2745 {
2746 dlink_node *ptr = NULL, *next_ptr = NULL;
2747
2748 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2749 {
2750 struct ClassItem *aclass = map_to_conf(ptr->data);
2751
2752 if (!aclass->active && !aclass->curr_user_count)
2753 {
2754 destroy_cidr_class(aclass);
2755 delete_conf_item(ptr->data);
2756 }
2757 }
2758 }
2759
2760 /* init_class()
2761 *
2762 * inputs - NONE
2763 * output - NONE
2764 * side effects -
2765 */
2766 void
2767 init_class(void)
2768 {
2769 struct ClassItem *aclass;
2770
2771 class_default = make_conf_item(CLASS_TYPE);
2772
2773 aclass = map_to_conf(class_default);
2774 aclass->active = 1;
2775 DupString(class_default->name, "default");
2776 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
2777 aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2778 aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2779 aclass->max_sendq = DEFAULT_SENDQ;
2780
2781 client_check_cb = register_callback("check_client", check_client);
2782 }
2783
2784 /* get_sendq()
2785 *
2786 * inputs - pointer to client
2787 * output - sendq for this client as found from its class
2788 * side effects - NONE
2789 */
2790 unsigned int
2791 get_sendq(struct Client *client_p)
2792 {
2793 unsigned int sendq = DEFAULT_SENDQ;
2794 dlink_node *cnode;
2795 struct ConfItem *class_conf;
2796 struct ClassItem *aclass;
2797 struct AccessItem *aconf;
2798
2799 assert(!IsMe(client_p));
2800
2801 if ((cnode = client_p->localClient->confs.head))
2802 {
2803 struct ConfItem *conf = cnode->data;
2804
2805 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2806 (conf->type == OPER_TYPE));
2807
2808 aconf = map_to_conf(conf);
2809
2810 if ((class_conf = aconf->class_ptr) == NULL)
2811 return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2812
2813 aclass = map_to_conf(class_conf);
2814 sendq = aclass->max_sendq;
2815 return sendq;
2816 }
2817
2818 /* XXX return a default?
2819 * if here, then there wasn't an attached conf with a sendq
2820 * that is very bad -Dianora
2821 */
2822 return DEFAULT_SENDQ;
2823 }
2824
2825 /* conf_add_class_to_conf()
2826 *
2827 * inputs - pointer to config item
2828 * output - NONE
2829 * side effects - Add a class pointer to a conf
2830 */
2831 void
2832 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2833 {
2834 struct AccessItem *aconf = map_to_conf(conf);
2835 struct ClassItem *class = NULL;
2836
2837 if (class_name == NULL)
2838 {
2839 aconf->class_ptr = class_default;
2840
2841 if (conf->type == CLIENT_TYPE)
2842 sendto_realops_flags(UMODE_ALL, L_ALL,
2843 "Warning *** Defaulting to default class for %s@%s",
2844 aconf->user, aconf->host);
2845 else
2846 sendto_realops_flags(UMODE_ALL, L_ALL,
2847 "Warning *** Defaulting to default class for %s",
2848 conf->name);
2849 }
2850 else
2851 aconf->class_ptr = find_class(class_name);
2852
2853 if (aconf->class_ptr)
2854 class = map_to_conf(aconf->class_ptr);
2855
2856 if (aconf->class_ptr == NULL || !class->active)
2857 {
2858 if (conf->type == CLIENT_TYPE)
2859 sendto_realops_flags(UMODE_ALL, L_ALL,
2860 "Warning *** Defaulting to default class for %s@%s",
2861 aconf->user, aconf->host);
2862 else
2863 sendto_realops_flags(UMODE_ALL, L_ALL,
2864 "Warning *** Defaulting to default class for %s",
2865 conf->name);
2866 aconf->class_ptr = class_default;
2867 }
2868 }
2869
2870 /* conf_add_server()
2871 *
2872 * inputs - pointer to config item
2873 * - pointer to link count already on this conf
2874 * output - NONE
2875 * side effects - Add a connect block
2876 */
2877 int
2878 conf_add_server(struct ConfItem *conf, const char *class_name)
2879 {
2880 struct AccessItem *aconf = map_to_conf(conf);
2881
2882 conf_add_class_to_conf(conf, class_name);
2883
2884 if (!aconf->host || !conf->name)
2885 {
2886 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2887 ilog(LOG_TYPE_IRCD, "Bad connect block");
2888 return -1;
2889 }
2890
2891 if (EmptyString(aconf->passwd))
2892 {
2893 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2894 conf->name);
2895 ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2896 return -1;
2897 }
2898
2899 lookup_confhost(conf);
2900
2901 return 0;
2902 }
2903
2904 /* yyerror()
2905 *
2906 * inputs - message from parser
2907 * output - NONE
2908 * side effects - message to opers and log file entry is made
2909 */
2910 void
2911 yyerror(const char *msg)
2912 {
2913 char newlinebuf[IRCD_BUFSIZE];
2914
2915 if (conf_parser_ctx.pass != 1)
2916 return;
2917
2918 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2919 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2920 conffilebuf, lineno + 1, msg, newlinebuf);
2921 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
2922 conffilebuf, lineno + 1, msg, newlinebuf);
2923 }
2924
2925 /*
2926 * valid_tkline()
2927 *
2928 * inputs - pointer to ascii string to check
2929 * - whether the specified time is in seconds or minutes
2930 * output - -1 not enough parameters
2931 * - 0 if not an integer number, else the number
2932 * side effects - none
2933 * Originally written by Dianora (Diane, db@db.net)
2934 */
2935 time_t
2936 valid_tkline(const char *p, int minutes)
2937 {
2938 time_t result = 0;
2939
2940 for (; *p; ++p)
2941 {
2942 if (!IsDigit(*p))
2943 return 0;
2944
2945 result *= 10;
2946 result += ((*p) & 0xF);
2947 }
2948
2949 /*
2950 * In the degenerate case where oper does a /quote kline 0 user@host :reason
2951 * i.e. they specifically use 0, I am going to return 1 instead
2952 * as a return value of non-zero is used to flag it as a temporary kline
2953 */
2954 if (result == 0)
2955 result = 1;
2956
2957 /*
2958 * If the incoming time is in seconds convert it to minutes for the purpose
2959 * of this calculation
2960 */
2961 if (!minutes)
2962 result = result / (time_t)60;
2963
2964 if (result > MAX_TDKLINE_TIME)
2965 result = MAX_TDKLINE_TIME;
2966
2967 result = result * (time_t)60; /* turn it into seconds */
2968
2969 return result;
2970 }
2971
2972 /* valid_wild_card()
2973 *
2974 * input - pointer to client
2975 * - int flag, 0 for no warning oper 1 for warning oper
2976 * - count of following varargs to check
2977 * output - 0 if not valid, 1 if valid
2978 * side effects - NOTICE is given to source_p if warn is 1
2979 */
2980 int
2981 valid_wild_card(struct Client *source_p, int warn, int count, ...)
2982 {
2983 char *p;
2984 char tmpch;
2985 int nonwild = 0;
2986 va_list args;
2987
2988 /*
2989 * Now we must check the user and host to make sure there
2990 * are at least NONWILDCHARS non-wildcard characters in
2991 * them, otherwise assume they are attempting to kline
2992 * *@* or some variant of that. This code will also catch
2993 * people attempting to kline *@*.tld, as long as NONWILDCHARS
2994 * is greater than 3. In that case, there are only 3 non-wild
2995 * characters (tld), so if NONWILDCHARS is 4, the kline will
2996 * be disallowed.
2997 * -wnder
2998 */
2999
3000 va_start(args, count);
3001
3002 while (count--)
3003 {
3004 p = va_arg(args, char *);
3005 if (p == NULL)
3006 continue;
3007
3008 while ((tmpch = *p++))
3009 {
3010 if (!IsKWildChar(tmpch))
3011 {
3012 /*
3013 * If we find enough non-wild characters, we can
3014 * break - no point in searching further.
3015 */
3016 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3017 return 1;
3018 }
3019 }
3020 }
3021
3022 if (warn)
3023 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3024 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3025 return 0;
3026 }
3027
3028 /* XXX should this go into a separate file ? -Dianora */
3029 /* parse_aline
3030 *
3031 * input - pointer to cmd name being used
3032 * - pointer to client using cmd
3033 * - parc parameter count
3034 * - parv[] list of parameters to parse
3035 * - parse_flags bit map of things to test
3036 * - pointer to user or string to parse into
3037 * - pointer to host or NULL to parse into if non NULL
3038 * - pointer to optional tkline time or NULL
3039 * - pointer to target_server to parse into if non NULL
3040 * - pointer to reason to parse into
3041 *
3042 * output - 1 if valid, -1 if not valid
3043 * side effects - A generalised k/d/x etc. line parser,
3044 * "ALINE [time] user@host|string [ON] target :reason"
3045 * will parse returning a parsed user, host if
3046 * h_p pointer is non NULL, string otherwise.
3047 * if tkline_time pointer is non NULL a tk line will be set
3048 * to non zero if found.
3049 * if tkline_time pointer is NULL and tk line is found,
3050 * error is reported.
3051 * if target_server is NULL and an "ON" is found error
3052 * is reported.
3053 * if reason pointer is NULL ignore pointer,
3054 * this allows use of parse_a_line in unkline etc.
3055 *
3056 * - Dianora
3057 */
3058 int
3059 parse_aline(const char *cmd, struct Client *source_p,
3060 int parc, char **parv,
3061 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3062 char **target_server, char **reason)
3063 {
3064 int found_tkline_time=0;
3065 static char def_reason[] = "No Reason";
3066 static char user[USERLEN*4+1];
3067 static char host[HOSTLEN*4+1];
3068
3069 parv++;
3070 parc--;
3071
3072 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3073
3074 if (found_tkline_time != 0)
3075 {
3076 parv++;
3077 parc--;
3078
3079 if (tkline_time != NULL)
3080 *tkline_time = found_tkline_time;
3081 else
3082 {
3083 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3084 me.name, source_p->name, cmd);
3085 return -1;
3086 }
3087 }
3088
3089 if (parc == 0)
3090 {
3091 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3092 me.name, source_p->name, cmd);
3093 return -1;
3094 }
3095
3096 if (h_p == NULL)
3097 *up_p = *parv;
3098 else
3099 {
3100 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3101 return -1;
3102
3103 *up_p = user;
3104 *h_p = host;
3105 }
3106
3107 parc--;
3108 parv++;
3109
3110 if (parc != 0)
3111 {
3112 if (irccmp(*parv, "ON") == 0)
3113 {
3114 parc--;
3115 parv++;
3116
3117 if (target_server == NULL)
3118 {
3119 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3120 me.name, source_p->name, cmd);
3121 return -1;
3122 }
3123
3124 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
3125 {
3126 sendto_one(source_p, form_str(ERR_NOPRIVS),
3127 me.name, source_p->name, "remoteban");
3128 return -1;
3129 }
3130
3131 if (parc == 0 || EmptyString(*parv))
3132 {
3133 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3134 me.name, source_p->name, cmd);
3135 return -1;
3136 }
3137
3138 *target_server = *parv;
3139 parc--;
3140 parv++;
3141 }
3142 else
3143 {
3144 /* Make sure target_server *is* NULL if no ON server found
3145 * caller probably NULL'd it first, but no harm to do it again -db
3146 */
3147 if (target_server != NULL)
3148 *target_server = NULL;
3149 }
3150 }
3151
3152 if (h_p != NULL)
3153 {
3154 if (strchr(user, '!') != NULL)
3155 {
3156 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3157 me.name, source_p->name);
3158 return -1;
3159 }
3160
3161 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
3162 return -1;
3163 }
3164 else
3165 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
3166 return -1;
3167
3168 if (reason != NULL)
3169 {
3170 if (parc != 0 && !EmptyString(*parv))
3171 {
3172 *reason = *parv;
3173 if (!valid_comment(source_p, *reason, 1))
3174 return -1;
3175 }
3176 else
3177 *reason = def_reason;
3178 }
3179
3180 return 1;
3181 }
3182
3183 /* find_user_host()
3184 *
3185 * inputs - pointer to client placing kline
3186 * - pointer to user_host_or_nick
3187 * - pointer to user buffer
3188 * - pointer to host buffer
3189 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3190 * side effects -
3191 */
3192 static int
3193 find_user_host(struct Client *source_p, char *user_host_or_nick,
3194 char *luser, char *lhost, unsigned int flags)
3195 {
3196 struct Client *target_p = NULL;
3197 char *hostp = NULL;
3198
3199 if (lhost == NULL)
3200 {
3201 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3202 return 1;
3203 }
3204
3205 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3206 {
3207 /* Explicit user@host mask given */
3208
3209 if (hostp != NULL) /* I'm a little user@host */
3210 {
3211 *(hostp++) = '\0'; /* short and squat */
3212 if (*user_host_or_nick)
3213 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3214 else
3215 strcpy(luser, "*");
3216 if (*hostp)
3217 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3218 else
3219 strcpy(lhost, "*");
3220 }
3221 else
3222 {
3223 luser[0] = '*'; /* no @ found, assume its *@somehost */
3224 luser[1] = '\0';
3225 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3226 }
3227
3228 return 1;
3229 }
3230 else if (!(flags & NOUSERLOOKUP))
3231 {
3232 /* Try to find user@host mask from nick */
3233 /* Okay to use source_p as the first param, because source_p == client_p */
3234 if ((target_p =
3235 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3236 return 0;
3237
3238 if (IsExemptKline(target_p))
3239 {
3240 if (!IsServer(source_p))
3241 sendto_one(source_p,
3242 ":%s NOTICE %s :%s is E-lined",
3243 me.name, source_p->name, target_p->name);
3244 return 0;
3245 }
3246
3247 /*
3248 * turn the "user" bit into "*user", blow away '~'
3249 * if found in original user name (non-idented)
3250 */
3251 strlcpy(luser, target_p->username, USERLEN*4 + 1);
3252
3253 if (target_p->username[0] == '~')
3254 luser[0] = '*';
3255
3256 if (target_p->sockhost[0] == '\0' ||
3257 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3258 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3259 else
3260 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3261 return 1;
3262 }
3263
3264 return 0;
3265 }
3266
3267 /* valid_comment()
3268 *
3269 * inputs - pointer to client
3270 * - pointer to comment
3271 * output - 0 if no valid comment,
3272 * - 1 if valid
3273 * side effects - truncates reason where necessary
3274 */
3275 int
3276 valid_comment(struct Client *source_p, char *comment, int warn)
3277 {
3278 if (strchr