ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 876
Committed: Wed Oct 24 21:51:21 2007 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100887 byte(s)
Log Message:
Backported WATCH

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

Properties

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