ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1592
Committed: Sat Oct 27 21:02:32 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 91440 byte(s)
Log Message:
- Second time's the charm? Moving svnroot/ircd-hybrid-8 to
  svnroot/ircd-hybrid/trunk

File Contents

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

Properties

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