ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 992
Committed: Mon Aug 17 19:19:16 2009 UTC (16 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100185 byte(s)
Log Message:
- fix possible auth/dns related memleaks

File Contents

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

Properties

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