ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1121
Committed: Sun Jan 9 11:03:03 2011 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99203 byte(s)
Log Message:
- removed all instances of STATIC_MODULES since we don't have
  static modules anymore
- removed m_mkpasswd module from contrib

File Contents

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

Properties

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