/[svn]/ircd-hybrid/branches/8.2.x/src/conf.c
ViewVC logotype

Contents of /ircd-hybrid/branches/8.2.x/src/conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1618 - (show annotations)
Tue Oct 30 21:04:38 2012 UTC (10 years, 7 months ago) by michael
Original Path: ircd-hybrid/trunk/src/conf.c
File MIME type: text/x-chdr
File size: 91772 byte(s)
- Made m_globops() and ms_globops() use sendto_realops_flags()
- Added message-type parameter to sendto_realops_flags() which can be one of
  SEND_NOTICE, SEND_GLOBAL, SEND_LOCOPS
- Forward-port -r1617

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