/[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 673 - (hide annotations)
Tue Jun 13 07:38:50 2006 UTC (13 years, 5 months ago) by michael
Original Path: ircd-hybrid-7.2/src/s_conf.c
File MIME type: text/x-chdr
File size: 100886 byte(s)
- check_classes(): Only call destroy_cidr_class() on a class that is ready
  for deletion, otherwise the current cidr count would become unadjusted in
  case a disabled class gets re-enabled later on.

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