ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1632
Committed: Sun Nov 4 15:37:10 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 74851 byte(s)
Log Message:
- Initial rewrite of the configuration subsystem

File Contents

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

Properties

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