ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/conf.c
Revision: 1623
Committed: Thu Nov 1 13:24:43 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/conf.c
File size: 89466 byte(s)
Log Message:
- Removed temporary_xlines list

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

Properties

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