ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1490
Committed: Sat Jul 28 19:33:23 2012 UTC (13 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 92416 byte(s)
Log Message:
- removed serverhide::disable_hidden configuration option
- update NEWS

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
311 break;
312
313 default:
314 conf = NULL;
315 break;
316 }
317
318 /* XXX Yes, this will core if default is hit. I want it to for now - db */
319 conf->type = type;
320
321 return conf;
322 }
323
324 void
325 delete_conf_item(struct ConfItem *conf)
326 {
327 dlink_node *m = NULL, *m_next = NULL;
328 struct MatchItem *match_item;
329 struct AccessItem *aconf;
330 ConfType type = conf->type;
331
332 MyFree(conf->name);
333 conf->name = NULL;
334
335 switch(type)
336 {
337 case DLINE_TYPE:
338 case EXEMPTDLINE_TYPE:
339 case GLINE_TYPE:
340 case KLINE_TYPE:
341 case CLIENT_TYPE:
342 case OPER_TYPE:
343 case SERVER_TYPE:
344 aconf = map_to_conf(conf);
345
346 if (aconf->dns_pending)
347 delete_resolver_queries(aconf);
348 if (aconf->passwd != NULL)
349 memset(aconf->passwd, 0, strlen(aconf->passwd));
350 if (aconf->spasswd != NULL)
351 memset(aconf->spasswd, 0, strlen(aconf->spasswd));
352 aconf->class_ptr = NULL;
353
354 MyFree(aconf->passwd);
355 MyFree(aconf->spasswd);
356 MyFree(aconf->reason);
357 MyFree(aconf->oper_reason);
358 MyFree(aconf->user);
359 MyFree(aconf->host);
360 #ifdef HAVE_LIBCRYPTO
361 MyFree(aconf->cipher_list);
362
363 if (aconf->rsa_public_key)
364 RSA_free(aconf->rsa_public_key);
365 MyFree(aconf->rsa_public_key_file);
366 #endif
367
368 /* Yes, sigh. switch on type again */
369 switch(type)
370 {
371 case EXEMPTDLINE_TYPE:
372 case DLINE_TYPE:
373 case GLINE_TYPE:
374 case KLINE_TYPE:
375 case CLIENT_TYPE:
376 MyFree(conf);
377 break;
378
379 case OPER_TYPE:
380 aconf = map_to_conf(conf);
381 if (!IsConfIllegal(aconf))
382 dlinkDelete(&conf->node, &oconf_items);
383 MyFree(conf);
384 break;
385
386 case SERVER_TYPE:
387 aconf = map_to_conf(conf);
388
389 DLINK_FOREACH_SAFE(m, m_next, aconf->hub_list.head)
390 {
391 MyFree(m->data);
392 free_dlink_node(m);
393 }
394
395 DLINK_FOREACH_SAFE(m, m_next, aconf->leaf_list.head)
396 {
397 MyFree(m->data);
398 free_dlink_node(m);
399 }
400
401 if (!IsConfIllegal(aconf))
402 dlinkDelete(&conf->node, &server_items);
403 MyFree(conf);
404 break;
405
406 default:
407 break;
408 }
409 break;
410
411 case ULINE_TYPE:
412 match_item = map_to_conf(conf);
413 MyFree(match_item->user);
414 MyFree(match_item->host);
415 MyFree(match_item->reason);
416 MyFree(match_item->oper_reason);
417 dlinkDelete(&conf->node, &uconf_items);
418 MyFree(conf);
419 break;
420
421 case XLINE_TYPE:
422 match_item = map_to_conf(conf);
423 MyFree(match_item->user);
424 MyFree(match_item->host);
425 MyFree(match_item->reason);
426 MyFree(match_item->oper_reason);
427 dlinkDelete(&conf->node, &xconf_items);
428 MyFree(conf);
429 break;
430 #ifdef HAVE_LIBPCRE
431 case RKLINE_TYPE:
432 aconf = map_to_conf(conf);
433 MyFree(aconf->regexuser);
434 MyFree(aconf->regexhost);
435 MyFree(aconf->user);
436 MyFree(aconf->host);
437 MyFree(aconf->reason);
438 MyFree(aconf->oper_reason);
439 dlinkDelete(&conf->node, &rkconf_items);
440 MyFree(conf);
441 break;
442
443 case RXLINE_TYPE:
444 MyFree(conf->regexpname);
445 match_item = map_to_conf(conf);
446 MyFree(match_item->user);
447 MyFree(match_item->host);
448 MyFree(match_item->reason);
449 MyFree(match_item->oper_reason);
450 dlinkDelete(&conf->node, &rxconf_items);
451 MyFree(conf);
452 break;
453 #endif
454 case NRESV_TYPE:
455 match_item = map_to_conf(conf);
456 MyFree(match_item->user);
457 MyFree(match_item->host);
458 MyFree(match_item->reason);
459 MyFree(match_item->oper_reason);
460 dlinkDelete(&conf->node, &nresv_items);
461
462 if (conf->flags & CONF_FLAGS_TEMPORARY)
463 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
464 free_dlink_node(m);
465
466 MyFree(conf);
467 break;
468
469 case CLUSTER_TYPE:
470 dlinkDelete(&conf->node, &cluster_items);
471 MyFree(conf);
472 break;
473
474 case CRESV_TYPE:
475 if (conf->flags & CONF_FLAGS_TEMPORARY)
476 if ((m = dlinkFindDelete(&temporary_resv, conf)) != NULL)
477 free_dlink_node(m);
478
479 MyFree(conf);
480 break;
481
482 case CLASS_TYPE:
483 dlinkDelete(&conf->node, &class_items);
484 MyFree(conf);
485 break;
486
487 case SERVICE_TYPE:
488 dlinkDelete(&conf->node, &service_items);
489 MyFree(conf);
490 break;
491
492 default:
493 break;
494 }
495 }
496
497 /* free_access_item()
498 *
499 * inputs - pointer to conf to free
500 * output - none
501 * side effects - crucial password fields are zeroed, conf is freed
502 */
503 void
504 free_access_item(struct AccessItem *aconf)
505 {
506 struct ConfItem *conf;
507
508 if (aconf == NULL)
509 return;
510 conf = unmap_conf_item(aconf);
511 delete_conf_item(conf);
512 }
513
514 static const unsigned int shared_bit_table[] =
515 { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
516
517 /* report_confitem_types()
518 *
519 * inputs - pointer to client requesting confitem report
520 * - ConfType to report
521 * output - none
522 * side effects -
523 */
524 void
525 report_confitem_types(struct Client *source_p, ConfType type)
526 {
527 dlink_node *ptr = NULL, *dptr = NULL;
528 struct ConfItem *conf = NULL;
529 struct AccessItem *aconf = NULL;
530 struct MatchItem *matchitem = NULL;
531 struct ClassItem *classitem = NULL;
532 char buf[12];
533 char *p = NULL;
534
535 switch (type)
536 {
537 case XLINE_TYPE:
538 DLINK_FOREACH(ptr, xconf_items.head)
539 {
540 conf = ptr->data;
541 matchitem = map_to_conf(conf);
542
543 sendto_one(source_p, form_str(RPL_STATSXLINE),
544 me.name, source_p->name,
545 matchitem->hold ? "x": "X", matchitem->count,
546 conf->name, matchitem->reason);
547 }
548 break;
549
550 #ifdef HAVE_LIBPCRE
551 case RXLINE_TYPE:
552 DLINK_FOREACH(ptr, rxconf_items.head)
553 {
554 conf = ptr->data;
555 matchitem = map_to_conf(conf);
556
557 sendto_one(source_p, form_str(RPL_STATSXLINE),
558 me.name, source_p->name,
559 "XR", matchitem->count,
560 conf->name, matchitem->reason);
561 }
562 break;
563
564 case RKLINE_TYPE:
565 DLINK_FOREACH(ptr, rkconf_items.head)
566 {
567 aconf = map_to_conf((conf = ptr->data));
568
569 sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
570 source_p->name, "KR", aconf->host, aconf->user,
571 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
572 }
573 break;
574 #endif
575
576 case ULINE_TYPE:
577 DLINK_FOREACH(ptr, uconf_items.head)
578 {
579 conf = ptr->data;
580 matchitem = map_to_conf(conf);
581
582 p = buf;
583
584 /* some of these are redundant for the sake of
585 * consistency with cluster{} flags
586 */
587 *p++ = 'c';
588 flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
589
590 sendto_one(source_p, form_str(RPL_STATSULINE),
591 me.name, source_p->name, conf->name,
592 matchitem->user?matchitem->user: "*",
593 matchitem->host?matchitem->host: "*", buf);
594 }
595
596 DLINK_FOREACH(ptr, cluster_items.head)
597 {
598 conf = ptr->data;
599
600 p = buf;
601
602 *p++ = 'C';
603 flags_to_ascii(conf->flags, shared_bit_table, p, 0);
604
605 sendto_one(source_p, form_str(RPL_STATSULINE),
606 me.name, source_p->name, conf->name,
607 "*", "*", buf);
608 }
609
610 break;
611
612 case OPER_TYPE:
613 DLINK_FOREACH(ptr, oconf_items.head)
614 {
615 conf = ptr->data;
616 aconf = map_to_conf(conf);
617
618 /* Don't allow non opers to see oper privs */
619 if (HasUMode(source_p, UMODE_OPER))
620 sendto_one(source_p, form_str(RPL_STATSOLINE),
621 me.name, source_p->name, 'O', aconf->user, aconf->host,
622 conf->name, oper_privs_as_string(aconf->port),
623 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
624 else
625 sendto_one(source_p, form_str(RPL_STATSOLINE),
626 me.name, source_p->name, 'O', aconf->user, aconf->host,
627 conf->name, "0",
628 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
629 }
630 break;
631
632 case CLASS_TYPE:
633 DLINK_FOREACH(ptr, class_items.head)
634 {
635 conf = ptr->data;
636 classitem = map_to_conf(conf);
637 sendto_one(source_p, form_str(RPL_STATSYLINE),
638 me.name, source_p->name, 'Y',
639 conf->name, classitem->ping_freq,
640 classitem->con_freq,
641 classitem->max_total, classitem->max_sendq,
642 classitem->curr_user_count,
643 classitem->number_per_cidr, classitem->cidr_bitlen_ipv4,
644 classitem->number_per_cidr, classitem->cidr_bitlen_ipv6,
645 classitem->active ? "active" : "disabled");
646 }
647 break;
648
649 case CONF_TYPE:
650 case CLIENT_TYPE:
651 break;
652
653 case SERVICE_TYPE:
654 DLINK_FOREACH(ptr, service_items.head)
655 {
656 conf = ptr->data;
657 sendto_one(source_p, form_str(RPL_STATSSERVICE),
658 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
659 }
660 break;
661
662 case SERVER_TYPE:
663 DLINK_FOREACH(ptr, server_items.head)
664 {
665 p = buf;
666
667 conf = ptr->data;
668 aconf = map_to_conf(conf);
669
670 buf[0] = '\0';
671
672 if (IsConfAllowAutoConn(aconf))
673 *p++ = 'A';
674 if (IsConfSSL(aconf))
675 *p++ = 'S';
676 if (IsConfTopicBurst(aconf))
677 *p++ = 'T';
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.use_invex = 1;
1788 ConfigChannel.use_except = 1;
1789 ConfigChannel.use_knock = 1;
1790 ConfigChannel.knock_delay = 300;
1791 ConfigChannel.knock_delay_channel = 60;
1792 ConfigChannel.max_chans_per_user = 25;
1793 ConfigChannel.max_chans_per_oper = 50;
1794 ConfigChannel.quiet_on_ban = 1;
1795 ConfigChannel.max_bans = 25;
1796 ConfigChannel.default_split_user_count = 0;
1797 ConfigChannel.default_split_server_count = 0;
1798 ConfigChannel.no_join_on_split = 0;
1799 ConfigChannel.no_create_on_split = 0;
1800
1801 ConfigServerHide.flatten_links = 0;
1802 ConfigServerHide.links_delay = 300;
1803 ConfigServerHide.hidden = 0;
1804 ConfigServerHide.hide_servers = 0;
1805 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1806 ConfigServerHide.hide_server_ips = 0;
1807
1808
1809 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1810 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1811 ConfigFileEntry.glines = 0;
1812 ConfigFileEntry.gline_time = 12 * 3600;
1813 ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1814 ConfigFileEntry.gline_min_cidr = 16;
1815 ConfigFileEntry.gline_min_cidr6 = 48;
1816 ConfigFileEntry.invisible_on_connect = 1;
1817 ConfigFileEntry.burst_away = 0;
1818 ConfigFileEntry.use_whois_actually = 1;
1819 ConfigFileEntry.tkline_expire_notices = 1;
1820 ConfigFileEntry.hide_spoof_ips = 1;
1821 ConfigFileEntry.ignore_bogus_ts = 0;
1822 ConfigFileEntry.disable_auth = 0;
1823 ConfigFileEntry.disable_remote = 0;
1824 ConfigFileEntry.kill_chase_time_limit = 90;
1825 ConfigFileEntry.default_floodcount = 8;
1826 ConfigFileEntry.failed_oper_notice = 1;
1827 ConfigFileEntry.dots_in_ident = 0;
1828 ConfigFileEntry.min_nonwildcard = 4;
1829 ConfigFileEntry.min_nonwildcard_simple = 3;
1830 ConfigFileEntry.max_accept = 20;
1831 ConfigFileEntry.anti_nick_flood = 0;
1832 ConfigFileEntry.max_nick_time = 20;
1833 ConfigFileEntry.max_nick_changes = 5;
1834 ConfigFileEntry.anti_spam_exit_message_time = 0;
1835 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1836 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1837 ConfigFileEntry.kline_with_reason = 1;
1838 ConfigFileEntry.kline_reason = NULL;
1839 ConfigFileEntry.warn_no_nline = 1;
1840 ConfigFileEntry.stats_o_oper_only = 0;
1841 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1842 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1843 ConfigFileEntry.stats_P_oper_only = 0;
1844 ConfigFileEntry.caller_id_wait = 60;
1845 ConfigFileEntry.opers_bypass_callerid = 0;
1846 ConfigFileEntry.pace_wait = 10;
1847 ConfigFileEntry.pace_wait_simple = 1;
1848 ConfigFileEntry.short_motd = 0;
1849 ConfigFileEntry.ping_cookie = 0;
1850 ConfigFileEntry.no_oper_flood = 0;
1851 ConfigFileEntry.true_no_oper_flood = 0;
1852 ConfigFileEntry.oper_pass_resv = 1;
1853 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1854 ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1855 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1856 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1857 UMODE_OPERWALL | UMODE_WALLOP;
1858 ConfigFileEntry.use_egd = 0;
1859 ConfigFileEntry.egdpool_path = NULL;
1860 ConfigFileEntry.throttle_time = 10;
1861 }
1862
1863 static void
1864 validate_conf(void)
1865 {
1866 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1867 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1868
1869 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1870 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1871
1872 if (ServerInfo.network_name == NULL)
1873 DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1874
1875 if (ServerInfo.network_desc == NULL)
1876 DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1877
1878 if (ConfigFileEntry.service_name == NULL)
1879 DupString(ConfigFileEntry.service_name, SERVICE_NAME_DEFAULT);
1880
1881 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1882 (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1883 ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1884
1885 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1886 }
1887
1888 /* read_conf()
1889 *
1890 * inputs - file descriptor pointing to config file to use
1891 * output - None
1892 * side effects - Read configuration file.
1893 */
1894 static void
1895 read_conf(FILE *file)
1896 {
1897 lineno = 0;
1898
1899 set_default_conf(); /* Set default values prior to conf parsing */
1900 conf_parser_ctx.pass = 1;
1901 yyparse(); /* pick up the classes first */
1902
1903 rewind(file);
1904
1905 conf_parser_ctx.pass = 2;
1906 yyparse(); /* Load the values from the conf */
1907 validate_conf(); /* Check to make sure some values are still okay. */
1908 /* Some global values are also loaded here. */
1909 check_class(); /* Make sure classes are valid */
1910 }
1911
1912 /* lookup_confhost()
1913 *
1914 * start DNS lookups of all hostnames in the conf
1915 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1916 */
1917 static void
1918 lookup_confhost(struct ConfItem *conf)
1919 {
1920 struct AccessItem *aconf;
1921 struct addrinfo hints, *res;
1922
1923 aconf = map_to_conf(conf);
1924
1925 if (has_wildcards(aconf->host))
1926 {
1927 ilog(LOG_TYPE_IRCD, "Host/server name error: (%s) (%s)",
1928 aconf->host, conf->name);
1929 return;
1930 }
1931
1932 /* Do name lookup now on hostnames given and store the
1933 * ip numbers in conf structure.
1934 */
1935 memset(&hints, 0, sizeof(hints));
1936
1937 hints.ai_family = AF_UNSPEC;
1938 hints.ai_socktype = SOCK_STREAM;
1939
1940 /* Get us ready for a bind() and don't bother doing dns lookup */
1941 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1942
1943 if (getaddrinfo(aconf->host, NULL, &hints, &res))
1944 {
1945 conf_dns_lookup(aconf);
1946 return;
1947 }
1948
1949 assert(res != NULL);
1950
1951 memcpy(&aconf->addr, res->ai_addr, res->ai_addrlen);
1952 aconf->addr.ss_len = res->ai_addrlen;
1953 aconf->addr.ss.ss_family = res->ai_family;
1954 freeaddrinfo(res);
1955 }
1956
1957 /* conf_connect_allowed()
1958 *
1959 * inputs - pointer to inaddr
1960 * - int type ipv4 or ipv6
1961 * output - BANNED or accepted
1962 * side effects - none
1963 */
1964 int
1965 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1966 {
1967 struct ip_entry *ip_found;
1968 struct AccessItem *aconf = find_dline_conf(addr, aftype);
1969
1970 /* DLINE exempt also gets you out of static limits/pacing... */
1971 if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1972 return 0;
1973
1974 if (aconf != NULL)
1975 return BANNED_CLIENT;
1976
1977 ip_found = find_or_add_ip(addr);
1978
1979 if ((CurrentTime - ip_found->last_attempt) <
1980 ConfigFileEntry.throttle_time)
1981 {
1982 ip_found->last_attempt = CurrentTime;
1983 return TOO_FAST;
1984 }
1985
1986 ip_found->last_attempt = CurrentTime;
1987 return 0;
1988 }
1989
1990 static struct AccessItem *
1991 find_regexp_kline(const char *uhi[])
1992 {
1993 #ifdef HAVE_LIBPCRE
1994 const dlink_node *ptr = NULL;
1995
1996 DLINK_FOREACH(ptr, rkconf_items.head)
1997 {
1998 struct AccessItem *aptr = map_to_conf(ptr->data);
1999
2000 assert(aptr->regexuser);
2001 assert(aptr->regexhost);
2002
2003 if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2004 (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2005 !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2006 return aptr;
2007 }
2008 #endif
2009 return NULL;
2010 }
2011
2012 /* find_kill()
2013 *
2014 * inputs - pointer to client structure
2015 * output - pointer to struct AccessItem if found
2016 * side effects - See if this user is klined already,
2017 * and if so, return struct AccessItem pointer
2018 */
2019 struct AccessItem *
2020 find_kill(struct Client *client_p)
2021 {
2022 struct AccessItem *aconf = NULL;
2023 const char *uhi[3];
2024
2025 uhi[0] = client_p->username;
2026 uhi[1] = client_p->host;
2027 uhi[2] = client_p->sockhost;
2028
2029 assert(client_p != NULL);
2030
2031 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2032 CONF_KLINE, client_p->localClient->aftype,
2033 client_p->username, NULL, 1);
2034 if (aconf == NULL)
2035 aconf = find_regexp_kline(uhi);
2036
2037 return aconf;
2038 }
2039
2040 struct AccessItem *
2041 find_gline(struct Client *client_p)
2042 {
2043 struct AccessItem *aconf;
2044
2045 assert(client_p != NULL);
2046
2047 aconf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
2048 CONF_GLINE, client_p->localClient->aftype,
2049 client_p->username, NULL, 1);
2050 return aconf;
2051 }
2052
2053 /* add_temp_line()
2054 *
2055 * inputs - pointer to struct ConfItem
2056 * output - none
2057 * Side effects - links in given struct ConfItem into
2058 * temporary *line link list
2059 */
2060 void
2061 add_temp_line(struct ConfItem *conf)
2062 {
2063 if (conf->type == XLINE_TYPE)
2064 {
2065 conf->flags |= CONF_FLAGS_TEMPORARY;
2066 dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2067 }
2068 else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2069 {
2070 conf->flags |= CONF_FLAGS_TEMPORARY;
2071 dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2072 }
2073 }
2074
2075 /* cleanup_tklines()
2076 *
2077 * inputs - NONE
2078 * output - NONE
2079 * side effects - call function to expire temporary k/d lines
2080 * This is an event started off in ircd.c
2081 */
2082 void
2083 cleanup_tklines(void *notused)
2084 {
2085 hostmask_expire_temporary();
2086 expire_tklines(&temporary_xlines);
2087 expire_tklines(&temporary_resv);
2088 }
2089
2090 /* expire_tklines()
2091 *
2092 * inputs - tkline list pointer
2093 * output - NONE
2094 * side effects - expire tklines
2095 */
2096 static void
2097 expire_tklines(dlink_list *tklist)
2098 {
2099 dlink_node *ptr;
2100 dlink_node *next_ptr;
2101 struct ConfItem *conf;
2102 struct MatchItem *xconf;
2103 struct MatchItem *nconf;
2104 struct ResvChannel *cconf;
2105
2106 DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2107 {
2108 conf = ptr->data;
2109
2110 if (conf->type == XLINE_TYPE)
2111 {
2112 xconf = (struct MatchItem *)map_to_conf(conf);
2113 if (xconf->hold <= CurrentTime)
2114 {
2115 if (ConfigFileEntry.tkline_expire_notices)
2116 sendto_realops_flags(UMODE_ALL, L_ALL,
2117 "Temporary X-line for [%s] sexpired", conf->name);
2118 dlinkDelete(ptr, tklist);
2119 free_dlink_node(ptr);
2120 delete_conf_item(conf);
2121 }
2122 }
2123 else if (conf->type == NRESV_TYPE)
2124 {
2125 nconf = (struct MatchItem *)map_to_conf(conf);
2126 if (nconf->hold <= CurrentTime)
2127 {
2128 if (ConfigFileEntry.tkline_expire_notices)
2129 sendto_realops_flags(UMODE_ALL, L_ALL,
2130 "Temporary RESV for [%s] expired", conf->name);
2131 dlinkDelete(ptr, tklist);
2132 free_dlink_node(ptr);
2133 delete_conf_item(conf);
2134 }
2135 }
2136 else if (conf->type == CRESV_TYPE)
2137 {
2138 cconf = (struct ResvChannel *)map_to_conf(conf);
2139 if (cconf->hold <= CurrentTime)
2140 {
2141 if (ConfigFileEntry.tkline_expire_notices)
2142 sendto_realops_flags(UMODE_ALL, L_ALL,
2143 "Temporary RESV for [%s] expired", cconf->name);
2144 delete_channel_resv(cconf);
2145 }
2146 }
2147 }
2148 }
2149
2150 /* oper_privs_as_string()
2151 *
2152 * inputs - pointer to client_p
2153 * output - pointer to static string showing oper privs
2154 * side effects - return as string, the oper privs as derived from port
2155 */
2156 static const struct oper_privs
2157 {
2158 const unsigned int oprivs;
2159 const unsigned char c;
2160 } flag_list[] = {
2161 { OPER_FLAG_ADMIN, 'A' },
2162 { OPER_FLAG_REMOTEBAN, 'B' },
2163 { OPER_FLAG_DIE, 'D' },
2164 { OPER_FLAG_GLINE, 'G' },
2165 { OPER_FLAG_REHASH, 'H' },
2166 { OPER_FLAG_K, 'K' },
2167 { OPER_FLAG_OPERWALL, 'L' },
2168 { OPER_FLAG_N, 'N' },
2169 { OPER_FLAG_GLOBAL_KILL, 'O' },
2170 { OPER_FLAG_REMOTE, 'R' },
2171 { OPER_FLAG_OPER_SPY, 'S' },
2172 { OPER_FLAG_UNKLINE, 'U' },
2173 { OPER_FLAG_X, 'X' },
2174 { 0, '\0' }
2175 };
2176
2177 char *
2178 oper_privs_as_string(const unsigned int port)
2179 {
2180 static char privs_out[16];
2181 char *privs_ptr = privs_out;
2182 unsigned int i = 0;
2183
2184 for (; flag_list[i].oprivs; ++i)
2185 {
2186 if (port & flag_list[i].oprivs)
2187 *privs_ptr++ = flag_list[i].c;
2188 else
2189 *privs_ptr++ = ToLowerTab[flag_list[i].c];
2190 }
2191
2192 *privs_ptr = '\0';
2193
2194 return privs_out;
2195 }
2196
2197 /*
2198 * Input: A client to find the active oper{} name for.
2199 * Output: The nick!user@host{oper} of the oper.
2200 * "oper" is server name for remote opers
2201 * Side effects: None.
2202 */
2203 const char *
2204 get_oper_name(const struct Client *client_p)
2205 {
2206 dlink_node *cnode = NULL;
2207 /* +5 for !,@,{,} and null */
2208 static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
2209
2210 if (MyConnect(client_p))
2211 {
2212 if ((cnode = client_p->localClient->confs.head))
2213 {
2214 struct ConfItem *conf = cnode->data;
2215 const struct AccessItem *aconf = map_to_conf(conf);
2216
2217 if (IsConfOperator(aconf))
2218 {
2219 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2220 client_p->username, client_p->host, conf->name);
2221 return buffer;
2222 }
2223 }
2224
2225 /* Probably should assert here for now. If there is an oper out there
2226 * with no oper{} conf attached, it would be good for us to know...
2227 */
2228 assert(0); /* Oper without oper conf! */
2229 }
2230
2231 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
2232 client_p->username, client_p->host, client_p->servptr->name);
2233 return buffer;
2234 }
2235
2236 /* read_conf_files()
2237 *
2238 * inputs - cold start YES or NO
2239 * output - none
2240 * side effects - read all conf files needed, ircd.conf kline.conf etc.
2241 */
2242 void
2243 read_conf_files(int cold)
2244 {
2245 const char *filename;
2246 char chanmodes[32];
2247 char chanlimit[32];
2248
2249 conf_parser_ctx.boot = cold;
2250 filename = get_conf_name(CONF_TYPE);
2251
2252 /* We need to know the initial filename for the yyerror() to report
2253 FIXME: The full path is in conffilenamebuf first time since we
2254 dont know anything else
2255
2256 - Gozem 2002-07-21
2257 */
2258 strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2259
2260 if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
2261 {
2262 if (cold)
2263 {
2264 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2265 filename, strerror(errno));
2266 exit(-1);
2267 }
2268 else
2269 {
2270 sendto_realops_flags(UMODE_ALL, L_ALL,
2271 "Unable to read configuration file '%s': %s",
2272 filename, strerror(errno));
2273 return;
2274 }
2275 }
2276
2277 if (!cold)
2278 clear_out_old_conf();
2279
2280 read_conf(conf_parser_ctx.conf_file);
2281 fclose(conf_parser_ctx.conf_file);
2282
2283 add_isupport("NETWORK", ServerInfo.network_name, -1);
2284 snprintf(chanmodes, sizeof(chanmodes), "b%s%s:%d",
2285 ConfigChannel.use_except ? "e" : "",
2286 ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2287 add_isupport("MAXLIST", chanmodes, -1);
2288 add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2289
2290 add_isupport("CHANTYPES", "#", -1);
2291
2292 snprintf(chanlimit, sizeof(chanlimit), "#:%d",
2293 ConfigChannel.max_chans_per_user);
2294 add_isupport("CHANLIMIT", chanlimit, -1);
2295 snprintf(chanmodes, sizeof(chanmodes), "%s%s%s",
2296 ConfigChannel.use_except ? "e" : "",
2297 ConfigChannel.use_invex ? "I" : "", "b,k,l,imnprstORS");
2298 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2299
2300 if (ConfigChannel.use_except)
2301 add_isupport("EXCEPTS", "e", -1);
2302 if (ConfigChannel.use_invex)
2303 add_isupport("INVEX", "I", -1);
2304 add_isupport("CHANMODES", chanmodes, -1);
2305
2306 /*
2307 * message_locale may have changed. rebuild isupport since it relies
2308 * on strlen(form_str(RPL_ISUPPORT))
2309 */
2310 rebuild_isupport_message_line();
2311
2312 #ifdef HAVE_LIBPCRE
2313 parse_conf_file(RKLINE_TYPE, cold);
2314 parse_conf_file(RXLINE_TYPE, cold);
2315 #endif
2316 parse_conf_file(KLINE_TYPE, cold);
2317 parse_conf_file(DLINE_TYPE, cold);
2318 parse_conf_file(XLINE_TYPE, cold);
2319 parse_conf_file(NRESV_TYPE, cold);
2320 parse_conf_file(CRESV_TYPE, cold);
2321 }
2322
2323 /* parse_conf_file()
2324 *
2325 * inputs - type of conf file to parse
2326 * output - none
2327 * side effects - conf file for givenconf type is opened and read then parsed
2328 */
2329 static void
2330 parse_conf_file(int type, int cold)
2331 {
2332 FILE *file = NULL;
2333 const char *filename = get_conf_name(type);
2334
2335 if ((file = fopen(filename, "r")) == NULL)
2336 {
2337 if (cold)
2338 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
2339 filename, strerror(errno));
2340 else
2341 sendto_realops_flags(UMODE_ALL, L_ALL,
2342 "Unable to read configuration file '%s': %s",
2343 filename, strerror(errno));
2344 }
2345 else
2346 {
2347 parse_csv_file(file, type);
2348 fclose(file);
2349 }
2350 }
2351
2352 /* clear_out_old_conf()
2353 *
2354 * inputs - none
2355 * output - none
2356 * side effects - Clear out the old configuration
2357 */
2358 static void
2359 clear_out_old_conf(void)
2360 {
2361 dlink_node *ptr = NULL, *next_ptr = NULL;
2362 struct ConfItem *conf;
2363 struct AccessItem *aconf;
2364 struct ClassItem *cltmp;
2365 struct MatchItem *match_item;
2366 dlink_list *free_items [] = {
2367 &server_items, &oconf_items,
2368 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2369 &nresv_items, &cluster_items, &service_items, NULL
2370 };
2371
2372 dlink_list ** iterator = free_items; /* C is dumb */
2373
2374 /* We only need to free anything allocated by yyparse() here.
2375 * Resetting structs, etc, is taken care of by set_default_conf().
2376 */
2377
2378 for (; *iterator != NULL; iterator++)
2379 {
2380 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2381 {
2382 conf = ptr->data;
2383 /* XXX This is less than pretty */
2384 if (conf->type == SERVER_TYPE)
2385 {
2386 aconf = map_to_conf(conf);
2387
2388 if (aconf->clients != 0)
2389 {
2390 SetConfIllegal(aconf);
2391 dlinkDelete(&conf->node, &server_items);
2392 }
2393 else
2394 {
2395 delete_conf_item(conf);
2396 }
2397 }
2398 else if (conf->type == OPER_TYPE)
2399 {
2400 aconf = map_to_conf(conf);
2401
2402 if (aconf->clients != 0)
2403 {
2404 SetConfIllegal(aconf);
2405 dlinkDelete(&conf->node, &oconf_items);
2406 }
2407 else
2408 {
2409 delete_conf_item(conf);
2410 }
2411 }
2412 else if (conf->type == XLINE_TYPE ||
2413 conf->type == RXLINE_TYPE ||
2414 conf->type == RKLINE_TYPE)
2415 {
2416 /* temporary (r)xlines are also on
2417 * the (r)xconf items list */
2418 if (conf->flags & CONF_FLAGS_TEMPORARY)
2419 continue;
2420
2421 delete_conf_item(conf);
2422 }
2423 else
2424 {
2425 delete_conf_item(conf);
2426 }
2427 }
2428 }
2429
2430 /*
2431 * don't delete the class table, rather mark all entries
2432 * for deletion. The table is cleaned up by check_class. - avalon
2433 */
2434 DLINK_FOREACH(ptr, class_items.head)
2435 {
2436 cltmp = map_to_conf(ptr->data);
2437
2438 if (ptr != class_items.tail) /* never mark the "default" class */
2439 cltmp->active = 0;
2440 }
2441
2442 clear_out_address_conf();
2443
2444 /* clean out module paths */
2445 mod_clear_paths();
2446
2447 /* clean out ServerInfo */
2448 MyFree(ServerInfo.description);
2449 ServerInfo.description = NULL;
2450 MyFree(ServerInfo.network_name);
2451 ServerInfo.network_name = NULL;
2452 MyFree(ServerInfo.network_desc);
2453 ServerInfo.network_desc = NULL;
2454 MyFree(ConfigFileEntry.egdpool_path);
2455 ConfigFileEntry.egdpool_path = NULL;
2456 #ifdef HAVE_LIBCRYPTO
2457 if (ServerInfo.rsa_private_key != NULL)
2458 {
2459 RSA_free(ServerInfo.rsa_private_key);
2460 ServerInfo.rsa_private_key = NULL;
2461 }
2462
2463 MyFree(ServerInfo.rsa_private_key_file);
2464 ServerInfo.rsa_private_key_file = NULL;
2465
2466 if (ServerInfo.server_ctx)
2467 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
2468 SSL_OP_NO_SSLv3|
2469 SSL_OP_NO_TLSv1);
2470 if (ServerInfo.client_ctx)
2471 SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
2472 SSL_OP_NO_SSLv3|
2473 SSL_OP_NO_TLSv1);
2474 #endif
2475
2476 /* clean out old resvs from the conf */
2477 clear_conf_resv();
2478
2479 /* clean out AdminInfo */
2480 MyFree(AdminInfo.name);
2481 AdminInfo.name = NULL;
2482 MyFree(AdminInfo.email);
2483 AdminInfo.email = NULL;
2484 MyFree(AdminInfo.description);
2485 AdminInfo.description = NULL;
2486
2487 /* operator{} and class{} blocks are freed above */
2488 /* clean out listeners */
2489 close_listeners();
2490
2491 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2492 * exempt{} and gecos{} blocks are freed above too
2493 */
2494
2495 /* clean out general */
2496 MyFree(ConfigFileEntry.service_name);
2497 ConfigFileEntry.service_name = NULL;
2498
2499 delete_isupport("INVEX");
2500 delete_isupport("EXCEPTS");
2501 }
2502
2503 /* flush_deleted_I_P()
2504 *
2505 * inputs - none
2506 * output - none
2507 * side effects - This function removes I/P conf items
2508 */
2509 static void
2510 flush_deleted_I_P(void)
2511 {
2512 dlink_node *ptr;
2513 dlink_node *next_ptr;
2514 struct ConfItem *conf;
2515 struct AccessItem *aconf;
2516 dlink_list * free_items [] = {
2517 &server_items, &oconf_items, NULL
2518 };
2519 dlink_list ** iterator = free_items; /* C is dumb */
2520
2521 /* flush out deleted I and P lines
2522 * although still in use.
2523 */
2524 for (; *iterator != NULL; iterator++)
2525 {
2526 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2527 {
2528 conf = ptr->data;
2529 aconf = (struct AccessItem *)map_to_conf(conf);
2530
2531 if (IsConfIllegal(aconf))
2532 {
2533 dlinkDelete(ptr, *iterator);
2534
2535 if (aconf->clients == 0)
2536 delete_conf_item(conf);
2537 }
2538 }
2539 }
2540 }
2541
2542 /* get_conf_name()
2543 *
2544 * inputs - type of conf file to return name of file for
2545 * output - pointer to filename for type of conf
2546 * side effects - none
2547 */
2548 const char *
2549 get_conf_name(ConfType type)
2550 {
2551 switch (type)
2552 {
2553 case CONF_TYPE:
2554 return ConfigFileEntry.configfile;
2555 break;
2556 case KLINE_TYPE:
2557 return ConfigFileEntry.klinefile;
2558 break;
2559 case RKLINE_TYPE:
2560 return ConfigFileEntry.rklinefile;
2561 break;
2562 case DLINE_TYPE:
2563 return ConfigFileEntry.dlinefile;
2564 break;
2565 case XLINE_TYPE:
2566 return ConfigFileEntry.xlinefile;
2567 break;
2568 case RXLINE_TYPE:
2569 return ConfigFileEntry.rxlinefile;
2570 break;
2571 case CRESV_TYPE:
2572 return ConfigFileEntry.cresvfile;
2573 break;
2574 case NRESV_TYPE:
2575 return ConfigFileEntry.nresvfile;
2576 break;
2577 case GLINE_TYPE:
2578 return ConfigFileEntry.glinefile;
2579 break;
2580
2581 default:
2582 return NULL; /* This should NEVER HAPPEN since we call this function
2583 only with the above values, this will cause us to core
2584 at some point if this happens so we know where it was */
2585 }
2586 }
2587
2588 #define BAD_PING (-1)
2589
2590 /* get_conf_ping()
2591 *
2592 * inputs - pointer to struct AccessItem
2593 * - pointer to a variable that receives ping warning time
2594 * output - ping frequency
2595 * side effects - NONE
2596 */
2597 static int
2598 get_conf_ping(struct ConfItem *conf, int *pingwarn)
2599 {
2600 struct ClassItem *aclass;
2601 struct AccessItem *aconf;
2602
2603 if (conf != NULL)
2604 {
2605 aconf = (struct AccessItem *)map_to_conf(conf);
2606 if (aconf->class_ptr != NULL)
2607 {
2608 aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2609 *pingwarn = aclass->ping_warning;
2610 return aclass->ping_freq;
2611 }
2612 }
2613
2614 return BAD_PING;
2615 }
2616
2617 /* get_client_class()
2618 *
2619 * inputs - pointer to client struct
2620 * output - pointer to name of class
2621 * side effects - NONE
2622 */
2623 const char *
2624 get_client_class(struct Client *target_p)
2625 {
2626 dlink_node *cnode = NULL;
2627 struct AccessItem *aconf = NULL;
2628
2629 assert(!IsMe(target_p));
2630
2631 if ((cnode = target_p->localClient->confs.head))
2632 {
2633 struct ConfItem *conf = cnode->data;
2634
2635 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2636 (conf->type == OPER_TYPE));
2637
2638 aconf = map_to_conf(conf);
2639 if (aconf->class_ptr != NULL)
2640 return aconf->class_ptr->name;
2641 }
2642
2643 return "default";
2644 }
2645
2646 /* get_client_ping()
2647 *
2648 * inputs - pointer to client struct
2649 * - pointer to a variable that receives ping warning time
2650 * output - ping frequency
2651 * side effects - NONE
2652 */
2653 int
2654 get_client_ping(struct Client *target_p, int *pingwarn)
2655 {
2656 int ping = 0;
2657 dlink_node *cnode = NULL;
2658
2659 if ((cnode = target_p->localClient->confs.head))
2660 {
2661 struct ConfItem *conf = cnode->data;
2662
2663 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2664 (conf->type == OPER_TYPE));
2665
2666 ping = get_conf_ping(conf, pingwarn);
2667 if (ping > 0)
2668 return ping;
2669 }
2670
2671 *pingwarn = 0;
2672 return DEFAULT_PINGFREQUENCY;
2673 }
2674
2675 /* find_class()
2676 *
2677 * inputs - string name of class
2678 * output - corresponding Class pointer
2679 * side effects - NONE
2680 */
2681 struct ConfItem *
2682 find_class(const char *classname)
2683 {
2684 struct ConfItem *conf;
2685
2686 if ((conf = find_exact_name_conf(CLASS_TYPE, NULL, classname, NULL, NULL)) != NULL)
2687 return conf;
2688
2689 return class_default;
2690 }
2691
2692 /* check_class()
2693 *
2694 * inputs - NONE
2695 * output - NONE
2696 * side effects -
2697 */
2698 void
2699 check_class(void)
2700 {
2701 dlink_node *ptr = NULL, *next_ptr = NULL;
2702
2703 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2704 {
2705 struct ClassItem *aclass = map_to_conf(ptr->data);
2706
2707 if (!aclass->active && !aclass->curr_user_count)
2708 {
2709 destroy_cidr_class(aclass);
2710 delete_conf_item(ptr->data);
2711 }
2712 }
2713 }
2714
2715 /* init_class()
2716 *
2717 * inputs - NONE
2718 * output - NONE
2719 * side effects -
2720 */
2721 void
2722 init_class(void)
2723 {
2724 struct ClassItem *aclass;
2725
2726 class_default = make_conf_item(CLASS_TYPE);
2727
2728 aclass = map_to_conf(class_default);
2729 aclass->active = 1;
2730 DupString(class_default->name, "default");
2731 aclass->con_freq = DEFAULT_CONNECTFREQUENCY;
2732 aclass->ping_freq = DEFAULT_PINGFREQUENCY;
2733 aclass->max_total = MAXIMUM_LINKS_DEFAULT;
2734 aclass->max_sendq = DEFAULT_SENDQ;
2735
2736 client_check_cb = register_callback("check_client", check_client);
2737 }
2738
2739 /* get_sendq()
2740 *
2741 * inputs - pointer to client
2742 * output - sendq for this client as found from its class
2743 * side effects - NONE
2744 */
2745 unsigned int
2746 get_sendq(struct Client *client_p)
2747 {
2748 unsigned int sendq = DEFAULT_SENDQ;
2749 dlink_node *cnode;
2750 struct ConfItem *class_conf;
2751 struct ClassItem *aclass;
2752 struct AccessItem *aconf;
2753
2754 assert(!IsMe(client_p));
2755
2756 if ((cnode = client_p->localClient->confs.head))
2757 {
2758 struct ConfItem *conf = cnode->data;
2759
2760 assert((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2761 (conf->type == OPER_TYPE));
2762
2763 aconf = map_to_conf(conf);
2764
2765 if ((class_conf = aconf->class_ptr) == NULL)
2766 return DEFAULT_SENDQ; /* TBV: shouldn't be possible at all */
2767
2768 aclass = map_to_conf(class_conf);
2769 sendq = aclass->max_sendq;
2770 return sendq;
2771 }
2772
2773 /* XXX return a default?
2774 * if here, then there wasn't an attached conf with a sendq
2775 * that is very bad -Dianora
2776 */
2777 return DEFAULT_SENDQ;
2778 }
2779
2780 /* conf_add_class_to_conf()
2781 *
2782 * inputs - pointer to config item
2783 * output - NONE
2784 * side effects - Add a class pointer to a conf
2785 */
2786 void
2787 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2788 {
2789 struct AccessItem *aconf = map_to_conf(conf);
2790 struct ClassItem *class = NULL;
2791
2792 if (class_name == NULL)
2793 {
2794 aconf->class_ptr = class_default;
2795
2796 if (conf->type == CLIENT_TYPE)
2797 sendto_realops_flags(UMODE_ALL, L_ALL,
2798 "Warning *** Defaulting to default class for %s@%s",
2799 aconf->user, aconf->host);
2800 else
2801 sendto_realops_flags(UMODE_ALL, L_ALL,
2802 "Warning *** Defaulting to default class for %s",
2803 conf->name);
2804 }
2805 else
2806 aconf->class_ptr = find_class(class_name);
2807
2808 if (aconf->class_ptr)
2809 class = map_to_conf(aconf->class_ptr);
2810
2811 if (aconf->class_ptr == NULL || !class->active)
2812 {
2813 if (conf->type == CLIENT_TYPE)
2814 sendto_realops_flags(UMODE_ALL, L_ALL,
2815 "Warning *** Defaulting to default class for %s@%s",
2816 aconf->user, aconf->host);
2817 else
2818 sendto_realops_flags(UMODE_ALL, L_ALL,
2819 "Warning *** Defaulting to default class for %s",
2820 conf->name);
2821 aconf->class_ptr = class_default;
2822 }
2823 }
2824
2825 /* conf_add_server()
2826 *
2827 * inputs - pointer to config item
2828 * - pointer to link count already on this conf
2829 * output - NONE
2830 * side effects - Add a connect block
2831 */
2832 int
2833 conf_add_server(struct ConfItem *conf, const char *class_name)
2834 {
2835 struct AccessItem *aconf = map_to_conf(conf);
2836
2837 conf_add_class_to_conf(conf, class_name);
2838
2839 if (!aconf->host || !conf->name)
2840 {
2841 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2842 ilog(LOG_TYPE_IRCD, "Bad connect block");
2843 return -1;
2844 }
2845
2846 if (EmptyString(aconf->passwd))
2847 {
2848 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2849 conf->name);
2850 ilog(LOG_TYPE_IRCD, "Bad connect block, host %s", conf->name);
2851 return -1;
2852 }
2853
2854 lookup_confhost(conf);
2855
2856 return 0;
2857 }
2858
2859 /* yyerror()
2860 *
2861 * inputs - message from parser
2862 * output - NONE
2863 * side effects - message to opers and log file entry is made
2864 */
2865 void
2866 yyerror(const char *msg)
2867 {
2868 char newlinebuf[IRCD_BUFSIZE];
2869
2870 if (conf_parser_ctx.pass != 1)
2871 return;
2872
2873 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2874 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2875 conffilebuf, lineno + 1, msg, newlinebuf);
2876 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
2877 conffilebuf, lineno + 1, msg, newlinebuf);
2878 }
2879
2880 /*
2881 * valid_tkline()
2882 *
2883 * inputs - pointer to ascii string to check
2884 * - whether the specified time is in seconds or minutes
2885 * output - -1 not enough parameters
2886 * - 0 if not an integer number, else the number
2887 * side effects - none
2888 * Originally written by Dianora (Diane, db@db.net)
2889 */
2890 time_t
2891 valid_tkline(const char *p, int minutes)
2892 {
2893 time_t result = 0;
2894
2895 for (; *p; ++p)
2896 {
2897 if (!IsDigit(*p))
2898 return 0;
2899
2900 result *= 10;
2901 result += ((*p) & 0xF);
2902 }
2903
2904 /*
2905 * In the degenerate case where oper does a /quote kline 0 user@host :reason
2906 * i.e. they specifically use 0, I am going to return 1 instead
2907 * as a return value of non-zero is used to flag it as a temporary kline
2908 */
2909 if (result == 0)
2910 result = 1;
2911
2912 /*
2913 * If the incoming time is in seconds convert it to minutes for the purpose
2914 * of this calculation
2915 */
2916 if (!minutes)
2917 result = result / (time_t)60;
2918
2919 if (result > MAX_TDKLINE_TIME)
2920 result = MAX_TDKLINE_TIME;
2921
2922 result = result * (time_t)60; /* turn it into seconds */
2923
2924 return result;
2925 }
2926
2927 /* valid_wild_card()
2928 *
2929 * input - pointer to client
2930 * - int flag, 0 for no warning oper 1 for warning oper
2931 * - count of following varargs to check
2932 * output - 0 if not valid, 1 if valid
2933 * side effects - NOTICE is given to source_p if warn is 1
2934 */
2935 int
2936 valid_wild_card(struct Client *source_p, int warn, int count, ...)
2937 {
2938 char *p;
2939 char tmpch;
2940 int nonwild = 0;
2941 va_list args;
2942
2943 /*
2944 * Now we must check the user and host to make sure there
2945 * are at least NONWILDCHARS non-wildcard characters in
2946 * them, otherwise assume they are attempting to kline
2947 * *@* or some variant of that. This code will also catch
2948 * people attempting to kline *@*.tld, as long as NONWILDCHARS
2949 * is greater than 3. In that case, there are only 3 non-wild
2950 * characters (tld), so if NONWILDCHARS is 4, the kline will
2951 * be disallowed.
2952 * -wnder
2953 */
2954
2955 va_start(args, count);
2956
2957 while (count--)
2958 {
2959 p = va_arg(args, char *);
2960 if (p == NULL)
2961 continue;
2962
2963 while ((tmpch = *p++))
2964 {
2965 if (!IsKWildChar(tmpch))
2966 {
2967 /*
2968 * If we find enough non-wild characters, we can
2969 * break - no point in searching further.
2970 */
2971 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
2972 return 1;
2973 }
2974 }
2975 }
2976
2977 if (warn)
2978 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
2979 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
2980 return 0;
2981 }
2982
2983 /* XXX should this go into a separate file ? -Dianora */
2984 /* parse_aline
2985 *
2986 * input - pointer to cmd name being used
2987 * - pointer to client using cmd
2988 * - parc parameter count
2989 * - parv[] list of parameters to parse
2990 * - parse_flags bit map of things to test
2991 * - pointer to user or string to parse into
2992 * - pointer to host or NULL to parse into if non NULL
2993 * - pointer to optional tkline time or NULL
2994 * - pointer to target_server to parse into if non NULL
2995 * - pointer to reason to parse into
2996 *
2997 * output - 1 if valid, -1 if not valid
2998 * side effects - A generalised k/d/x etc. line parser,
2999 * "ALINE [time] user@host|string [ON] target :reason"
3000 * will parse returning a parsed user, host if
3001 * h_p pointer is non NULL, string otherwise.
3002 * if tkline_time pointer is non NULL a tk line will be set
3003 * to non zero if found.
3004 * if tkline_time pointer is NULL and tk line is found,
3005 * error is reported.
3006 * if target_server is NULL and an "ON" is found error
3007 * is reported.
3008 * if reason pointer is NULL ignore pointer,
3009 * this allows use of parse_a_line in unkline etc.
3010 *
3011 * - Dianora
3012 */
3013 int
3014 parse_aline(const char *cmd, struct Client *source_p,
3015 int parc, char **parv,
3016 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3017 char **target_server, char **reason)
3018 {
3019 int found_tkline_time=0;
3020 static char def_reason[] = "No Reason";
3021 static char user[USERLEN*4+1];
3022 static char host[HOSTLEN*4+1];
3023
3024 parv++;
3025 parc--;
3026
3027 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3028
3029 if (found_tkline_time != 0)
3030 {
3031 parv++;
3032 parc--;
3033
3034 if (tkline_time != NULL)
3035 *tkline_time = found_tkline_time;
3036 else
3037 {
3038 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3039 me.name, source_p->name, cmd);
3040 return -1;
3041 }
3042 }
3043
3044 if (parc == 0)
3045 {
3046 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3047 me.name, source_p->name, cmd);
3048 return -1;
3049 }
3050
3051 if (h_p == NULL)
3052 *up_p = *parv;
3053 else
3054 {
3055 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3056 return -1;
3057
3058 *up_p = user;
3059 *h_p = host;
3060 }
3061
3062 parc--;
3063 parv++;
3064
3065 if (parc != 0)
3066 {
3067 if (irccmp(*parv, "ON") == 0)
3068 {
3069 parc--;
3070 parv++;
3071
3072 if (target_server == NULL)
3073 {
3074 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3075 me.name, source_p->name, cmd);
3076 return -1;
3077 }
3078
3079 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
3080 {
3081 sendto_one(source_p, form_str(ERR_NOPRIVS),
3082 me.name, source_p->name, "remoteban");
3083 return -1;
3084 }
3085
3086 if (parc == 0 || EmptyString(*parv))
3087 {
3088 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3089 me.name, source_p->name, cmd);
3090 return -1;
3091 }
3092
3093 *target_server = *parv;
3094 parc--;
3095 parv++;
3096 }
3097 else
3098 {
3099 /* Make sure target_server *is* NULL if no ON server found
3100 * caller probably NULL'd it first, but no harm to do it again -db
3101 */
3102 if (target_server != NULL)
3103 *target_server = NULL;
3104 }
3105 }
3106
3107 if (h_p != NULL)
3108 {
3109 if (strchr(user, '!') != NULL)
3110 {
3111 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3112 me.name, source_p->name);
3113 return -1;
3114 }
3115
3116 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
3117 return -1;
3118 }
3119 else
3120 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
3121 return -1;
3122
3123 if (reason != NULL)
3124 {
3125 if (parc != 0 && !EmptyString(*parv))
3126 {
3127 *reason = *parv;
3128 if (!valid_comment(source_p, *reason, 1))
3129 return -1;
3130 }
3131 else
3132 *reason = def_reason;
3133 }
3134
3135 return 1;
3136 }
3137
3138 /* find_user_host()
3139 *
3140 * inputs - pointer to client placing kline
3141 * - pointer to user_host_or_nick
3142 * - pointer to user buffer
3143 * - pointer to host buffer
3144 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3145 * side effects -
3146 */
3147 static int
3148 find_user_host(struct Client *source_p, char *user_host_or_nick,
3149 char *luser, char *lhost, unsigned int flags)
3150 {
3151 struct Client *target_p = NULL;
3152 char *hostp = NULL;
3153
3154 if (lhost == NULL)
3155 {
3156 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3157 return 1;
3158 }
3159
3160 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3161 {
3162 /* Explicit user@host mask given */
3163
3164 if (hostp != NULL) /* I'm a little user@host */
3165 {
3166 *(hostp++) = '\0'; /* short and squat */
3167 if (*user_host_or_nick)
3168 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3169 else
3170 strcpy(luser, "*");
3171 if (*hostp)
3172 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3173 else
3174 strcpy(lhost, "*");
3175 }
3176 else
3177 {
3178 luser[0] = '*'; /* no @ found, assume its *@somehost */
3179 luser[1] = '\0';
3180 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3181 }
3182
3183 return 1;
3184 }
3185 else if (!(flags & NOUSERLOOKUP))
3186 {
3187 /* Try to find user@host mask from nick */
3188 /* Okay to use source_p as the first param, because source_p == client_p */
3189 if ((target_p =
3190 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3191 return 0;
3192
3193 if (IsExemptKline(target_p))
3194 {
3195 if (!IsServer(source_p))
3196 sendto_one(source_p,
3197 ":%s NOTICE %s :%s is E-lined",
3198 me.name, source_p->name, target_p->name);
3199 return 0;
3200 }
3201
3202 /*
3203 * turn the "user" bit into "*user", blow away '~'
3204 * if found in original user name (non-idented)
3205 */
3206 strlcpy(luser, target_p->username, USERLEN*4 + 1);
3207
3208 if (target_p->username[0] == '~')
3209 luser[0] = '*';
3210
3211 if (target_p->sockhost[0] == '\0' ||
3212 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3213 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3214 else
3215 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3216 return 1;
3217 }
3218
3219 return 0;
3220 }
3221
3222 /* valid_comment()
3223 *
3224 * inputs - pointer to client
3225 * - pointer to comment
3226 * output - 0 if no valid comment,
3227 * - 1 if valid
3228 * side effects - truncates reason where necessary
3229 */
3230 int
3231 valid_comment(struct Client *source_p, char *comment, int warn)
3232 {
3233 if (strchr(comment, '"'))
3234 {
3235 if (warn)
3236 sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3237 me.name, source_p->name);
3238 return 0;
3239 }
3240
3241 if (strlen(comment) > REASONLEN)
3242 comment[REASONLEN-1] = '\0';
3243
3244 return 1;
3245 }
3246
3247 /* match_conf_password()
3248 *
3249 * inputs - pointer to given password
3250 * - pointer to Conf
3251 * output - 1 or 0 if match
3252 * side effects - none
3253 */
3254 int
3255 match_conf_password(const char *password, const struct AccessItem *aconf)
3256 {
3257 const char *encr = NULL;
3258
3259 if (EmptyString(password) || EmptyString(aconf->passwd))
3260 return 0;
3261
3262 if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3263 encr = crypt(password, aconf->passwd);
3264 else
3265 encr = password;
3266
3267 return !strcmp(encr, aconf->passwd);
3268 }
3269
3270 /*
3271 * cluster_a_line
3272 *
3273 * inputs - client sending the cluster
3274 * - command name "KLINE" "XLINE" etc.
3275 * - capab -- CAP_KLN etc. from s_serv.h
3276 * - cluster type -- CLUSTER_KLINE etc. from conf.h
3277 * - pattern and args to send along
3278 * output - none
3279 * side effects - Take source_p send the pattern with args given
3280 * along to all servers that match capab and cluster type
3281 */
3282 void
3283 cluster_a_line(struct Client *source_p, const char *command,
3284 int capab, int cluster_type, const char *pattern, ...)
3285 {
3286 va_list args;
3287 char buffer[IRCD_BUFSIZE];
3288 const dlink_node *ptr = NULL;
3289
3290 va_start(args, pattern);
3291 vsnprintf(buffer, sizeof(buffer), pattern, args);
3292 va_end(args);
3293
3294 DLINK_FOREACH(ptr, cluster_items.head)
3295 {
3296 const struct ConfItem *conf = ptr->data;
3297
3298 if (conf->flags & cluster_type)
3299 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3300 "%s %s %s", command, conf->name, buffer);
3301 }
3302 }
3303
3304 /*
3305 * split_nuh
3306 *
3307 * inputs - pointer to original mask (modified in place)
3308 * - pointer to pointer where nick should go
3309 * - pointer to pointer where user should go
3310 * - pointer to pointer where host should go
3311 * output - NONE
3312 * side effects - mask is modified in place
3313 * If nick pointer is NULL, ignore writing to it
3314 * this allows us to use this function elsewhere.
3315 *
3316 * mask nick user host
3317 * ---------------------- ------- ------- ------
3318 * Dianora!db@db.net Dianora db db.net
3319 * Dianora Dianora * *
3320 * db.net * * db.net
3321 * OR if nick pointer is NULL
3322 * Dianora - * Dianora
3323 * Dianora! Dianora * *
3324 * Dianora!@ Dianora * *
3325 * Dianora!db Dianora db *
3326 * Dianora!@db.net Dianora * db.net
3327 * db@db.net * db db.net
3328 * !@ * * *
3329 * @ * * *
3330 * ! * * *
3331 */
3332 void
3333 split_nuh(struct split_nuh_item *const iptr)
3334 {
3335 char *p = NULL, *q = NULL;
3336
3337 if (iptr->nickptr)
3338 strlcpy(iptr->nickptr, "*", iptr->nicksize);
3339 if (iptr->userptr)
3340 strlcpy(iptr->userptr, "*", iptr->usersize);
3341 if (iptr->hostptr)
3342 strlcpy(iptr->hostptr, "*", iptr->hostsize);
3343
3344 if ((p = strchr(iptr->nuhmask, '!')))
3345 {
3346 *p = '\0';
3347
3348 if (iptr->nickptr && *iptr->nuhmask != '\0')
3349 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3350
3351 if ((q = strchr(++p, '@'))) {
3352 *q++ = '\0';
3353
3354 if (*p != '\0')
3355 strlcpy(iptr->userptr, p, iptr->usersize);
3356
3357 if (*q != '\0')
3358 strlcpy(iptr->hostptr, q, iptr->hostsize);
3359 }
3360 else
3361 {
3362 if (*p != '\0')
3363 strlcpy(iptr->userptr, p, iptr->usersize);
3364 }
3365 }
3366 else
3367 {
3368 /* No ! found so lets look for a user@host */
3369 if ((p = strchr(iptr->nuhmask, '@')))
3370 {
3371 /* if found a @ */
3372 *p++ = '\0';
3373
3374 if (*iptr->nuhmask != '\0')
3375 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3376
3377 if (*p != '\0')
3378 strlcpy(iptr->hostptr, p, iptr->hostsize);
3379 }
3380 else
3381 {
3382 /* no @ found */
3383 if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3384 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3385 else
3386 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3387 }
3388 }
3389 }
3390
3391 /*
3392 * flags_to_ascii
3393 *
3394 * inputs - flags is a bitmask
3395 * - pointer to table of ascii letters corresponding
3396 * to each bit
3397 * - flag 1 for convert ToLower if bit missing
3398 * 0 if ignore.
3399 * output - none
3400 * side effects - string pointed to by p has bitmap chars written to it
3401 */
3402 static void
3403 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3404 int lowerit)
3405 {
3406 unsigned int mask = 1;
3407 int i = 0;
3408
3409 for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3410 {
3411 if (flags & mask)
3412 *p++ = bit_table[i];
3413 else if (lowerit)
3414 *p++ = ToLower(bit_table[i]);
3415 }
3416 *p = '\0';
3417 }
3418
3419 /*
3420 * cidr_limit_reached
3421 *
3422 * inputs - int flag allowing over_rule of limits
3423 * - pointer to the ip to be added
3424 * - pointer to the class
3425 * output - non zero if limit reached
3426 * 0 if limit not reached
3427 * side effects -
3428 */
3429 static int
3430 cidr_limit_reached(int over_rule,
3431 struct irc_ssaddr *ip, struct ClassItem *aclass)
3432 {
3433 dlink_node *ptr = NULL;
3434 struct CidrItem *cidr;
3435
3436 if (aclass->number_per_cidr <= 0)
3437 return 0;
3438
3439 if (ip->ss.ss_family == AF_INET)
3440 {
3441 if (aclass->cidr_bitlen_ipv4 <= 0)
3442 return 0;
3443
3444 DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3445 {
3446 cidr = ptr->data;
3447 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3448 {
3449 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3450 return -1;
3451 cidr->number_on_this_cidr++;
3452 return 0;
3453 }
3454 }
3455 cidr = MyMalloc(sizeof(struct CidrItem));
3456 cidr->number_on_this_cidr = 1;
3457 cidr->mask = *ip;
3458 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv4);
3459 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3460 }
3461 #ifdef IPV6
3462 else if (aclass->cidr_bitlen_ipv6 > 0)
3463 {
3464 DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3465 {
3466 cidr = ptr->data;
3467 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3468 {
3469 if (!over_rule && (cidr->number_on_this_cidr >= aclass->number_per_cidr))
3470 return -1;
3471 cidr->number_on_this_cidr++;
3472 return 0;
3473 }
3474 }
3475 cidr = MyMalloc(sizeof(struct CidrItem));
3476 cidr->number_on_this_cidr = 1;
3477 cidr->mask = *ip;
3478 mask_addr(&cidr->mask, aclass->cidr_bitlen_ipv6);
3479 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3480 }
3481 #endif
3482 return 0;
3483 }
3484
3485 /*
3486 * remove_from_cidr_check
3487 *
3488 * inputs - pointer to the ip to be removed
3489 * - pointer to the class
3490 * output - NONE
3491 * side effects -
3492 */
3493 static void
3494 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3495 {
3496 dlink_node *ptr = NULL;
3497 dlink_node *next_ptr = NULL;
3498 struct CidrItem *cidr;
3499
3500 if (aclass->number_per_cidr == 0)
3501 return;
3502
3503 if (ip->ss.ss_family == AF_INET)
3504 {
3505 if (aclass->cidr_bitlen_ipv4 <= 0)
3506 return;
3507
3508 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3509 {
3510 cidr = ptr->data;
3511 if (match_ipv4(ip, &cidr->mask, aclass->cidr_bitlen_ipv4))
3512 {
3513 cidr->number_on_this_cidr--;
3514 if (cidr->number_on_this_cidr == 0)
3515 {
3516 dlinkDelete(ptr, &aclass->list_ipv4);
3517 MyFree(cidr);
3518 return;
3519 }
3520 }
3521 }
3522 }
3523 #ifdef IPV6
3524 else if (aclass->cidr_bitlen_ipv6 > 0)
3525 {
3526 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3527 {
3528 cidr = ptr->data;
3529 if (match_ipv6(ip, &cidr->mask, aclass->cidr_bitlen_ipv6))
3530 {
3531 cidr->number_on_this_cidr--;
3532 if (cidr->number_on_this_cidr == 0)
3533 {
3534 dlinkDelete(ptr, &aclass->list_ipv6);
3535 MyFree(cidr);
3536 return;
3537 }
3538 }
3539 }
3540 }
3541 #endif
3542 }
3543
3544 static void
3545 rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3546 dlink_list *old_list, dlink_list *new_list, int changed)
3547 {
3548 dlink_node *ptr;
3549 struct Client *client_p;
3550 struct ConfItem *conf;
3551 struct AccessItem *aconf;
3552
3553 if (!changed)
3554 {
3555 *new_list = *old_list;
3556 old_list->head = old_list->tail = NULL;
3557 old_list->length = 0;
3558 return;
3559 }
3560
3561 DLINK_FOREACH(ptr, local_client_list.head)
3562 {
3563 client_p = ptr->data;
3564 if (client_p->localClient->aftype != aftype)
3565 continue;
3566 if (dlink_list_length(&client_p->localClient->confs) == 0)
3567 continue;
3568
3569 conf = client_p->localClient->confs.tail->data;
3570 if (conf->type == CLIENT_TYPE)
3571 {
3572 aconf = map_to_conf(conf);
3573 if (aconf->class_ptr == oldcl)
3574 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3575 }
3576 }
3577 }
3578
3579 /*
3580 * rebuild_cidr_class
3581 *
3582 * inputs - pointer to old conf
3583 * - pointer to new_class
3584 * output - none
3585 * side effects - rebuilds the class link list of cidr blocks
3586 */
3587 void
3588 rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3589 {
3590 struct ClassItem *old_class = map_to_conf(conf);
3591
3592 if (old_class->number_per_cidr > 0 && new_class->number_per_cidr > 0)
3593 {
3594 if (old_class->cidr_bitlen_ipv4 > 0 && new_class->cidr_bitlen_ipv4 > 0)
3595 rebuild_cidr_list(AF_INET, conf, new_class,
3596 &old_class->list_ipv4, &new_class->list_ipv4,
3597 old_class->cidr_bitlen_ipv4 != new_class->cidr_bitlen_ipv4);
3598
3599 #ifdef IPV6
3600 if (old_class->cidr_bitlen_ipv6 > 0 && new_class->cidr_bitlen_ipv6 > 0)
3601 rebuild_cidr_list(AF_INET6, conf, new_class,
3602 &old_class->list_ipv6, &new_class->list_ipv6,
3603 old_class->cidr_bitlen_ipv6 != new_class->cidr_bitlen_ipv6);
3604 #endif
3605 }
3606
3607 destroy_cidr_class(old_class);
3608 }
3609
3610 /*
3611 * destroy_cidr_list
3612 *
3613 * inputs - pointer to class dlink list of cidr blocks
3614 * output - none
3615 * side effects - completely destroys the class link list of cidr blocks
3616 */
3617 static void
3618 destroy_cidr_list(dlink_list *list)
3619 {
3620 dlink_node *ptr = NULL, *next_ptr = NULL;
3621
3622 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3623 {
3624 dlinkDelete(ptr, list);
3625 MyFree(ptr->data);
3626 }
3627 }
3628
3629 /*
3630 * destroy_cidr_class
3631 *
3632 * inputs - pointer to class
3633 * output - none
3634 * side effects - completely destroys the class link list of cidr blocks
3635 */
3636 static void
3637 destroy_cidr_class(struct ClassItem *aclass)
3638 {
3639 destroy_cidr_list(&aclass->list_ipv4);
3640 destroy_cidr_list(&aclass->list_ipv6);
3641 }

Properties

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