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

Annotation of /ircd-hybrid-8/src/s_conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 632 - (hide annotations)
Thu Jun 1 10:53:00 2006 UTC (13 years, 6 months ago) by michael
Original Path: ircd-hybrid-7.2/src/s_conf.c
File MIME type: text/x-chdr
File size: 101434 byte(s)
- Added channel::disable_fake_channels which disallows creation of channels
  that have ascii 2, 3, 31 and 160 in their names.
- Minor improvements and cleanups to channel name validation routines
  backported from 7.3

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