ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1519
Committed: Wed Sep 5 12:02:04 2012 UTC (11 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92464 byte(s)
Log Message:
- Topics as well as user-aways are now sent in a burst by default

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

Properties

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