ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1285
Committed: Sun Feb 5 15:12:59 2012 UTC (13 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100850 byte(s)
Log Message:
- added CIDR support for operator{} blocks
- operator "name"{} is no longer supported

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

Properties

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