ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1622
Committed: Thu Nov 1 13:16:37 2012 UTC (12 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 89516 byte(s)
Log Message:
- klines, dlines, xlines, glines and resv now make use of the new database;
  also, temporary *lines are now stored, so they're not lost after
  restarting the ircd. This also applies to G-lines.

File Contents

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

Properties

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