ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_conf.c
Revision: 146
Committed: Sun Oct 16 15:45:25 2005 UTC (19 years, 10 months ago) by db
Content type: text/x-csrc
File size: 73176 byte(s)
Log Message:
- More conf cleanups, aconf->client count is no longer needed
  as an AccessItem can now be deleted immediately.
- Note bug in s_conf.c with flush_deleted_I_P, it was trying to
  free MatchItems using an AccessConf this bug is in 7.1.4 as well
  as 7.2 flush_deleted_I_P() is no longer needed at all in 7.3
  since AccessItems are removed immediately.
- Fixed a few cores in server establishment, notably ->serv
  has to be allocated sooner since there are no confs to attach.
  make_server() is probably called once too often now.


File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_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 "ircd_defs.h"
27 #include "s_conf.h"
28 #include "parse_aline.h"
29 #include "s_serv.h"
30 #include "resv.h"
31 #include "s_stats.h"
32 #include "channel.h"
33 #include "client.h"
34 #include "common.h"
35 #include "hash.h"
36 #include "ircd.h"
37 #include "listener.h"
38 #include "hostmask.h"
39 #include "modules.h"
40 #include "numeric.h"
41 #include "send.h"
42 #include "s_gline.h"
43 #include "userhost.h"
44 #include "s_user.h"
45 #include "channel_mode.h"
46
47 struct Callback *client_check_cb = NULL;
48 struct config_server_hide ConfigServerHide;
49
50 /* general conf items link list root, other than k lines etc. */
51 dlink_list server_items = { NULL, NULL, 0 };
52 dlink_list cluster_items = { NULL, NULL, 0 };
53 dlink_list hub_items = { NULL, NULL, 0 };
54 dlink_list leaf_items = { NULL, NULL, 0 };
55 dlink_list oconf_items = { NULL, NULL, 0 };
56 dlink_list uconf_items = { NULL, NULL, 0 };
57 dlink_list xconf_items = { NULL, NULL, 0 };
58 dlink_list rxconf_items = { NULL, NULL, 0 };
59 dlink_list rkconf_items = { NULL, NULL, 0 };
60 dlink_list nresv_items = { NULL, NULL, 0 };
61 dlink_list class_items = { NULL, NULL, 0 };
62 dlink_list gdeny_items = { NULL, NULL, 0 };
63
64 extern unsigned int lineno;
65 extern char linebuf[];
66 extern char conffilebuf[IRCD_BUFSIZE];
67 extern char yytext[];
68 extern int yyparse(); /* defined in y.tab.c */
69 unsigned int scount = 0; /* used by yyparse(), etc */
70 int ypass = 1; /* used by yyparse() */
71
72 /* internally defined functions */
73 static void lookup_confhost(struct ConfItem *);
74 static void set_default_conf(void);
75 static void validate_conf(void);
76 static void read_conf(FBFILE *);
77 static void clear_out_old_conf(void);
78 static void garbage_collect_ip_entries(void);
79 static int hash_ip(struct irc_ssaddr *);
80 static int verify_access(struct Client *, const char *, struct AccessItem **);
81 static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
82 static void parse_conf_file(int, int);
83 static int check_class_limits(struct Client *, int ,struct ClassItem *);
84 static int attach_class(struct Client *client_p, struct ClassItem *aclass);
85 static void free_aconf_items(struct ConfItem *, dlink_list *);
86 static void free_match_items(struct ConfItem *, dlink_list *);
87 static void delete_link(struct ConfItem *, dlink_list *);
88
89 #define CONFSIZE (offsetof(struct ConfItem, conf))
90 struct conf_item_table_type conf_item_table[] =
91 {
92 /* CONF_TYPE */
93 { 0, 0 , 0, 0},
94 /* CLASS_TYPE */
95 { CONFSIZE + sizeof(struct ClassItem), 0,
96 &class_items, delete_link},
97 /* OPER_TYPE */
98 { CONFSIZE + sizeof(struct AccessItem), CONF_OPERATOR,
99 &oconf_items, free_aconf_items },
100 /* CLIENT_TYPE */
101 { CONFSIZE + sizeof(struct AccessItem), CONF_CLIENT,
102 NULL, free_aconf_items },
103 /* SERVER_TYPE */
104 { CONFSIZE + sizeof(struct AccessItem), CONF_SERVER,
105 &server_items, free_aconf_items },
106 /* HUB_TYPE */
107 { CONFSIZE + sizeof(struct MatchItem), 0,
108 &hub_items, free_match_items },
109 /* LEAF_TYPE */
110 { CONFSIZE + sizeof(struct MatchItem), 0,
111 &leaf_items, free_match_items },
112 /* KLINE_TYPE */
113 { CONFSIZE + sizeof(struct AccessItem), CONF_KLINE,
114 NULL, free_aconf_items },
115 /* DLINE_TYPE */
116 { CONFSIZE + sizeof(struct AccessItem), CONF_DLINE,
117 NULL, free_aconf_items },
118 /* EXEMPTDLINE_TYPE */
119 { CONFSIZE + sizeof(struct AccessItem), CONF_EXEMPTDLINE,
120 NULL, free_aconf_items },
121 /* CLUSTER_TYPE */
122 { CONFSIZE , 0,
123 &cluster_items, delete_link },
124 /* RKLINE_TYPE */
125 { CONFSIZE + sizeof(struct AccessItem), CONF_KLINE,
126 &rkconf_items, free_aconf_items },
127 /* RXLINE_TYPE */
128 { CONFSIZE + sizeof(struct MatchItem), CONF_KLINE,
129 &rxconf_items, free_match_items },
130 /* XLINE_TYPE */
131 { CONFSIZE + sizeof(struct AccessItem), 0,
132 &xconf_items, free_match_items },
133 /* ULINE_TYPE */
134 { CONFSIZE + sizeof(struct AccessItem), 0,
135 &uconf_items, free_match_items },
136 /* GLINE_TYPE */
137 { CONFSIZE + sizeof(struct AccessItem), CONF_GLINE,
138 NULL, free_aconf_items },
139 /* CRESV_TYPE */
140 { CONFSIZE + sizeof(struct MatchItem), 0, NULL },
141 /* NRESV_TYPE */
142 { CONFSIZE + sizeof(struct MatchItem), 0,
143 &nresv_items, free_match_items },
144 /* GDENY_TYPE */
145 { CONFSIZE + sizeof(struct AccessItem), 0,
146 &gdeny_items, free_aconf_items },
147 { 0, 0, 0}
148 };
149
150 /*
151 * bit_len
152 */
153 static int cidr_limit_reached(int, struct irc_ssaddr *, struct ClassItem *);
154 static void remove_from_cidr_check(struct irc_ssaddr *, struct ClassItem *);
155 static void destroy_cidr_class(struct ClassItem *);
156
157 static void flags_to_ascii(unsigned int, const unsigned int[], char *, int);
158
159 FBFILE *conf_fbfile_in = NULL;
160
161 /* address of default class conf */
162 static struct ConfItem *class_default;
163
164 /* usually, with hash tables, you use a prime number...
165 * but in this case I am dealing with ip addresses,
166 * not ascii strings.
167 */
168 #define IP_HASH_SIZE 0x1000
169
170 struct ip_entry
171 {
172 struct irc_ssaddr ip;
173 int count;
174 time_t last_attempt;
175 struct ip_entry *next;
176 };
177
178 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
179 static BlockHeap *ip_entry_heap = NULL;
180 static int ip_entries_count = 0;
181
182 /* conf_dns_callback()
183 *
184 * inputs - pointer to struct AccessItem
185 * - pointer to DNSReply reply
186 * output - none
187 * side effects - called when resolver query finishes
188 * if the query resulted in a successful search, hp will contain
189 * a non-null pointer, otherwise hp will be null.
190 * if successful save hp in the conf item it was called with
191 */
192 static void
193 conf_dns_callback(void *vptr, struct DNSReply *reply)
194 {
195 struct AccessItem *aconf = (struct AccessItem *)vptr;
196 struct ConfItem *conf;
197
198 MyFree(aconf->dns_query);
199 aconf->dns_query = NULL;
200
201 if (reply != NULL)
202 memcpy(&aconf->ipnum, &reply->addr, sizeof(reply->addr));
203 else
204 {
205 ilog(L_NOTICE, "Host not found: %s, ignoring connect{} block",
206 aconf->host);
207 conf = aconf->conf_ptr;
208 sendto_realops_flags(UMODE_ALL, L_ALL,
209 "Ignoring connect{} block for %s - host not found",
210 conf->name);
211 delete_conf_item(conf);
212 }
213 }
214
215 /* conf_dns_lookup()
216 *
217 * do a nameserver lookup of the conf host
218 * if the conf entry is currently doing a ns lookup do nothing, otherwise
219 * allocate a dns_query and start ns lookup.
220 */
221 static void
222 conf_dns_lookup(struct AccessItem *aconf)
223 {
224 if (aconf->dns_query == NULL)
225 {
226 aconf->dns_query = MyMalloc(sizeof(struct DNSQuery));
227 aconf->dns_query->ptr = aconf;
228 aconf->dns_query->callback = conf_dns_callback;
229 gethost_byname(aconf->host, aconf->dns_query);
230 }
231 }
232
233 /* make_conf_item()
234 *
235 * inputs - type of item
236 * output - pointer to new conf entry
237 * side effects - none
238 */
239 struct ConfItem *
240 make_conf_item(ConfType type)
241 {
242 size_t size;
243 struct ConfItem *conf = NULL;
244 struct AccessItem *aconf = NULL;
245 dlink_list *list;
246 int status;
247
248 size = conf_item_table[type].size;
249 conf = MyMalloc(size);
250 conf->type = type;
251 list = conf_item_table[type].list;
252 status = conf_item_table[type].status;
253 /* XXX conf_ptr is in the same place in each subtype */
254 aconf = &conf->conf.AccessItem;
255 aconf->conf_ptr = conf;
256 /* XXX */
257 if (status != 0)
258 {
259 aconf->status = status;
260 aconf->aftype = AF_INET;
261 }
262 if (list != NULL)
263 dlinkAdd(conf, &conf->node, list);
264
265 return conf;
266 }
267
268 /*
269 * delete_conf_item
270 *
271 * inputs - pointer to struct ConfItem
272 * output - NONE
273 * side effects - Take given conf and delete it.
274 */
275 void
276 delete_conf_item(struct ConfItem *conf)
277 {
278 ConfType type = conf->type;
279 dlink_list *list;
280
281 list = conf_item_table[type].list;
282
283 MyFree(conf->name);
284 conf->name = NULL;
285 MyFree(conf->regexpname);
286 conf->regexpname = NULL;
287
288 if (conf_item_table[type].freer != NULL)
289 conf_item_table[type].freer(conf, list);
290
291 MyFree(conf);
292 }
293
294 /*
295 * free_aconf_items
296 *
297 * inputs - pointer to struct ConfItem
298 * - pointer to list to delink from, if NULL nothing to do
299 * output - NONE
300 * side effects - free all AcessItem entries, optionally delink from
301 * given list
302 */
303 static void
304 free_aconf_items(struct ConfItem *conf, dlink_list *list)
305 {
306 struct AccessItem *aconf;
307
308 aconf = &conf->conf.AccessItem;
309
310 if (aconf->dns_query != NULL)
311 {
312 delete_resolver_queries(aconf->dns_query);
313 MyFree(aconf->dns_query);
314 }
315 if (aconf->passwd != NULL)
316 memset(aconf->passwd, 0, strlen(aconf->passwd));
317 if (aconf->spasswd != NULL)
318 memset(aconf->spasswd, 0, strlen(aconf->spasswd));
319 aconf->class_ptr = NULL;
320
321 MyFree(aconf->regexuser);
322 MyFree(aconf->regexhost);
323 MyFree(aconf->passwd);
324 MyFree(aconf->spasswd);
325 MyFree(aconf->reason);
326 MyFree(aconf->oper_reason);
327 MyFree(aconf->user);
328 MyFree(aconf->host);
329 MyFree(aconf->fakename);
330 #ifdef HAVE_LIBCRYPTO
331 if (aconf->rsa_public_key)
332 RSA_free(aconf->rsa_public_key);
333 MyFree(aconf->rsa_public_key_file);
334 #endif
335
336 if (list != NULL && !IsConfIllegal(aconf))
337 dlinkDelete(&conf->node, list);
338 }
339
340 /*
341 * delete_link
342 *
343 * inputs - pointer to struct ConfItem
344 * - pointer to list
345 * output - NONE
346 * side effects - Simply unhook given ConfItem from given list
347 */
348 static void
349 delete_link(struct ConfItem *conf, dlink_list *list)
350 {
351 if (list != NULL)
352 dlinkDelete(&conf->node, list);
353 }
354
355
356 /*
357 * free_match_items
358 *
359 * inputs - pointer to struct ConfItem
360 * - pointer to list to delink from, if NULL nothing to do
361 * output - NONE
362 * side effects - free all MatchItem entries, optionally delink from
363 * given list
364 */
365 static void
366 free_match_items(struct ConfItem *conf, dlink_list *list)
367 {
368 struct MatchItem *match_item;
369
370 match_item = &conf->conf.MatchItem;
371 MyFree(match_item->user);
372 MyFree(match_item->host);
373 MyFree(match_item->reason);
374 MyFree(match_item->oper_reason);
375 if ((list != NULL) && !match_item->illegal)
376 dlinkDelete(&conf->node, list);
377 }
378
379 static const unsigned int shared_bit_table[] =
380 { 'K', 'k', 'U', 'X', 'x', 'Y', 'Q', 'q', 'R', 'L', 0};
381
382 /* report_confitem_types()
383 *
384 * inputs - pointer to client requesting confitem report
385 * - ConfType to report
386 * output - none
387 * side effects - report conf items to source_p
388 */
389 void
390 report_confitem_types(struct Client *source_p, ConfType type, int temp)
391 {
392 dlink_node *ptr = NULL;
393 struct ConfItem *conf = NULL;
394 struct AccessItem *aconf = NULL;
395 struct MatchItem *matchitem = NULL;
396 struct ClassItem *classitem = NULL;
397 char buf[12];
398 char *p = NULL;
399
400 switch (type)
401 {
402 case GDENY_TYPE:
403 DLINK_FOREACH(ptr, gdeny_items.head)
404 {
405 conf = ptr->data;
406 aconf = &conf->conf.AccessItem;
407
408 p = buf;
409
410 if (aconf->flags & GDENY_BLOCK)
411 *p++ = 'B';
412 else
413 *p++ = 'b';
414
415 if (aconf->flags & GDENY_REJECT)
416 *p++ = 'R';
417 else
418 *p++ = 'r';
419
420 *p = '\0';
421
422 sendto_one(source_p, ":%s %d %s V %s@%s %s %s",
423 me.name, RPL_STATSDEBUG, source_p->name,
424 aconf->user, aconf->host, conf->name, buf);
425 }
426 break;
427
428 case XLINE_TYPE:
429 DLINK_FOREACH(ptr, xconf_items.head)
430 {
431 conf = ptr->data;
432 matchitem = &conf->conf.MatchItem;
433
434 sendto_one(source_p, form_str(RPL_STATSXLINE),
435 me.name, source_p->name,
436 matchitem->hold ? "x": "X", matchitem->count,
437 conf->name, matchitem->reason);
438 }
439 break;
440
441 case RXLINE_TYPE:
442 DLINK_FOREACH(ptr, rxconf_items.head)
443 {
444 conf = ptr->data;
445 matchitem = &conf->conf.MatchItem;
446
447 sendto_one(source_p, form_str(RPL_STATSXLINE),
448 me.name, source_p->name,
449 matchitem->hold ? "xR": "XR", matchitem->count,
450 conf->name, matchitem->reason);
451 }
452 break;
453
454 case RKLINE_TYPE:
455 p = temp ? "Rk" : "RK";
456
457 DLINK_FOREACH(ptr, rkconf_items.head)
458 {
459 aconf = &((struct ConfItem *)(conf = ptr->data))->conf.AccessItem;
460
461 if (temp && !(conf->flags & CONF_FLAGS_TEMPORARY))
462 continue;
463
464 sendto_one(source_p, form_str(RPL_STATSKLINE), me.name,
465 source_p->name, p, aconf->host, aconf->user,
466 aconf->reason, aconf->oper_reason ? aconf->oper_reason : "");
467 }
468 break;
469
470 case ULINE_TYPE:
471 DLINK_FOREACH(ptr, uconf_items.head)
472 {
473 conf = ptr->data;
474 matchitem = &conf->conf.MatchItem;
475
476 p = buf;
477
478 /* some of these are redundant for the sake of
479 * consistency with cluster{} flags
480 */
481 *p++ = 'c';
482 flags_to_ascii(matchitem->action, shared_bit_table, p, 0);
483
484 sendto_one(source_p, form_str(RPL_STATSULINE),
485 me.name, source_p->name, conf->name,
486 matchitem->user?matchitem->user: "*",
487 matchitem->host?matchitem->host: "*", buf);
488 }
489
490 DLINK_FOREACH(ptr, cluster_items.head)
491 {
492 conf = ptr->data;
493
494 p = buf;
495
496 *p++ = 'C';
497 flags_to_ascii(conf->flags, shared_bit_table, p, 0);
498
499 sendto_one(source_p, form_str(RPL_STATSULINE),
500 me.name, source_p->name, conf->name,
501 "*", "*", buf);
502 }
503
504 break;
505
506 case OPER_TYPE:
507 DLINK_FOREACH(ptr, oconf_items.head)
508 {
509 conf = ptr->data;
510 aconf = &conf->conf.AccessItem;
511
512 /* Don't allow non opers to see oper privs */
513 if (IsOper(source_p))
514 sendto_one(source_p, form_str(RPL_STATSOLINE),
515 me.name, source_p->name, 'O', aconf->user, aconf->host,
516 conf->name, oper_privs_as_string(aconf->port),
517 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
518 else
519 sendto_one(source_p, form_str(RPL_STATSOLINE),
520 me.name, source_p->name, 'O', aconf->user, aconf->host,
521 conf->name, "0",
522 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
523 }
524 break;
525
526 case CLASS_TYPE:
527 DLINK_FOREACH(ptr, class_items.head)
528 {
529 conf = ptr->data;
530 classitem = &conf->conf.ClassItem;
531 sendto_one(source_p, form_str(RPL_STATSYLINE),
532 me.name, source_p->name, 'Y',
533 conf->name, PingFreq(classitem),
534 ConFreq(classitem),
535 MaxTotal(classitem), MaxSendq(classitem));
536 }
537 break;
538
539 case CONF_TYPE:
540 case CLIENT_TYPE:
541 break;
542
543 case SERVER_TYPE:
544 DLINK_FOREACH(ptr, server_items.head)
545 {
546 p = buf;
547
548 conf = ptr->data;
549 aconf = &conf->conf.AccessItem;
550
551 buf[0] = '\0';
552
553 if (IsConfAllowAutoConn(aconf))
554 *p++ = 'A';
555 if (IsConfCryptLink(aconf))
556 *p++ = 'C';
557 if (IsConfLazyLink(aconf))
558 *p++ = 'L';
559 if (aconf->fakename)
560 *p++ = 'M';
561 if (IsConfTopicBurst(aconf))
562 *p++ = 'T';
563 if (IsConfCompressed(aconf))
564 *p++ = 'Z';
565 if (buf[0] == '\0')
566 *p++ = '*';
567
568 *p = '\0';
569
570 /* Allow admins to see actual ips
571 * unless hide_server_ips is enabled
572 */
573 if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
574 sendto_one(source_p, form_str(RPL_STATSCLINE),
575 me.name, source_p->name, 'C', aconf->host,
576 buf, conf->name, aconf->port,
577 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
578 else
579 sendto_one(source_p, form_str(RPL_STATSCLINE),
580 me.name, source_p->name, 'C',
581 "*@127.0.0.1", buf, conf->name, aconf->port,
582 aconf->class_ptr ? aconf->class_ptr->name : "<default>");
583 }
584 break;
585
586 case HUB_TYPE:
587 DLINK_FOREACH(ptr, hub_items.head)
588 {
589 conf = ptr->data;
590 matchitem = &conf->conf.MatchItem;
591 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
592 source_p->name, 'H', matchitem->host, conf->name, 0, "*");
593 }
594 break;
595
596 case LEAF_TYPE:
597 DLINK_FOREACH(ptr, leaf_items.head)
598 {
599 conf = ptr->data;
600 matchitem = &conf->conf.MatchItem;
601 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
602 source_p->name, 'L', matchitem->host, conf->name, 0, "*");
603 }
604 break;
605
606 case GLINE_TYPE:
607 case KLINE_TYPE:
608 case DLINE_TYPE:
609 case EXEMPTDLINE_TYPE:
610 case CRESV_TYPE:
611 case NRESV_TYPE:
612 case CLUSTER_TYPE:
613 break;
614 }
615 }
616
617 /* check_client()
618 *
619 * inputs - pointer to client
620 * output - 0 = Success
621 * NOT_AUTHORIZED (-1) = Access denied (no I line match)
622 * IRCD_SOCKET_ERROR (-2) = Bad socket.
623 * I_LINE_FULL (-3) = I-line is full
624 * TOO_MANY (-4) = Too many connections from hostname
625 * BANNED_CLIENT (-5) = K-lined
626 * side effects - Ordinary client access check.
627 * Look for conf lines which have the same
628 * status as the flags passed.
629 */
630 static void *
631 check_client(va_list args)
632 {
633 struct Client *source_p = va_arg(args, struct Client *);
634 const char *username = va_arg(args, const char *);
635 struct AccessItem **aptr = va_arg(args, struct AccessItem **);
636 int i;
637
638 if ((i = verify_access(source_p, username, aptr)))
639 ilog(L_INFO, "Access denied: %s[%s]",
640 source_p->name, source_p->sockhost);
641
642 switch (i)
643 {
644 case IRCD_SOCKET_ERROR:
645 exit_client(source_p, &me, "Socket Error");
646 break;
647
648 case TOO_MANY:
649 sendto_realops_flags(UMODE_FULL, L_ALL,
650 "Too many on IP for %s (%s).",
651 get_client_name(source_p, SHOW_IP),
652 source_p->sockhost);
653 ilog(L_INFO,"Too many connections on IP from %s.",
654 get_client_name(source_p, SHOW_IP));
655 ServerStats->is_ref++;
656 exit_client(source_p, &me, "No more connections allowed on that IP");
657 break;
658
659 case I_LINE_FULL:
660 sendto_realops_flags(UMODE_FULL, L_ALL,
661 "I-line is full for %s (%s).",
662 get_client_name(source_p, SHOW_IP),
663 source_p->sockhost);
664 ilog(L_INFO,"Too many connections from %s.",
665 get_client_name(source_p, SHOW_IP));
666 ServerStats->is_ref++;
667 exit_client(source_p, &me,
668 "No more connections allowed in your connection class");
669 break;
670
671 case NOT_AUTHORIZED:
672 {
673 static char ipaddr[HOSTIPLEN];
674 ServerStats->is_ref++;
675 /* jdc - lists server name & port connections are on */
676 /* a purely cosmetical change */
677 irc_getnameinfo((struct sockaddr*)&source_p->localClient->ip,
678 source_p->localClient->ip.ss_len, ipaddr, HOSTIPLEN, NULL, 0,
679 NI_NUMERICHOST);
680 sendto_realops_flags(UMODE_UNAUTH, L_ALL,
681 "Unauthorized client connection from %s [%s] on [%s/%u].",
682 get_client_name(source_p, SHOW_IP),
683 ipaddr,
684 source_p->localClient->listener->name,
685 source_p->localClient->listener->port);
686 ilog(L_INFO,
687 "Unauthorized client connection from %s on [%s/%u].",
688 get_client_name(source_p, SHOW_IP),
689 source_p->localClient->listener->name,
690 source_p->localClient->listener->port);
691
692 /* XXX It is prolematical whether it is better to use the
693 * capture reject code here or rely on the connecting too fast code.
694 * - Dianora
695 */
696 if(REJECT_HOLD_TIME > 0)
697 {
698 sendto_one(source_p, ":%s NOTICE %s :You are not authorized to use this server",
699 me.name, source_p->name);
700 source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
701 SetCaptured(source_p);
702 }
703 else
704 exit_client(source_p, &me, "You are not authorized to use this server");
705 break;
706 }
707
708 case BANNED_CLIENT:
709 /*
710 * Don't exit them immediately, play with them a bit.
711 * - Dianora
712 */
713 if (REJECT_HOLD_TIME > 0)
714 {
715 source_p->localClient->reject_delay = CurrentTime + REJECT_HOLD_TIME;
716 SetCaptured(source_p);
717 }
718 else
719 exit_client(source_p, &me, "Banned");
720 ServerStats->is_ref++;
721 break;
722
723 case 0:
724 default:
725 break;
726 }
727
728 return (i < 0 ? NULL : source_p);
729 }
730
731 /* verify_access()
732 *
733 * inputs - pointer to client to verify
734 * - pointer to proposed username
735 * output - 0 if success -'ve if not
736 * side effect - find the first (best) I line to attach.
737 */
738 static int
739 verify_access(struct Client *client_p, const char *username, struct AccessItem **aptr)
740 {
741 struct AccessItem *aconf = NULL, *rkconf = NULL;
742 struct ConfItem *conf = NULL;
743 struct ClassItem *aclass = NULL;
744 char non_ident[USERLEN + 1] = { '~', '\0' };
745 const char *uhi[3];
746
747 if (IsGotId(client_p))
748 {
749 aconf = find_address_conf(client_p->host, client_p->username,
750 &client_p->localClient->ip,
751 client_p->localClient->aftype,
752 client_p->localClient->passwd);
753 }
754 else
755 {
756 strlcpy(non_ident+1, username, sizeof(non_ident)-1);
757 aconf = find_address_conf(client_p->host,non_ident,
758 &client_p->localClient->ip,
759 client_p->localClient->aftype,
760 client_p->localClient->passwd);
761 }
762
763 uhi[0] = IsGotId(client_p) ? client_p->username : non_ident;
764 uhi[1] = client_p->host;
765 uhi[2] = client_p->sockhost;
766
767 rkconf = find_regexp_kline(uhi);
768
769 if (aconf != NULL)
770 {
771 if (IsConfClient(aconf) && !rkconf)
772 {
773 conf = aconf->conf_ptr;
774
775 if (IsConfRedir(aconf))
776 {
777 sendto_one(client_p, form_str(RPL_REDIR),
778 me.name, client_p->name,
779 conf->name ? conf->name : "",
780 aconf->port);
781 return(NOT_AUTHORIZED);
782 }
783
784 if (IsConfDoIdentd(aconf))
785 SetNeedId(client_p);
786
787 /* Thanks for spoof idea amm */
788 if (IsConfDoSpoofIp(aconf))
789 {
790 if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(aconf))
791 sendto_realops_flags(UMODE_ALL, L_ADMIN, "%s spoofing: %s as %s",
792 client_p->name, client_p->host, conf->name);
793 strlcpy(client_p->host, conf->name, sizeof(client_p->host));
794 SetIPSpoof(client_p);
795 }
796
797 aclass = &((struct ConfItem *)(aconf->class_ptr))->conf.ClassItem;
798
799 if (check_class_limits(client_p, IsConfExemptLimits(aconf), aclass))
800 {
801 assert(aptr);
802 *aptr = aconf;
803 attach_class(client_p, aclass);
804 return(0);
805 }
806 else
807 return(TOO_MANY);
808 }
809 else if (rkconf || IsConfKill(aconf) || (ConfigFileEntry.glines && IsConfGline(aconf)))
810 {
811 /* XXX */
812 aconf = rkconf ? rkconf : aconf;
813 if (IsConfGline(aconf))
814 sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
815 client_p->name);
816 if (ConfigFileEntry.kline_with_reason)
817 sendto_one(client_p, ":%s NOTICE %s :*** Banned %s",
818 me.name, client_p->name, aconf->reason);
819 return(BANNED_CLIENT);
820 }
821 }
822
823 return(NOT_AUTHORIZED);
824 }
825
826 /* check_class_limits()
827 *
828 * inputs - client pointer
829 * - int exempt or not to limits
830 * - class pointer
831 * output - 0 if limits ok, non 0 if limits not ok
832 * side effects - NONE
833 */
834 static int
835 check_class_limits(struct Client *client_p, int exempt,
836 struct ClassItem *aclass)
837 {
838 struct ip_entry *ip_found;
839 int a_limit_reached = 0;
840 int local = 0, global = 0, ident = 0;
841
842 ip_found = find_or_add_ip(&client_p->localClient->ip);
843 ip_found->count++;
844 SetIpHash(client_p);
845
846 count_user_host(client_p->username, client_p->host,
847 &global, &local, &ident);
848
849 /* XXX blah. go down checking the various silly limits
850 * setting a_limit_reached if any limit is reached.
851 * - Dianora
852 */
853 if (MaxTotal(aclass) != 0 && CurrUserCount(aclass) >= MaxTotal(aclass))
854 a_limit_reached = 1;
855 else if (MaxPerIp(aclass) != 0 && ip_found->count >= MaxPerIp(aclass))
856 a_limit_reached = 1;
857 else if (MaxLocal(aclass) != 0 && local >= MaxLocal(aclass))
858 a_limit_reached = 1;
859 else if (MaxGlobal(aclass) != 0 && global >= MaxGlobal(aclass))
860 a_limit_reached = 1;
861 else if (MaxIdent(aclass) != 0 && ident >= MaxIdent(aclass) &&
862 client_p->username[0] != '~')
863 a_limit_reached = 1;
864
865
866 if (a_limit_reached)
867 {
868 if (!exempt)
869 return 0; /* Already at maximum allowed */
870
871 sendto_one(client_p,
872 ":%s NOTICE %s :*** Your connection class is full, "
873 "but you have exceed_limit = yes;", me.name, client_p->name);
874 }
875
876 if (cidr_limit_reached(exempt, &client_p->localClient->ip, aclass))
877 return 0; /* Already at maximum allowed */
878
879 return 1;
880 }
881
882 /* init_ip_hash_table()
883 *
884 * inputs - NONE
885 * output - NONE
886 * side effects - allocate memory for ip_entry(s)
887 * - clear the ip hash table
888 */
889 void
890 init_ip_hash_table(void)
891 {
892 ip_entry_heap = BlockHeapCreate("ip", sizeof(struct ip_entry),
893 2 * hard_fdlimit);
894 memset(ip_hash_table, 0, sizeof(ip_hash_table));
895 }
896
897 /* find_or_add_ip()
898 *
899 * inputs - pointer to struct irc_ssaddr
900 * output - pointer to a struct ip_entry
901 * side effects -
902 *
903 * If the ip # was not found, a new struct ip_entry is created, and the ip
904 * count set to 0.
905 */
906 static struct ip_entry *
907 find_or_add_ip(struct irc_ssaddr *ip_in)
908 {
909 struct ip_entry *ptr, *newptr;
910 int hash_index = hash_ip(ip_in), res;
911 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
912 #ifdef IPV6
913 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
914 #endif
915
916 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
917 {
918 #ifdef IPV6
919 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
920 continue;
921 if (ip_in->ss.ss_family == AF_INET6)
922 {
923 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
924 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
925 }
926 else
927 #endif
928 {
929 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
930 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
931 }
932 if (res == 0)
933 {
934 /* Found entry already in hash, return it. */
935 return ptr;
936 }
937 }
938
939 if (ip_entries_count >= 2 * hard_fdlimit)
940 garbage_collect_ip_entries();
941
942 newptr = BlockHeapAlloc(ip_entry_heap);
943 ip_entries_count++;
944 memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
945
946 newptr->next = ip_hash_table[hash_index];
947 ip_hash_table[hash_index] = newptr;
948
949 return newptr;
950 }
951
952 /* remove_one_ip()
953 *
954 * inputs - unsigned long IP address value
955 * output - NONE
956 * side effects - The ip address given, is looked up in ip hash table
957 * and number of ip#'s for that ip decremented.
958 * If ip # count reaches 0 and has expired,
959 * the struct ip_entry is returned to the ip_entry_heap
960 */
961 void
962 remove_one_ip(struct irc_ssaddr *ip_in)
963 {
964 struct ip_entry *ptr;
965 struct ip_entry *last_ptr = NULL;
966 int hash_index = hash_ip(ip_in), res;
967 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
968 #ifdef IPV6
969 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
970 #endif
971
972 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
973 {
974 #ifdef IPV6
975 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
976 continue;
977 if (ip_in->ss.ss_family == AF_INET6)
978 {
979 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
980 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
981 }
982 else
983 #endif
984 {
985 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
986 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
987 }
988 if (res)
989 continue;
990 if (ptr->count > 0)
991 ptr->count--;
992 if (ptr->count == 0 &&
993 (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
994 {
995 if (last_ptr != NULL)
996 last_ptr->next = ptr->next;
997 else
998 ip_hash_table[hash_index] = ptr->next;
999
1000 BlockHeapFree(ip_entry_heap, ptr);
1001 ip_entries_count--;
1002 return;
1003 }
1004 last_ptr = ptr;
1005 }
1006 }
1007
1008 /* hash_ip()
1009 *
1010 * input - pointer to an irc_inaddr
1011 * output - integer value used as index into hash table
1012 * side effects - hopefully, none
1013 */
1014 static int
1015 hash_ip(struct irc_ssaddr *addr)
1016 {
1017 if (addr->ss.ss_family == AF_INET)
1018 {
1019 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1020 int hash;
1021 u_int32_t ip;
1022
1023 ip = ntohl(v4->sin_addr.s_addr);
1024 hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
1025 return hash;
1026 }
1027 #ifdef IPV6
1028 else
1029 {
1030 int hash;
1031 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
1032 u_int32_t *ip = (u_int32_t *)&v6->sin6_addr.s6_addr;
1033
1034 hash = ip[0] ^ ip[3];
1035 hash ^= hash >> 16;
1036 hash ^= hash >> 8;
1037 hash = hash & (IP_HASH_SIZE - 1);
1038 return hash;
1039 }
1040 #else
1041 return 0;
1042 #endif
1043 }
1044
1045 /* count_ip_hash()
1046 *
1047 * inputs - pointer to counter of number of ips hashed
1048 * - pointer to memory used for ip hash
1049 * output - returned via pointers input
1050 * side effects - NONE
1051 *
1052 * number of hashed ip #'s is counted up, plus the amount of memory
1053 * used in the hash.
1054 */
1055 void
1056 count_ip_hash(int *number_ips_stored, unsigned long *mem_ips_stored)
1057 {
1058 struct ip_entry *ptr;
1059 int i;
1060
1061 *number_ips_stored = 0;
1062 *mem_ips_stored = 0;
1063
1064 for (i = 0; i < IP_HASH_SIZE; i++)
1065 {
1066 for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
1067 {
1068 *number_ips_stored += 1;
1069 *mem_ips_stored += sizeof(struct ip_entry);
1070 }
1071 }
1072 }
1073
1074 /* garbage_collect_ip_entries()
1075 *
1076 * input - NONE
1077 * output - NONE
1078 * side effects - free up all ip entries with no connections
1079 */
1080 static void
1081 garbage_collect_ip_entries(void)
1082 {
1083 struct ip_entry *ptr;
1084 struct ip_entry *last_ptr;
1085 struct ip_entry *next_ptr;
1086 int i;
1087
1088 for (i = 0; i < IP_HASH_SIZE; i++)
1089 {
1090 last_ptr = NULL;
1091
1092 for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
1093 {
1094 next_ptr = ptr->next;
1095
1096 if (ptr->count == 0 &&
1097 (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
1098 {
1099 if (last_ptr != NULL)
1100 last_ptr->next = ptr->next;
1101 else
1102 ip_hash_table[i] = ptr->next;
1103 BlockHeapFree(ip_entry_heap, ptr);
1104 ip_entries_count--;
1105 }
1106 else
1107 last_ptr = ptr;
1108 }
1109 }
1110 }
1111
1112 /* detach_conf()
1113 *
1114 * inputs - pointer to client to detach
1115 * - type of conf to detach
1116 * output - 0 for success, -1 for failure
1117 * side effects - Disassociate configuration from the client.
1118 * Also removes a class from the list if marked for deleting.
1119 */
1120 int
1121 detach_conf(struct Client *client_p, ConfType type)
1122 {
1123 dlink_node *ptr, *next_ptr;
1124 struct ConfItem *conf;
1125 struct ClassItem *aclass;
1126 struct AccessItem *aconf;
1127 struct MatchItem *match_item;
1128
1129 aclass = client_p->localClient->class;
1130 if (aclass != NULL)
1131 {
1132 remove_from_cidr_check(&client_p->localClient->ip, aclass);
1133
1134 if (CurrUserCount(aclass) > 0)
1135 aclass->curr_user_count--;
1136 if (MaxTotal(aclass) < 0 && CurrUserCount(aclass) <= 0)
1137 delete_conf_item(aclass->conf_ptr);
1138 }
1139
1140 /* More to do if this client is a server, else return */
1141 if (client_p->serv == NULL)
1142 return 0;
1143
1144 conf = client_p->serv->sconf;
1145 aconf = &conf->conf.AccessItem;
1146
1147 client_p->serv->sconf = NULL;
1148
1149 DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->serv->leafs_hubs.head)
1150 {
1151 conf = ptr->data;
1152 match_item = &conf->conf.MatchItem;
1153
1154 dlinkDelete(ptr, &client_p->serv->leafs_hubs);
1155 free_dlink_node(ptr);
1156
1157 if (match_item->ref_count == 0 && match_item->illegal)
1158 delete_conf_item(conf);
1159 }
1160
1161 return 0;
1162 }
1163
1164 /* attach_leaf_hub()
1165 *
1166 * inputs - server pointer
1167 * - conf (HUB or LEAF mask) pointer
1168 * output - 0 if sucessfully added, 1 if unsuccessful.
1169 * side effects - Associate a specific configuration entry to a *local*
1170 * server
1171 */
1172 int
1173 attach_leaf_hub(struct Client *client_p, struct ConfItem *conf)
1174 {
1175 struct MatchItem *match_item;
1176 if (dlinkFind(&client_p->serv->leafs_hubs, conf) != NULL)
1177 return 1;
1178
1179 match_item = &conf->conf.MatchItem;
1180 match_item->ref_count++;
1181 dlinkAdd(conf, make_dlink_node(), &client_p->serv->leafs_hubs);
1182
1183 return 0;
1184 }
1185
1186 /*
1187 * attach_class
1188 *
1189 * inputs - pointer to client to attach ClassItem to
1190 * - pointer to aclass
1191 * output - 0 if successful, -1 if unsuccesful
1192 * side effects -
1193 */
1194 static int
1195 attach_class(struct Client *client_p, struct ClassItem *aclass)
1196 {
1197 if (client_p->localClient->class == NULL)
1198 {
1199 CurrUserCount(aclass)++;
1200 client_p->localClient->class = aclass;
1201 return 0;
1202 }
1203 else
1204 {
1205 ilog(L_ERROR, "%s: attach_class already attached",
1206 get_client_name(client_p, SHOW_IP));
1207 return -1;
1208 }
1209 }
1210
1211 /*
1212 * attach_server_conf
1213 *
1214 * inputs - pointer to client to attach ConfItem to
1215 * - pointer to ConfItem
1216 * output - 0 if successful, -1 if unsuccesful
1217 * side effects -
1218 */
1219 int
1220 attach_server_conf(struct Client *client_p, struct ConfItem *conf)
1221 {
1222 if (client_p->serv->sconf == NULL)
1223 {
1224 client_p->serv->sconf = conf;
1225 return 0;
1226 }
1227 else
1228 {
1229 ilog(L_ERROR, "%s: attach_server_conf already attached",
1230 get_client_name(client_p, SHOW_IP));
1231 return -1;
1232 }
1233 }
1234
1235 /* attach_connect_block()
1236 *
1237 * inputs - pointer to server to attach
1238 * - name of server
1239 * - hostname of server
1240 * output - true (1) if both are found, otherwise return false (0)
1241 * side effects - find connect block and attach them to connecting client
1242 */
1243 int
1244 attach_connect_block(struct Client *client_p, const char *name,
1245 const char *host)
1246 {
1247 dlink_node *ptr;
1248 struct ConfItem *conf;
1249 struct AccessItem *aconf;
1250
1251 assert(client_p != NULL);
1252 assert(host != NULL);
1253
1254 if (client_p == NULL || host == NULL)
1255 return 0;
1256
1257 DLINK_FOREACH(ptr, server_items.head)
1258 {
1259 conf = ptr->data;
1260 aconf = &conf->conf.AccessItem;
1261
1262 if (match(conf->name, name) == 0 || match(aconf->host, host) == 0)
1263 continue;
1264
1265 attach_server_conf(client_p, conf);
1266 return 1;
1267 }
1268
1269 return 0;
1270 }
1271
1272 /* find_matching_name_conf()
1273 *
1274 * inputs - type of link list to look in
1275 * - pointer to name string to find
1276 * - pointer to user
1277 * - pointer to host
1278 * - optional action to match on as well
1279 * output - NULL or pointer to found struct MatchItem
1280 * side effects - looks for a match on name field
1281 */
1282 struct ConfItem *
1283 find_matching_name_conf(ConfType type, const char *name, const char *user,
1284 const char *host, int action)
1285 {
1286 dlink_node *ptr=NULL;
1287 struct ConfItem *conf=NULL;
1288 struct AccessItem *aconf=NULL;
1289 struct MatchItem *match_item=NULL;
1290 dlink_list *list_p = conf_item_table[type].list;
1291
1292 switch (type)
1293 {
1294 case RXLINE_TYPE:
1295 DLINK_FOREACH(ptr, list_p->head)
1296 {
1297 conf = ptr->data;
1298 assert(conf->regexpname);
1299
1300 if (!ircd_pcre_exec(conf->regexpname, name))
1301 return conf;
1302 }
1303 break;
1304
1305 case XLINE_TYPE:
1306 case ULINE_TYPE:
1307 case NRESV_TYPE:
1308 DLINK_FOREACH(ptr, list_p->head)
1309 {
1310 conf = ptr->data;
1311
1312 match_item = &conf->conf.MatchItem;
1313 if (EmptyString(conf->name))
1314 continue;
1315 if ((name != NULL) && match_esc(conf->name, name))
1316 {
1317 if ((user == NULL && (host == NULL)))
1318 return conf;
1319 if ((match_item->action & action) != action)
1320 continue;
1321 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1322 return conf;
1323 if (match(match_item->user, user) && match(match_item->host, host))
1324 return conf;
1325 }
1326 }
1327 break;
1328
1329 case SERVER_TYPE:
1330 DLINK_FOREACH(ptr, list_p->head)
1331 {
1332 conf = ptr->data;
1333 aconf = &conf->conf.AccessItem;
1334
1335 if ((name != NULL) && match_esc(name, conf->name))
1336 return conf;
1337 else if ((host != NULL) && match_esc(host, aconf->host))
1338 return conf;
1339 }
1340 break;
1341
1342 default:
1343 break;
1344 }
1345 return NULL;
1346 }
1347
1348 /* find_exact_name_conf()
1349 *
1350 * inputs - type of link list to look in
1351 * - pointer to name string to find
1352 * - pointer to user
1353 * - pointer to host
1354 * output - NULL or pointer to found struct MatchItem
1355 * side effects - looks for an exact match on name field
1356 */
1357 struct ConfItem *
1358 find_exact_name_conf(ConfType type, const char *name,
1359 const char *user, const char *host)
1360 {
1361 dlink_node *ptr = NULL;
1362 struct AccessItem *aconf;
1363 struct ConfItem *conf;
1364 struct MatchItem *match_item;
1365 dlink_list *list_p;
1366
1367 list_p = conf_item_table[type].list;
1368
1369 switch(type)
1370 {
1371 case RXLINE_TYPE:
1372 case XLINE_TYPE:
1373 case ULINE_TYPE:
1374 case NRESV_TYPE:
1375
1376 DLINK_FOREACH(ptr, list_p->head)
1377 {
1378 conf = ptr->data;
1379 match_item = &conf->conf.MatchItem;
1380 if (EmptyString(conf->name))
1381 continue;
1382
1383 if (irccmp(conf->name, name) == 0)
1384 {
1385 if ((user == NULL && (host == NULL)))
1386 return (conf);
1387 if (EmptyString(match_item->user) || EmptyString(match_item->host))
1388 return (conf);
1389 if (match(match_item->user, user) && match(match_item->host, host))
1390 return (conf);
1391 }
1392 }
1393 break;
1394
1395 case OPER_TYPE:
1396 DLINK_FOREACH(ptr, list_p->head)
1397 {
1398 conf = ptr->data;
1399 aconf = &conf->conf.AccessItem;
1400 if (EmptyString(conf->name))
1401 continue;
1402
1403 if (irccmp(conf->name, name) == 0)
1404 {
1405 if ((user == NULL && (host == NULL)))
1406 return (conf);
1407 if (EmptyString(aconf->user) || EmptyString(aconf->host))
1408 return (conf);
1409 if (match(aconf->user, user) && match(aconf->host, host))
1410 return (conf);
1411 }
1412 }
1413 break;
1414
1415 case SERVER_TYPE:
1416 DLINK_FOREACH(ptr, list_p->head)
1417 {
1418 conf = ptr->data;
1419 if (EmptyString(conf->name))
1420 continue;
1421 aconf = &conf->conf.AccessItem;
1422
1423 if (name == NULL)
1424 {
1425 if (EmptyString(aconf->host))
1426 continue;
1427 if (irccmp(aconf->host, host) == 0)
1428 return(conf);
1429 }
1430 else if (irccmp(conf->name, name) == 0)
1431 {
1432 return (conf);
1433 }
1434 }
1435 break;
1436
1437 case CLASS_TYPE:
1438 DLINK_FOREACH(ptr, list_p->head)
1439 {
1440 conf = ptr->data;
1441 if (EmptyString(conf->name))
1442 continue;
1443
1444 if (irccmp(conf->name, name) == 0)
1445 return (conf);
1446 }
1447 break;
1448
1449 default:
1450 break;
1451 }
1452 return(NULL);
1453 }
1454
1455 /* rehash()
1456 *
1457 * Actual REHASH service routine. Called with sig == 0 if it has been called
1458 * as a result of an operator issuing this command, else assume it has been
1459 * called as a result of the server receiving a HUP signal.
1460 */
1461 int
1462 rehash(int sig)
1463 {
1464 if (sig != 0)
1465 sendto_realops_flags(UMODE_ALL, L_ALL,
1466 "Got signal SIGHUP, reloading ircd.conf file");
1467
1468 #ifndef _WIN32
1469 restart_resolver();
1470 #endif
1471 /* Don't close listeners until known I can go ahead with the rehash */
1472
1473 /* Check to see if we magically got(or lost) IPv6 support */
1474 ServerInfo.can_use_v6 = check_can_use_v6();
1475
1476 read_conf_files(0);
1477
1478 if (ServerInfo.description != NULL)
1479 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1480
1481 #ifndef STATIC_MODULES
1482 load_conf_modules();
1483 #endif
1484
1485 rehashed_klines = 1;
1486
1487 if (ConfigLoggingEntry.use_logging)
1488 reopen_log(logFileName);
1489
1490 return(0);
1491 }
1492
1493 /* set_default_conf()
1494 *
1495 * inputs - NONE
1496 * output - NONE
1497 * side effects - Set default values here.
1498 * This is called **PRIOR** to parsing the
1499 * configuration file. If you want to do some validation
1500 * of values later, put them in validate_conf().
1501 */
1502 static void
1503 set_default_conf(void)
1504 {
1505 /* verify init_class() ran, this should be an unnecessary check
1506 * but its not much work.
1507 */
1508 assert(class_default == (struct ConfItem *) class_items.tail->data);
1509
1510 #ifdef HAVE_LIBCRYPTO
1511 ServerInfo.rsa_private_key = NULL;
1512 ServerInfo.rsa_private_key_file = NULL;
1513 #endif
1514
1515 /* ServerInfo.name is not rehashable */
1516 /* ServerInfo.name = ServerInfo.name; */
1517 ServerInfo.description = NULL;
1518 DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1519 DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1520
1521 memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1522 ServerInfo.specific_ipv4_vhost = 0;
1523 memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1524 ServerInfo.specific_ipv6_vhost = 0;
1525
1526 ServerInfo.max_clients = MAXCLIENTS_MAX;
1527 /* Don't reset hub, as that will break lazylinks */
1528 /* ServerInfo.hub = NO; */
1529 ServerInfo.dns_host.sin_addr.s_addr = 0;
1530 ServerInfo.dns_host.sin_port = 0;
1531 AdminInfo.name = NULL;
1532 AdminInfo.email = NULL;
1533 AdminInfo.description = NULL;
1534
1535 set_log_level(L_NOTICE);
1536 ConfigLoggingEntry.use_logging = 1;
1537 ConfigLoggingEntry.operlog[0] = '\0';
1538 ConfigLoggingEntry.userlog[0] = '\0';
1539 ConfigLoggingEntry.klinelog[0] = '\0';
1540 ConfigLoggingEntry.glinelog[0] = '\0';
1541 ConfigLoggingEntry.killlog[0] = '\0';
1542 ConfigLoggingEntry.operspylog[0] = '\0';
1543 ConfigLoggingEntry.ioerrlog[0] = '\0';
1544 ConfigLoggingEntry.failed_operlog[0] = '\0';
1545
1546 ConfigChannel.restrict_channels = NO;
1547 ConfigChannel.disable_local_channels = NO;
1548 ConfigChannel.use_invex = YES;
1549 ConfigChannel.use_except = YES;
1550 ConfigChannel.use_knock = YES;
1551 ConfigChannel.knock_delay = 300;
1552 ConfigChannel.knock_delay_channel = 60;
1553 ConfigChannel.invite_ops_only = YES;
1554 ConfigChannel.max_chans_per_user = 15;
1555 ConfigChannel.quiet_on_ban = YES;
1556 ConfigChannel.max_bans = 25;
1557 ConfigChannel.default_split_user_count = 0;
1558 ConfigChannel.default_split_server_count = 0;
1559 ConfigChannel.no_join_on_split = NO;
1560 ConfigChannel.no_create_on_split = NO;
1561 ConfigChannel.burst_topicwho = YES;
1562
1563 ConfigServerHide.flatten_links = NO;
1564 ConfigServerHide.links_delay = 300;
1565 ConfigServerHide.hidden = NO;
1566 ConfigServerHide.disable_hidden = NO;
1567 ConfigServerHide.hide_servers = NO;
1568 DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1569 ConfigServerHide.hide_server_ips = NO;
1570
1571 ConfigFileEntry.gline_min_cidr = 16;
1572 ConfigFileEntry.gline_min_cidr6 = 48;
1573 ConfigFileEntry.invisible_on_connect = YES;
1574 ConfigFileEntry.burst_away = NO;
1575 ConfigFileEntry.use_whois_actually = YES;
1576 ConfigFileEntry.tkline_expire_notices = YES;
1577 ConfigFileEntry.hide_spoof_ips = YES;
1578 ConfigFileEntry.ignore_bogus_ts = NO;
1579 ConfigFileEntry.disable_auth = NO;
1580 ConfigFileEntry.disable_remote = NO;
1581 ConfigFileEntry.kill_chase_time_limit = 90;
1582 ConfigFileEntry.default_floodcount = 8; /* XXX */
1583 ConfigFileEntry.failed_oper_notice = YES;
1584 ConfigFileEntry.dots_in_ident = 0; /* XXX */
1585 ConfigFileEntry.dot_in_ip6_addr = YES;
1586 ConfigFileEntry.min_nonwildcard = 4;
1587 ConfigFileEntry.min_nonwildcard_simple = 3;
1588 ConfigFileEntry.max_accept = 20;
1589 ConfigFileEntry.anti_nick_flood = NO; /* XXX */
1590 ConfigFileEntry.max_nick_time = 20;
1591 ConfigFileEntry.max_nick_changes = 5;
1592 ConfigFileEntry.anti_spam_exit_message_time = 0; /* XXX */
1593 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1594 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT; /* XXX */
1595 ConfigFileEntry.kline_with_reason = YES;
1596 ConfigFileEntry.kline_reason = NULL;
1597 ConfigFileEntry.warn_no_nline = YES;
1598 ConfigFileEntry.stats_o_oper_only = NO; /* XXX */
1599 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1600 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1601 ConfigFileEntry.stats_P_oper_only = NO;
1602 ConfigFileEntry.caller_id_wait = 60;
1603 ConfigFileEntry.opers_bypass_callerid = NO;
1604 ConfigFileEntry.pace_wait = 10;
1605 ConfigFileEntry.pace_wait_simple = 1;
1606 ConfigFileEntry.short_motd = NO;
1607 ConfigFileEntry.ping_cookie = NO;
1608 ConfigFileEntry.no_oper_flood = NO; /* XXX */
1609 ConfigFileEntry.true_no_oper_flood = NO; /* XXX */
1610 ConfigFileEntry.oper_pass_resv = YES;
1611 ConfigFileEntry.glines = NO; /* XXX */
1612 ConfigFileEntry.gline_time = 12 * 3600; /* XXX */
1613 ConfigFileEntry.idletime = 0;
1614 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1615 ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1616 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG; /* XXX */
1617 ConfigFileEntry.oper_umodes = UMODE_LOCOPS | UMODE_SERVNOTICE |
1618 UMODE_OPERWALL | UMODE_WALLOP; /* XXX */
1619 DupString(ConfigFileEntry.servlink_path, SLPATH);
1620 #ifdef HAVE_LIBCRYPTO
1621 /* jdc -- This is our default value for a cipher. According to the
1622 * CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1623 * under all circumstances if cryptlinks are enabled. So,
1624 * this will be our default.
1625 *
1626 * NOTE: I apologise for the hard-coded value of "1" (BF/128).
1627 * This should be moved into a find_cipher() routine.
1628 */
1629 ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1630 #endif
1631 ConfigFileEntry.use_egd = NO;
1632 ConfigFileEntry.egdpool_path = NULL;
1633 #ifdef HAVE_LIBZ
1634 ConfigFileEntry.compression_level = 0;
1635 #endif
1636 ConfigFileEntry.throttle_time = 10;
1637 }
1638
1639 /* read_conf()
1640 *
1641 * inputs - file descriptor pointing to config file to use
1642 * output - None
1643 * side effects - Read configuration file.
1644 */
1645 static void
1646 read_conf(FBFILE *file)
1647 {
1648 scount = lineno = 0;
1649
1650 set_default_conf(); /* Set default values prior to conf parsing */
1651 ypass = 1;
1652 yyparse(); /* pick up the classes first */
1653
1654 fbrewind(file);
1655
1656 ypass = 2;
1657 yyparse(); /* Load the values from the conf */
1658 validate_conf(); /* Check to make sure some values are still okay. */
1659 /* Some global values are also loaded here. */
1660 check_class(); /* Make sure classes are valid */
1661 }
1662
1663 static void
1664 validate_conf(void)
1665 {
1666 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1667 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1668
1669 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1670 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1671
1672 if (ConfigFileEntry.servlink_path == NULL)
1673 DupString(ConfigFileEntry.servlink_path, SLPATH);
1674
1675 if (ServerInfo.network_name == NULL)
1676 DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1677
1678 if (ServerInfo.network_desc == NULL)
1679 DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1680
1681 if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1682 (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1683 ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1684 }
1685
1686 /* lookup_confhost()
1687 *
1688 * inputs - pointer to ConfItem
1689 * output - NONE
1690 * side effects - start DNS lookups of all hostnames in the conf
1691 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1692 */
1693 static void
1694 lookup_confhost(struct ConfItem *conf)
1695 {
1696 struct AccessItem *aconf;
1697 struct addrinfo hints, *res;
1698
1699 aconf = &conf->conf.AccessItem;
1700
1701 if (EmptyString(aconf->host) || EmptyString(aconf->user))
1702 {
1703 ilog(L_ERROR, "Host/server name error: (%s) (%s)",
1704 aconf->host, conf->name);
1705 return;
1706 }
1707
1708 if (strchr(aconf->host, '*') || strchr(aconf->host, '?'))
1709 return;
1710
1711 /* Do name lookup now on hostnames given and store the
1712 * ip numbers in conf structure.
1713 */
1714 memset(&hints, 0, sizeof(hints));
1715
1716 hints.ai_family = AF_UNSPEC;
1717 hints.ai_socktype = SOCK_STREAM;
1718
1719 /* Get us ready for a bind() and don't bother doing dns lookup */
1720 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1721
1722 if (irc_getaddrinfo(aconf->host, NULL, &hints, &res))
1723 {
1724 conf_dns_lookup(aconf);
1725 return;
1726 }
1727
1728 assert(res != NULL);
1729
1730 memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
1731 aconf->ipnum.ss_len = res->ai_addrlen;
1732 aconf->ipnum.ss.ss_family = res->ai_family;
1733 irc_freeaddrinfo(res);
1734 }
1735
1736 /* conf_connect_allowed()
1737 *
1738 * inputs - pointer to inaddr
1739 * - int type ipv4 or ipv6
1740 * output - BANNED or accepted
1741 * side effects - none
1742 */
1743 int
1744 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1745 {
1746 struct ip_entry *ip_found;
1747 struct AccessItem *aconf = find_dline_conf(addr, aftype);
1748
1749 /* DLINE exempt also gets you out of static limits/pacing... */
1750 if (aconf && (aconf->status & CONF_EXEMPTDLINE))
1751 return 0;
1752
1753 if (aconf != NULL)
1754 return BANNED_CLIENT;
1755
1756 ip_found = find_or_add_ip(addr);
1757 ip_found->last_attempt = CurrentTime;
1758
1759 if ((CurrentTime - ip_found->last_attempt) <
1760 ConfigFileEntry.throttle_time)
1761 return TOO_FAST;
1762
1763 return 0;
1764 }
1765
1766 /* oper_privs_as_string()
1767 *
1768 * inputs - pointer to client_p
1769 * output - pointer to static string showing oper privs
1770 * side effects - return as string, the oper privs as derived from port
1771 */
1772 static const struct oper_privs
1773 {
1774 const unsigned int oprivs;
1775 const unsigned int hidden;
1776 const unsigned char c;
1777 } flag_list[] = {
1778 { OPER_FLAG_ADMIN, OPER_FLAG_HIDDEN_ADMIN, 'A' },
1779 { OPER_FLAG_REMOTEBAN, 0, 'B' },
1780 { OPER_FLAG_DIE, 0, 'D' },
1781 { OPER_FLAG_GLINE, 0, 'G' },
1782 { OPER_FLAG_REHASH, 0, 'H' },
1783 { OPER_FLAG_K, 0, 'K' },
1784 { OPER_FLAG_OPERWALL, 0, 'L' },
1785 { OPER_FLAG_N, 0, 'N' },
1786 { OPER_FLAG_GLOBAL_KILL, 0, 'O' },
1787 { OPER_FLAG_REMOTE, 0, 'R' },
1788 { OPER_FLAG_OPER_SPY, 0, 'S' },
1789 { OPER_FLAG_UNKLINE, 0, 'U' },
1790 { OPER_FLAG_X, 0, 'X' },
1791 { 0, 0, '\0' }
1792 };
1793
1794 char *
1795 oper_privs_as_string(const unsigned int port)
1796 {
1797 static char privs_out[16];
1798 char *privs_ptr = privs_out;
1799 unsigned int i = 0;
1800
1801 for (; flag_list[i].oprivs; ++i)
1802 {
1803 if ((port & flag_list[i].oprivs) &&
1804 (port & flag_list[i].hidden) == 0)
1805 *privs_ptr++ = flag_list[i].c;
1806 else
1807 *privs_ptr++ = ToLowerTab[flag_list[i].c];
1808 }
1809
1810 *privs_ptr = '\0';
1811
1812 return privs_out;
1813 }
1814
1815 /*
1816 * Input: A client to find the active oper{} name for.
1817 * Output: The nick!user@host{oper} of the oper.
1818 * "oper" is server name for remote opers
1819 * Side effects: None.
1820 */
1821 char *
1822 get_oper_name(const struct Client *client_p)
1823 {
1824 /* +5 for !,@,{,} and null */
1825 static char buffer[NICKLEN+USERLEN+HOSTLEN+HOSTLEN+5];
1826
1827 if (MyConnect(client_p) && IsOper(client_p))
1828 ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1829 client_p->username, client_p->host,
1830 client_p->localClient->auth_oper);
1831 else
1832 ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
1833 client_p->username, client_p->host,
1834 client_p->servptr->name);
1835 return buffer;
1836 }
1837
1838 /* read_conf_files()
1839 *
1840 * inputs - cold start YES or NO
1841 * output - none
1842 * side effects - read all conf files needed, ircd.conf kline.conf etc.
1843 */
1844 void
1845 read_conf_files(int cold)
1846 {
1847 const char *filename;
1848 char chanmodes[32];
1849 char chanlimit[32];
1850
1851 filename = get_conf_name(CONF_TYPE);
1852
1853 /* We need to know the initial filename for the yyerror() to report
1854 FIXME: The full path is in conffilenamebuf first time since we
1855 dont know anything else
1856
1857 - Gozem 2002-07-21
1858 */
1859 strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1860
1861 if ((conf_fbfile_in = fbopen(filename, "r")) == NULL)
1862 {
1863 if (cold)
1864 {
1865 ilog(L_CRIT, "Unable to read configuration file '%s': %s",
1866 filename, strerror(errno));
1867 exit(-1);
1868 }
1869 else
1870 {
1871 sendto_realops_flags(UMODE_ALL, L_ALL,
1872 "Unable to read configuration file '%s': %s",
1873 filename, strerror(errno));
1874 return;
1875 }
1876 }
1877
1878 if (!cold)
1879 clear_out_old_conf();
1880
1881 read_conf(conf_fbfile_in);
1882 fbclose(conf_fbfile_in);
1883
1884 add_isupport("NETWORK", ServerInfo.network_name, -1);
1885 ircsprintf(chanmodes, "b%s%s:%d", ConfigChannel.use_except ? "e" : "",
1886 ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
1887 add_isupport("MAXLIST", chanmodes, -1);
1888 add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1889 if (ConfigChannel.disable_local_channels)
1890 add_isupport("CHANTYPES", "#", -1);
1891 else
1892 add_isupport("CHANTYPES", "#&", -1);
1893 ircsprintf(chanlimit, "%s:%d", ConfigChannel.disable_local_channels ? "#" : "#&",
1894 ConfigChannel.max_chans_per_user);
1895 add_isupport("CHANLIMIT", chanlimit, -1);
1896 ircsprintf(chanmodes, "%s%s%s", ConfigChannel.use_except ? "e" : "",
1897 ConfigChannel.use_invex ? "I" : "", "b,k,l,imnpst");
1898 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1899 if (ConfigChannel.use_except)
1900 add_isupport("EXCEPTS", "e", -1);
1901 if (ConfigChannel.use_invex)
1902 add_isupport("INVEX", "I", -1);
1903 add_isupport("CHANMODES", chanmodes, -1);
1904
1905 /*
1906 * message_locale may have changed. rebuild isupport since it relies
1907 * on strlen(form_str(RPL_ISUPPORT))
1908 */
1909 rebuild_isupport_message_line();
1910
1911 parse_conf_file(KLINE_TYPE, cold);
1912 parse_conf_file(RKLINE_TYPE, cold);
1913 parse_conf_file(DLINE_TYPE, cold);
1914 parse_conf_file(XLINE_TYPE, cold);
1915 parse_conf_file(RXLINE_TYPE, cold);
1916 parse_conf_file(NRESV_TYPE, cold);
1917 parse_conf_file(CRESV_TYPE, cold);
1918 }
1919
1920 /* parse_conf_file()
1921 *
1922 * inputs - type of conf file to parse
1923 * output - none
1924 * side effects - conf file for givenconf type is opened and read then parsed
1925 */
1926 static void
1927 parse_conf_file(int type, int cold)
1928 {
1929 FBFILE *file = NULL;
1930 const char *filename = get_conf_name(type);
1931
1932 if ((file = fbopen(filename, "r")) == NULL)
1933 {
1934 if (cold)
1935 ilog(L_ERROR, "Unable to read configuration file '%s': %s",
1936 filename, strerror(errno));
1937 else
1938 sendto_realops_flags(UMODE_ALL, L_ALL,
1939 "Unable to read configuration file '%s': %s",
1940 filename, strerror(errno));
1941 }
1942 else
1943 {
1944 parse_csv_file(file, type);
1945 fbclose(file);
1946 }
1947 }
1948
1949 /* clear_out_old_conf()
1950 *
1951 * inputs - none
1952 * output - none
1953 * side effects - Clear out the old configuration
1954 */
1955 static void
1956 clear_out_old_conf(void)
1957 {
1958 dlink_node *ptr = NULL, *next_ptr = NULL;
1959 struct ConfItem *conf;
1960 struct ClassItem *cltmp;
1961 struct MatchItem *match_item;
1962 dlink_list *free_items [] = {
1963 &server_items, &oconf_items, &hub_items, &leaf_items,
1964 &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
1965 &nresv_items, &cluster_items, &gdeny_items, NULL
1966 };
1967
1968 dlink_list ** iterator = free_items; /* C is dumb */
1969
1970 /* Only need to free anything allocated by yyparse() here.
1971 * Resetting structs, etc, is taken care of by set_default_conf().
1972 */
1973
1974 for (; *iterator != NULL; iterator++)
1975 {
1976 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1977 {
1978 conf = ptr->data;
1979 if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
1980 {
1981 match_item = &conf->conf.MatchItem;
1982 if ((match_item->ref_count <= 0))
1983 delete_conf_item(conf);
1984 {
1985 match_item->illegal = 1;
1986 dlinkDelete(&conf->node, *iterator);
1987 }
1988 }
1989 else
1990 {
1991 /* temporary (r)xlines are also on
1992 * the (r)xconf items list
1993 */
1994 if ((conf->flags & CONF_FLAGS_TEMPORARY) == 0)
1995 delete_conf_item(conf);
1996 }
1997 }
1998 }
1999
2000 /* don't delete the class table, rather mark all entries
2001 * for deletion. The table is cleaned up by check_class. - avalon
2002 */
2003 DLINK_FOREACH(ptr, class_items.head)
2004 {
2005 conf = ptr->data;
2006 cltmp = &conf->conf.ClassItem;
2007 if (ptr != class_items.tail) /* never mark the "default" class */
2008 MaxTotal(cltmp) = -1;
2009 }
2010
2011 clear_out_address_conf();
2012
2013 /* clean out module paths */
2014 #ifndef STATIC_MODULES
2015 mod_clear_paths();
2016 #endif
2017
2018 /* clean out ServerInfo */
2019 MyFree(ServerInfo.description);
2020 ServerInfo.description = NULL;
2021 MyFree(ServerInfo.network_name);
2022 ServerInfo.network_name = NULL;
2023 MyFree(ServerInfo.network_desc);
2024 ServerInfo.network_desc = NULL;
2025 MyFree(ConfigFileEntry.egdpool_path);
2026 ConfigFileEntry.egdpool_path = NULL;
2027 #ifdef HAVE_LIBCRYPTO
2028 if (ServerInfo.rsa_private_key != NULL)
2029 {
2030 RSA_free(ServerInfo.rsa_private_key);
2031 ServerInfo.rsa_private_key = NULL;
2032 }
2033
2034 MyFree(ServerInfo.rsa_private_key_file);
2035 ServerInfo.rsa_private_key_file = NULL;
2036 #endif
2037
2038 /* clean out old resvs from the conf */
2039 clear_conf_resv();
2040
2041 /* clean out AdminInfo */
2042 MyFree(AdminInfo.name);
2043 AdminInfo.name = NULL;
2044 MyFree(AdminInfo.email);
2045 AdminInfo.email = NULL;
2046 MyFree(AdminInfo.description);
2047 AdminInfo.description = NULL;
2048
2049 /* operator{} and class{} blocks are freed above */
2050 /* clean out listeners */
2051 close_listeners();
2052
2053 /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2054 * exempt{} and gecos{} blocks are freed above too
2055 */
2056
2057 /* clean out general */
2058 MyFree(ConfigFileEntry.servlink_path);
2059 ConfigFileEntry.servlink_path = NULL;
2060 #ifdef HAVE_LIBCRYPTO
2061 ConfigFileEntry.default_cipher_preference = NULL;
2062 #endif /* HAVE_LIBCRYPTO */
2063 delete_isupport("INVEX");
2064 delete_isupport("EXCEPTS");
2065 }
2066
2067 /* get_conf_name()
2068 *
2069 * inputs - type of conf file to return name of file for
2070 * output - pointer to filename for type of conf
2071 * side effects - none
2072 */
2073 const char *
2074 get_conf_name(ConfType type)
2075 {
2076 switch (type)
2077 {
2078 case CONF_TYPE:
2079 return ConfigFileEntry.configfile;
2080 break;
2081 case KLINE_TYPE:
2082 return ConfigFileEntry.klinefile;
2083 break;
2084 case RKLINE_TYPE:
2085 return ConfigFileEntry.rklinefile;
2086 break;
2087 case DLINE_TYPE:
2088 return ConfigFileEntry.dlinefile;
2089 break;
2090 case XLINE_TYPE:
2091 return ConfigFileEntry.xlinefile;
2092 break;
2093 case RXLINE_TYPE:
2094 return ConfigFileEntry.rxlinefile;
2095 break;
2096 case CRESV_TYPE:
2097 return ConfigFileEntry.cresvfile;
2098 break;
2099 case NRESV_TYPE:
2100 return ConfigFileEntry.nresvfile;
2101 break;
2102 case GLINE_TYPE:
2103 return ConfigFileEntry.glinefile;
2104 break;
2105
2106 default:
2107 return NULL; /* This should NEVER HAPPEN since we call this function
2108 only with the above values, this will cause us to core
2109 at some point if this happens so we know where it was */
2110 }
2111 }
2112
2113
2114 /* get_client_className()
2115 *
2116 * inputs - pointer to client struct
2117 * output - pointer to name of class
2118 * side effects - NONE
2119 */
2120 const char *
2121 get_client_className(struct Client *target_p)
2122 {
2123 assert(target_p && !IsMe(target_p));
2124
2125 if (target_p->localClient->class != NULL)
2126 {
2127 struct ConfItem *conf = target_p->localClient->class->conf_ptr;
2128 return conf->name;
2129 }
2130
2131 return "default";
2132 }
2133
2134 #define BAD_PING (-1)
2135 /* get_client_ping()
2136 *
2137 * inputs - pointer to client struct
2138 * - pointer to a variable that receives ping warning time
2139 * output - ping frequency
2140 * side effects - NONE
2141 */
2142 int
2143 get_client_ping(struct Client *target_p, int *pingwarn)
2144 {
2145 struct ClassItem *aclass;
2146 int ping;
2147
2148 if (target_p->localClient->class != NULL)
2149 {
2150 aclass = target_p->localClient->class;
2151 ping = PingFreq(aclass);
2152 *pingwarn = PingWarning(aclass);
2153 if (ping > 0)
2154 return ping;
2155 }
2156 else
2157 {
2158 *pingwarn = 0;
2159 return BAD_PING;
2160 }
2161
2162 *pingwarn = 0;
2163 return DEFAULT_PINGFREQUENCY;
2164 }
2165
2166 /* find_class()
2167 *
2168 * inputs - string name of class
2169 * output - corresponding Class pointer
2170 * side effects - NONE
2171 */
2172 struct ConfItem *
2173 find_class(const char *classname)
2174 {
2175 struct ConfItem *conf;
2176
2177 if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2178 return(conf);
2179
2180 return class_default;
2181 }
2182
2183 /* check_class()
2184 *
2185 * inputs - NONE
2186 * output - NONE
2187 * side effects -
2188 */
2189 void
2190 check_class(void)
2191 {
2192 dlink_node *ptr;
2193 dlink_node *next_ptr;
2194 struct ConfItem *conf;
2195 struct ClassItem *aclass;
2196
2197 DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2198 {
2199 conf = ptr->data;
2200 aclass = &conf->conf.ClassItem;
2201
2202 if (MaxTotal(aclass) < 0)
2203 {
2204 destroy_cidr_class(aclass);
2205 if (CurrUserCount(aclass) > 0)
2206 dlinkDelete(&conf->node, &class_items);
2207 else
2208 delete_conf_item(conf);
2209 }
2210 }
2211 }
2212
2213 /* init_class()
2214 *
2215 * inputs - NONE
2216 * output - NONE
2217 * side effects -
2218 */
2219 void
2220 init_class(void)
2221 {
2222 struct ClassItem *aclass;
2223
2224 class_default = make_conf_item(CLASS_TYPE);
2225 aclass = &class_default->conf.ClassItem;
2226 DupString(class_default->name, "default");
2227 ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
2228 PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2229 MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2230 MaxSendq(aclass) = DEFAULT_SENDQ;
2231 CurrUserCount(aclass) = 0;
2232
2233 client_check_cb = register_callback("check_client", check_client);
2234 }
2235
2236 /* get_sendq()
2237 *
2238 * inputs - pointer to client
2239 * output - sendq for this client as found from its class
2240 * side effects - NONE
2241 */
2242 unsigned long
2243 get_sendq(struct Client *client_p)
2244 {
2245 unsigned long sendq = DEFAULT_SENDQ;
2246 struct ClassItem *aclass;
2247
2248 if (client_p && !IsMe(client_p) && (client_p->localClient->class))
2249 {
2250 aclass = client_p->localClient->class;
2251 sendq = MaxSendq(aclass);
2252 }
2253 return sendq;
2254 }
2255
2256 /* conf_add_class_to_conf()
2257 *
2258 * inputs - pointer to config item
2259 * output - NONE
2260 * side effects - Add a class pointer to a conf
2261 */
2262 void
2263 conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
2264 {
2265 struct AccessItem *aconf;
2266 struct ClassItem *aclass;
2267
2268 aconf = &conf->conf.AccessItem;
2269
2270 if (class_name == NULL)
2271 {
2272 aconf->class_ptr = class_default;
2273 if (conf->type == CLIENT_TYPE)
2274 sendto_realops_flags(UMODE_ALL, L_ALL,
2275 "Warning *** Defaulting to default class for %s@%s",
2276 aconf->user, aconf->host);
2277 else
2278 sendto_realops_flags(UMODE_ALL, L_ALL,
2279 "Warning *** Defaulting to default class for %s",
2280 conf->name);
2281 }
2282 else
2283 {
2284 aconf->class_ptr = find_class(class_name);
2285 }
2286
2287 if (aconf->class_ptr == NULL)
2288 {
2289 if (conf->type == CLIENT_TYPE)
2290 sendto_realops_flags(UMODE_ALL, L_ALL,
2291 "Warning *** Defaulting to default class for %s@%s",
2292 aconf->user, aconf->host);
2293 else
2294 sendto_realops_flags(UMODE_ALL, L_ALL,
2295 "Warning *** Defaulting to default class for %s",
2296 conf->name);
2297 aconf->class_ptr = class_default;
2298 }
2299 else
2300 {
2301 aclass = &conf->conf.ClassItem;
2302 if (MaxTotal(aclass) < 0)
2303 {
2304 aconf->class_ptr = class_default;
2305 }
2306 }
2307 }
2308
2309 #define MAXCONFLINKS 150
2310
2311 /* conf_add_server()
2312 *
2313 * inputs - pointer to config item
2314 * - pointer to link count already on this conf
2315 * output - NONE
2316 * side effects - Add a connect block
2317 */
2318 int
2319 conf_add_server(struct ConfItem *conf, unsigned int lcount, const char *class_name)
2320 {
2321 struct AccessItem *aconf;
2322 char *orig_host;
2323
2324 aconf = &conf->conf.AccessItem;
2325
2326 conf_add_class_to_conf(conf, class_name);
2327
2328 if (lcount > MAXCONFLINKS || !aconf->host || !conf->name)
2329 {
2330 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
2331 ilog(L_WARN, "Bad connect block");
2332 return -1;
2333 }
2334
2335 if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
2336 {
2337 sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
2338 conf->name);
2339 ilog(L_WARN, "Bad connect block, host %s", conf->name);
2340 return -1;
2341 }
2342
2343 orig_host = aconf->host;
2344 split_nuh(orig_host, NULL, &aconf->user, &aconf->host);
2345 MyFree(orig_host);
2346 lookup_confhost(conf);
2347
2348 return 0;
2349 }
2350
2351 /* conf_add_d_conf()
2352 *
2353 * inputs - pointer to config item
2354 * output - NONE
2355 * side effects - Add a d/D line
2356 */
2357 void
2358 conf_add_d_conf(struct AccessItem *aconf)
2359 {
2360 if (aconf->host == NULL)
2361 return;
2362
2363 aconf->user = NULL;
2364
2365 /* XXX - Should 'd' ever be in the old conf? For new conf we don't
2366 * need this anyway, so I will disable it for now... -A1kmm
2367 */
2368 if (parse_netmask(aconf->host, NULL, NULL) == HM_HOST)
2369 {
2370 ilog(L_WARN, "Invalid Dline %s ignored", aconf->host);
2371 delete_conf_item(aconf->conf_ptr);
2372 }
2373 else
2374 {
2375 /* XXX ensure user is NULL */
2376 MyFree(aconf->user);
2377 aconf->user = NULL;
2378 add_conf_by_address(CONF_DLINE, aconf);
2379 }
2380 }
2381
2382 /* yyerror()
2383 *
2384 * inputs - message from parser
2385 * output - NONE
2386 * side effects - message to opers and log file entry is made
2387 */
2388 void
2389 yyerror(const char *msg)
2390 {
2391 char newlinebuf[IRCD_BUFSIZE];
2392
2393 if (ypass != 1)
2394 return;
2395
2396 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
2397 sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
2398 conffilebuf, lineno + 1, msg, newlinebuf);
2399 ilog(L_WARN, "\"%s\", line %u: %s: %s",
2400 conffilebuf, lineno + 1, msg, newlinebuf);
2401 }
2402
2403 int
2404 conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
2405 {
2406 if (fbgets(lbuf, max_size, fb) == NULL)
2407 return 0;
2408
2409 return strlen(lbuf);
2410 }
2411
2412 int
2413 conf_yy_fatal_error(const char *msg)
2414 {
2415 return 0;
2416 }
2417
2418 /* match_conf_password()
2419 *
2420 * inputs - pointer to given password
2421 * - pointer to Conf
2422 * output - 1 or 0 if match
2423 * side effects - none
2424 */
2425 int
2426 match_conf_password(const char *password, const struct AccessItem *aconf)
2427 {
2428 const char *encr = NULL;
2429
2430 if (password == NULL || aconf->passwd == NULL)
2431 return 0;
2432
2433 if (aconf->flags & CONF_FLAGS_ENCRYPTED)
2434 {
2435 /* use first two chars of the password they send in as salt */
2436 /* If the password in the conf is MD5, and ircd is linked
2437 * to scrypt on FreeBSD, or the standard crypt library on
2438 * glibc Linux, then this code will work fine on generating
2439 * the proper encrypted hash for comparison.
2440 */
2441 if (*aconf->passwd)
2442 encr = crypt(password, aconf->passwd);
2443 else
2444 encr = "";
2445 }
2446 else
2447 encr = password;
2448
2449 return !strcmp(encr, aconf->passwd);
2450 }
2451
2452
2453 /*
2454 * split_nuh
2455 *
2456 * inputs - pointer to original mask (modified in place)
2457 * - pointer to pointer where nick should go
2458 * - pointer to pointer where user should go
2459 * - pointer to pointer where host should go
2460 * output - NONE
2461 * side effects - mask is modified in place
2462 * If nick pointer is NULL, ignore writing to it
2463 * this allows us to use this function elsewhere.
2464 *
2465 * mask nick user host
2466 * ---------------------- ------- ------- ------
2467 * Dianora!db@db.net Dianora db db.net
2468 * Dianora Dianora * *
2469 * db.net * * db.net
2470 * OR if nick pointer is NULL
2471 * Dianora - * Dianora
2472 * Dianora! Dianora * *
2473 * Dianora!@ Dianora * *
2474 * Dianora!db Dianora db *
2475 * Dianora!@db.net Dianora * db.net
2476 * db@db.net * db db.net
2477 * !@ * * *
2478 * @ * * *
2479 * ! * * *
2480 */
2481
2482 void
2483 split_nuh(char *mask, char **nick, char **user, char **host)
2484 {
2485 char *p = NULL, *q = NULL;
2486
2487 if ((p = strchr(mask, '!')) != NULL)
2488 {
2489 *p = '\0';
2490 if (nick != NULL)
2491 {
2492 if (*mask != '\0')
2493 *nick = xstrldup(mask, NICKLEN);
2494 else
2495 DupString(*nick, "*");
2496 }
2497
2498 if ((q = strchr(++p, '@')) != NULL)
2499 {
2500 *q = '\0';
2501
2502 if (*p != '\0')
2503 *user = xstrldup(p, USERLEN+1);
2504 else
2505 DupString(*user, "*");
2506
2507 if (*++q != '\0')
2508 *host = xstrldup(q, HOSTLEN+1);
2509 else
2510 DupString(*host, "*");
2511 }
2512 else
2513 {
2514 if (*p != '\0')
2515 *user = xstrldup(p, USERLEN+1);
2516 else
2517 DupString(*user, "*");
2518
2519 DupString(*host, "*");
2520 }
2521 }
2522 else /* No ! found so lets look for a user@host */
2523 {
2524 if ((p = strchr(mask, '@')) != NULL) /* if found a @ */
2525 {
2526 if (nick != NULL)
2527 DupString(*nick, "*");
2528 *p = '\0';
2529
2530 if (*mask != '\0')
2531 *user = xstrldup(mask, USERLEN+1);
2532 else
2533 DupString(*user, "*");
2534
2535 if (*++p != '\0')
2536 *host = xstrldup(p, HOSTLEN+1);
2537 else
2538 DupString(*host, "*");
2539 }
2540 else /* no @ found */
2541 {
2542 if (nick != NULL)
2543 {
2544 if (strpbrk(mask, ".:"))
2545 {
2546 DupString(*nick, "*");
2547 *host = xstrldup(mask, HOSTLEN+1);
2548 }
2549 else
2550 {
2551 *nick = xstrldup(mask, NICKLEN);
2552 DupString(*host, "*");
2553 }
2554
2555 DupString(*user, "*");
2556 }
2557 else
2558 {
2559 DupString(*user, "*");
2560 *host = xstrldup(mask, HOSTLEN+1);
2561 }
2562 }
2563 }
2564 }
2565
2566 /*
2567 * flags_to_ascii
2568 *
2569 * inputs - flags is a bitmask
2570 * - pointer to table of ascii letters corresponding
2571 * to each bit
2572 * - flag 1 for convert ToLower if bit missing
2573 * 0 if ignore.
2574 * output - none
2575 * side effects - string pointed to by p has bitmap chars written to it
2576 */
2577 static void
2578 flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
2579 int lowerit)
2580 {
2581 unsigned int mask = 1;
2582 int i = 0;
2583
2584 for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
2585 {
2586 if (flags & mask)
2587 *p++ = bit_table[i];
2588 else if(lowerit)
2589 *p++ = ToLower(bit_table[i]);
2590 }
2591 *p = '\0';
2592 }
2593
2594 /*
2595 * cidr_limit_reached
2596 *
2597 * inputs - int flag allowing exemption of limits
2598 * - pointer to the ip to be added
2599 * - pointer to the class
2600 * output - non zero if limit reached
2601 * 0 if limit not reached
2602 * side effects -
2603 */
2604 static int
2605 cidr_limit_reached(int exempt,
2606 struct irc_ssaddr *ip, struct ClassItem *aclass)
2607 {
2608 dlink_node *ptr = NULL;
2609 struct CidrItem *cidr;
2610
2611 if (NumberPerCidr(aclass) <= 0)
2612 return 0;
2613
2614 if (ip->ss.ss_family == AF_INET)
2615 {
2616 if (CidrBitlenIPV4(aclass) <= 0)
2617 return 0;
2618
2619 DLINK_FOREACH(ptr, aclass->list_ipv4.head)
2620 {
2621 cidr = ptr->data;
2622 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
2623 {
2624 if (!exempt && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
2625 return -1;
2626 cidr->number_on_this_cidr++;
2627 return 0;
2628 }
2629 }
2630 cidr = MyMalloc(sizeof(struct CidrItem));
2631 cidr->number_on_this_cidr = 1;
2632 cidr->mask = *ip;
2633 mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
2634 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
2635 }
2636 #ifdef IPV6
2637 else if (CidrBitlenIPV6(aclass) > 0)
2638 {
2639 DLINK_FOREACH(ptr, aclass->list_ipv6.head)
2640 {
2641 cidr = ptr->data;
2642 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
2643 {
2644 if (!exempt && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
2645 return -1;
2646 cidr->number_on_this_cidr++;
2647 return 0;
2648 }
2649 }
2650 cidr = MyMalloc(sizeof(struct CidrItem));
2651 cidr->number_on_this_cidr = 1;
2652 cidr->mask = *ip;
2653 mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
2654 dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
2655 }
2656 #endif
2657 return 0;
2658 }
2659
2660 /*
2661 * remove_from_cidr_check
2662 *
2663 * inputs - pointer to the ip to be removed
2664 * - pointer to the class
2665 * output - NONE
2666 * side effects -
2667 */
2668 static void
2669 remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
2670 {
2671 dlink_node *ptr = NULL;
2672 dlink_node *next_ptr = NULL;
2673 struct CidrItem *cidr;
2674
2675 if (NumberPerCidr(aclass) == 0)
2676 return;
2677
2678 if (ip->ss.ss_family == AF_INET)
2679 {
2680 if (CidrBitlenIPV4(aclass) <= 0)
2681 return;
2682
2683 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
2684 {
2685 cidr = ptr->data;
2686 if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
2687 {
2688 cidr->number_on_this_cidr--;
2689 if (cidr->number_on_this_cidr == 0)
2690 {
2691 dlinkDelete(ptr, &aclass->list_ipv4);
2692 MyFree(cidr);
2693 return;
2694 }
2695 }
2696 }
2697 }
2698 #ifdef IPV6
2699 else if (CidrBitlenIPV6(aclass) > 0)
2700 {
2701 DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
2702 {
2703 cidr = ptr->data;
2704 if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
2705 {
2706 cidr->number_on_this_cidr--;
2707 if (cidr->number_on_this_cidr == 0)
2708 {
2709 dlinkDelete(ptr, &aclass->list_ipv6);
2710 MyFree(cidr);
2711 return;
2712 }
2713 }
2714 }
2715 }
2716 #endif
2717 }
2718
2719 static void
2720 rebuild_cidr_list(int aftype, struct ClassItem *oldcl, struct ClassItem *newcl,
2721 dlink_list *old_list, dlink_list *new_list, int changed)
2722 {
2723 dlink_node *ptr;
2724 struct Client *client_p;
2725
2726 if (!changed)
2727 {
2728 *new_list = *old_list;
2729 old_list->head = old_list->tail = NULL;
2730 old_list->length = 0;
2731 return;
2732 }
2733
2734 DLINK_FOREACH(ptr, local_client_list.head)
2735 {
2736 client_p = ptr->data;
2737 if (client_p->localClient->aftype != aftype)
2738 continue;
2739 if (client_p->localClient->class == NULL)
2740 continue;
2741
2742 if (client_p->localClient->class == oldcl)
2743 cidr_limit_reached(1, &client_p->localClient->ip, newcl);
2744 }
2745 }
2746
2747 /*
2748 * rebuild_cidr_class
2749 *
2750 * inputs - pointer to old conf
2751 * - pointer to new_class
2752 * output - none
2753 * side effects - rebuilds the class link list of cidr blocks
2754 */
2755 void
2756 rebuild_cidr_class(struct ClassItem *old_class, struct ClassItem *new_class)
2757 {
2758 if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
2759 {
2760 if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
2761 rebuild_cidr_list(AF_INET, old_class, new_class,
2762 &old_class->list_ipv4, &new_class->list_ipv4,
2763 CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
2764
2765 #ifdef IPV6
2766 if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
2767 rebuild_cidr_list(AF_INET6, old_class, new_class,
2768 &old_class->list_ipv6, &new_class->list_ipv6,
2769 CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
2770 #endif
2771 }
2772
2773 destroy_cidr_class(old_class);
2774 }
2775
2776 /*
2777 * destroy_cidr_list
2778 *
2779 * inputs - pointer to class dlink list of cidr blocks
2780 * output - none
2781 * side effects - completely destroys the class link list of cidr blocks
2782 */
2783 static void
2784 destroy_cidr_list(dlink_list *list)
2785 {
2786 dlink_node *ptr = NULL;
2787 dlink_node *next_ptr = NULL;
2788 struct CidrItem *cidr;
2789
2790 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
2791 {
2792 cidr = ptr->data;
2793 dlinkDelete(ptr, list);
2794 MyFree(cidr);
2795 }
2796 }
2797
2798 /*
2799 * destroy_cidr_class
2800 *
2801 * inputs - pointer to class
2802 * output - none
2803 * side effects - completely destroys the class link list of cidr blocks
2804 */
2805 static void
2806 destroy_cidr_class(struct ClassItem *aclass)
2807 {
2808 destroy_cidr_list(&aclass->list_ipv4);
2809 destroy_cidr_list(&aclass->list_ipv6);
2810 }
2811
2812

Properties

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