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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1156 - (show annotations)
Tue Aug 9 20:29:20 2011 UTC (8 years, 3 months ago) by michael
File MIME type: text/x-chdr
File size: 99290 byte(s)
- create ircd-hybrid-8 "branch"

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