ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1518
Committed: Sun Sep 2 16:50:40 2012 UTC (11 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 92553 byte(s)
Log Message:
- Removed rkline.conf and rxline.conf leftovers. Regular expression based
  k- and x-lines can be set via ircd.conf only.

File Contents

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

Properties

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