ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1118
Committed: Thu Jan 6 13:39:10 2011 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/src/s_conf.c
File size: 99463 byte(s)
Log Message:
- cleanup and sanitize m_server.c. remove hostmasking. Improve TS6 suppport

File Contents

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

Properties

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