ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1072
Committed: Wed Feb 17 22:58:23 2010 UTC (15 years, 6 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99532 byte(s)
Log Message:
- remove old dot_in_ip6_addr configuration option. this is now obsolete.

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

Properties

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