/[svn]/ircd-hybrid-8/src/conf.c
ViewVC logotype

Contents of /ircd-hybrid-8/src/conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1503 - (show annotations)
Tue Aug 14 09:05:58 2012 UTC (7 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 92015 byte(s)
- Removed all unused references to GPATH and glinefile. There's no glines.conf.

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