ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 815
Committed: Sun Sep 10 17:35:18 2006 UTC (17 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100782 byte(s)
Log Message:
- Fixed bug in find_conf_exact() which sometimes made CHALLENGE useless

File Contents

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

Properties

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