ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1119
Committed: Fri Jan 7 22:01:47 2011 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99282 byte(s)
Log Message:
- removed HUB capability, which was a LL leftover

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

Properties

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