ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 99
Committed: Sun Oct 9 14:33:36 2005 UTC (19 years, 10 months ago) by michael
Content type: text/x-csrc
File size: 83417 byte(s)
Log Message:
- CHANNELLEN vs. LOCAL_CHANNELLEN fix.  Local JOINs are limited to 50chars whereas
  remote SJOINs/JOINs can be upto 200chars for backwards compatibility.

File Contents

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

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision