ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 672
Committed: Tue Jun 13 07:28:30 2006 UTC (19 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100897 byte(s)
Log Message:
- Fixed possible core introduced by previous commit
- Put some asserts into detach_conf()

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     aconf = (struct AccessItem *)map_to_conf(conf);
1477     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     if (!match(aconf->host, host) || !match(aconf->user,user)
1488     || irccmp(conf->name, name) )
1489     continue;
1490     if (type == OPER_TYPE)
1491     {
1492     struct ClassItem *aclass;
1493    
1494     aclass = (struct ClassItem *)aconf->class_ptr;
1495     if (aconf->clients < MaxTotal(aclass))
1496     return conf;
1497     else
1498     continue;
1499     }
1500     else
1501     return conf;
1502     }
1503     return NULL;
1504     }
1505    
1506     /* find_conf_name()
1507     *
1508     * inputs - pointer to conf link list to search
1509     * - pointer to name to find
1510     * - int mask of type of conf to find
1511     * output - NULL or pointer to conf found
1512     * side effects - find a conf entry which matches the name
1513     * and has the given mask.
1514     */
1515     struct ConfItem *
1516     find_conf_name(dlink_list *list, const char *name, ConfType type)
1517     {
1518     dlink_node *ptr;
1519     struct ConfItem* conf;
1520    
1521     DLINK_FOREACH(ptr, list->head)
1522     {
1523     conf = ptr->data;
1524    
1525     if (conf->type == type)
1526     {
1527     if (conf->name && (irccmp(conf->name, name) == 0 ||
1528     match(conf->name, name)))
1529     return conf;
1530     }
1531     }
1532    
1533     return NULL;
1534     }
1535    
1536     /* map_to_list()
1537     *
1538     * inputs - ConfType conf
1539     * output - pointer to dlink_list to use
1540     * side effects - none
1541     */
1542     static dlink_list *
1543     map_to_list(ConfType type)
1544     {
1545     switch(type)
1546     {
1547     case RXLINE_TYPE:
1548     return(&rxconf_items);
1549     break;
1550     case XLINE_TYPE:
1551     return(&xconf_items);
1552     break;
1553     case ULINE_TYPE:
1554     return(&uconf_items);
1555     break;
1556     case NRESV_TYPE:
1557     return(&nresv_items);
1558     break;
1559     case OPER_TYPE:
1560     return(&oconf_items);
1561     break;
1562     case CLASS_TYPE:
1563     return(&class_items);
1564     break;
1565     case SERVER_TYPE:
1566     return(&server_items);
1567     break;
1568     case CLUSTER_TYPE:
1569     return(&cluster_items);
1570     break;
1571     case CONF_TYPE:
1572     case GLINE_TYPE:
1573     case KLINE_TYPE:
1574     case DLINE_TYPE:
1575     case CRESV_TYPE:
1576     default:
1577     return NULL;
1578     }
1579     }
1580    
1581     /* find_matching_name_conf()
1582     *
1583     * inputs - type of link list to look in
1584     * - pointer to name string to find
1585     * - pointer to user
1586     * - pointer to host
1587     * - optional action to match on as well
1588     * output - NULL or pointer to found struct MatchItem
1589     * side effects - looks for a match on name field
1590     */
1591     struct ConfItem *
1592     find_matching_name_conf(ConfType type, const char *name, const char *user,
1593     const char *host, int action)
1594     {
1595     dlink_node *ptr=NULL;
1596     struct ConfItem *conf=NULL;
1597     struct AccessItem *aconf=NULL;
1598     struct MatchItem *match_item=NULL;
1599     dlink_list *list_p = map_to_list(type);
1600    
1601     switch (type)
1602     {
1603     case RXLINE_TYPE:
1604     DLINK_FOREACH(ptr, list_p->head)
1605     {
1606     conf = ptr->data;
1607     assert(conf->regexpname);
1608    
1609     if (!ircd_pcre_exec(conf->regexpname, name))
1610     return conf;
1611     }
1612     break;
1613    
1614     case XLINE_TYPE:
1615     case ULINE_TYPE:
1616     case NRESV_TYPE:
1617     DLINK_FOREACH(ptr, list_p->head)
1618     {
1619     conf = ptr->data;
1620    
1621     match_item = map_to_conf(conf);
1622     if (EmptyString(conf->name))
1623     continue;
1624     if ((name != NULL) && match_esc(conf->name, name))
1625     {
1626     if ((user == NULL && (host == NULL)))
1627     return conf;
1628     if ((match_item->action & action) != action)
1629     continue;
1630     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1631     return conf;
1632     if (match(match_item->user, user) && match(match_item->host, host))
1633     return conf;
1634     }
1635     }
1636     break;
1637    
1638     case SERVER_TYPE:
1639     DLINK_FOREACH(ptr, list_p->head)
1640     {
1641     conf = ptr->data;
1642     aconf = map_to_conf(conf);
1643    
1644     if ((name != NULL) && match_esc(name, conf->name))
1645     return conf;
1646     else if ((host != NULL) && match_esc(host, aconf->host))
1647     return conf;
1648     }
1649     break;
1650    
1651     default:
1652     break;
1653     }
1654     return NULL;
1655     }
1656    
1657     /* find_exact_name_conf()
1658     *
1659     * inputs - type of link list to look in
1660     * - pointer to name string to find
1661     * - pointer to user
1662     * - pointer to host
1663     * output - NULL or pointer to found struct MatchItem
1664     * side effects - looks for an exact match on name field
1665     */
1666     struct ConfItem *
1667     find_exact_name_conf(ConfType type, const char *name,
1668     const char *user, const char *host)
1669     {
1670     dlink_node *ptr = NULL;
1671     struct AccessItem *aconf;
1672     struct ConfItem *conf;
1673     struct MatchItem *match_item;
1674     dlink_list *list_p;
1675    
1676     list_p = map_to_list(type);
1677    
1678     switch(type)
1679     {
1680     case RXLINE_TYPE:
1681     case XLINE_TYPE:
1682     case ULINE_TYPE:
1683     case NRESV_TYPE:
1684    
1685     DLINK_FOREACH(ptr, list_p->head)
1686     {
1687     conf = ptr->data;
1688     match_item = (struct MatchItem *)map_to_conf(conf);
1689     if (EmptyString(conf->name))
1690     continue;
1691    
1692     if (irccmp(conf->name, name) == 0)
1693     {
1694     if ((user == NULL && (host == NULL)))
1695     return (conf);
1696     if (EmptyString(match_item->user) || EmptyString(match_item->host))
1697     return (conf);
1698     if (match(match_item->user, user) && match(match_item->host, host))
1699     return (conf);
1700     }
1701     }
1702     break;
1703    
1704     case OPER_TYPE:
1705     DLINK_FOREACH(ptr, list_p->head)
1706     {
1707     conf = ptr->data;
1708     aconf = (struct AccessItem *)map_to_conf(conf);
1709     if (EmptyString(conf->name))
1710     continue;
1711    
1712     if (irccmp(conf->name, name) == 0)
1713     {
1714     if ((user == NULL && (host == NULL)))
1715     return (conf);
1716     if (EmptyString(aconf->user) || EmptyString(aconf->host))
1717     return (conf);
1718     if (match(aconf->user, user) && match(aconf->host, host))
1719     return (conf);
1720     }
1721     }
1722     break;
1723    
1724     case SERVER_TYPE:
1725     DLINK_FOREACH(ptr, list_p->head)
1726     {
1727     conf = ptr->data;
1728     aconf = (struct AccessItem *)map_to_conf(conf);
1729     if (EmptyString(conf->name))
1730     continue;
1731    
1732     if (name == NULL)
1733     {
1734     if (EmptyString(aconf->host))
1735     continue;
1736     if (irccmp(aconf->host, host) == 0)
1737     return(conf);
1738     }
1739     else if (irccmp(conf->name, name) == 0)
1740     {
1741     return (conf);
1742     }
1743     }
1744     break;
1745    
1746     case CLASS_TYPE:
1747     DLINK_FOREACH(ptr, list_p->head)
1748     {
1749     conf = ptr->data;
1750     if (EmptyString(conf->name))
1751     continue;
1752    
1753     if (irccmp(conf->name, name) == 0)
1754     return (conf);
1755     }
1756     break;
1757    
1758     default:
1759     break;
1760     }
1761     return(NULL);
1762     }
1763    
1764     /* rehash()
1765     *
1766     * Actual REHASH service routine. Called with sig == 0 if it has been called
1767     * as a result of an operator issuing this command, else assume it has been
1768     * called as a result of the server receiving a HUP signal.
1769     */
1770     int
1771     rehash(int sig)
1772     {
1773     if (sig != 0)
1774     sendto_realops_flags(UMODE_ALL, L_ALL,
1775     "Got signal SIGHUP, reloading ircd.conf file");
1776    
1777     #ifndef _WIN32
1778     restart_resolver();
1779     #endif
1780     /* don't close listeners until we know we can go ahead with the rehash */
1781    
1782     /* Check to see if we magically got(or lost) IPv6 support */
1783     check_can_use_v6();
1784    
1785     read_conf_files(0);
1786    
1787     if (ServerInfo.description != NULL)
1788     strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1789    
1790     #ifndef STATIC_MODULES
1791     load_conf_modules();
1792     #endif
1793    
1794     flush_deleted_I_P();
1795    
1796     rehashed_klines = 1;
1797    
1798     if (ConfigLoggingEntry.use_logging)
1799     reopen_log(logFileName);
1800    
1801     return(0);
1802     }
1803    
1804     /* set_default_conf()
1805     *
1806     * inputs - NONE
1807     * output - NONE
1808     * side effects - Set default values here.
1809     * This is called **PRIOR** to parsing the
1810     * configuration file. If you want to do some validation
1811     * of values later, put them in validate_conf().
1812     */
1813     static void
1814     set_default_conf(void)
1815     {
1816     /* verify init_class() ran, this should be an unnecessary check
1817     * but its not much work.
1818     */
1819     assert(class_default == (struct ConfItem *) class_items.tail->data);
1820    
1821     #ifdef HAVE_LIBCRYPTO
1822     ServerInfo.rsa_private_key = NULL;
1823     ServerInfo.rsa_private_key_file = NULL;
1824     #endif
1825    
1826     /* ServerInfo.name is not rehashable */
1827     /* ServerInfo.name = ServerInfo.name; */
1828     ServerInfo.description = NULL;
1829     DupString(ServerInfo.network_name, NETWORK_NAME_DEFAULT);
1830     DupString(ServerInfo.network_desc, NETWORK_DESC_DEFAULT);
1831    
1832     memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1833     ServerInfo.specific_ipv4_vhost = 0;
1834     memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1835     ServerInfo.specific_ipv6_vhost = 0;
1836    
1837     ServerInfo.max_clients = MAXCLIENTS_MAX;
1838     /* Don't reset hub, as that will break lazylinks */
1839     /* ServerInfo.hub = NO; */
1840     ServerInfo.dns_host.sin_addr.s_addr = 0;
1841     ServerInfo.dns_host.sin_port = 0;
1842     AdminInfo.name = NULL;
1843     AdminInfo.email = NULL;
1844     AdminInfo.description = NULL;
1845    
1846     set_log_level(L_NOTICE);
1847     ConfigLoggingEntry.use_logging = 1;
1848     ConfigLoggingEntry.operlog[0] = '\0';
1849     ConfigLoggingEntry.userlog[0] = '\0';
1850     ConfigLoggingEntry.klinelog[0] = '\0';
1851     ConfigLoggingEntry.glinelog[0] = '\0';
1852     ConfigLoggingEntry.killlog[0] = '\0';
1853     ConfigLoggingEntry.operspylog[0] = '\0';
1854     ConfigLoggingEntry.ioerrlog[0] = '\0';
1855     ConfigLoggingEntry.failed_operlog[0] = '\0';
1856    
1857 michael 632 ConfigChannel.disable_fake_channels = NO;
1858 adx 30 ConfigChannel.restrict_channels = NO;
1859     ConfigChannel.disable_local_channels = NO;
1860     ConfigChannel.use_invex = YES;
1861     ConfigChannel.use_except = YES;
1862     ConfigChannel.use_knock = YES;
1863     ConfigChannel.knock_delay = 300;
1864     ConfigChannel.knock_delay_channel = 60;
1865     ConfigChannel.max_chans_per_user = 15;
1866     ConfigChannel.quiet_on_ban = YES;
1867     ConfigChannel.max_bans = 25;
1868     ConfigChannel.default_split_user_count = 0;
1869     ConfigChannel.default_split_server_count = 0;
1870     ConfigChannel.no_join_on_split = NO;
1871     ConfigChannel.no_create_on_split = NO;
1872     ConfigChannel.burst_topicwho = YES;
1873    
1874     ConfigServerHide.flatten_links = NO;
1875     ConfigServerHide.links_delay = 300;
1876     ConfigServerHide.hidden = NO;
1877     ConfigServerHide.disable_hidden = NO;
1878     ConfigServerHide.hide_servers = NO;
1879     DupString(ConfigServerHide.hidden_name, NETWORK_NAME_DEFAULT);
1880     ConfigServerHide.hide_server_ips = NO;
1881    
1882     ConfigFileEntry.gline_min_cidr = 16;
1883     ConfigFileEntry.gline_min_cidr6 = 48;
1884     ConfigFileEntry.invisible_on_connect = YES;
1885     ConfigFileEntry.burst_away = NO;
1886     ConfigFileEntry.use_whois_actually = YES;
1887     ConfigFileEntry.tkline_expire_notices = YES;
1888     ConfigFileEntry.hide_spoof_ips = YES;
1889     ConfigFileEntry.ignore_bogus_ts = NO;
1890     ConfigFileEntry.disable_auth = NO;
1891     ConfigFileEntry.disable_remote = NO;
1892     ConfigFileEntry.kill_chase_time_limit = 90;
1893     ConfigFileEntry.default_floodcount = 8; /* XXX */
1894     ConfigFileEntry.failed_oper_notice = YES;
1895     ConfigFileEntry.dots_in_ident = 0; /* XXX */
1896     ConfigFileEntry.dot_in_ip6_addr = YES;
1897     ConfigFileEntry.min_nonwildcard = 4;
1898     ConfigFileEntry.min_nonwildcard_simple = 3;
1899     ConfigFileEntry.max_accept = 20;
1900     ConfigFileEntry.anti_nick_flood = NO; /* XXX */
1901     ConfigFileEntry.max_nick_time = 20;
1902     ConfigFileEntry.max_nick_changes = 5;
1903     ConfigFileEntry.anti_spam_exit_message_time = 0; /* XXX */
1904     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1905     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT; /* XXX */
1906     ConfigFileEntry.kline_with_reason = YES;
1907     ConfigFileEntry.kline_reason = NULL;
1908     ConfigFileEntry.warn_no_nline = YES;
1909     ConfigFileEntry.stats_o_oper_only = NO; /* XXX */
1910     ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1911     ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1912     ConfigFileEntry.stats_P_oper_only = NO;
1913     ConfigFileEntry.caller_id_wait = 60;
1914     ConfigFileEntry.opers_bypass_callerid = NO;
1915     ConfigFileEntry.pace_wait = 10;
1916     ConfigFileEntry.pace_wait_simple = 1;
1917     ConfigFileEntry.short_motd = NO;
1918     ConfigFileEntry.ping_cookie = NO;
1919     ConfigFileEntry.no_oper_flood = NO; /* XXX */
1920     ConfigFileEntry.true_no_oper_flood = NO; /* XXX */
1921     ConfigFileEntry.oper_pass_resv = YES;
1922     ConfigFileEntry.glines = NO; /* XXX */
1923     ConfigFileEntry.gline_time = 12 * 3600; /* XXX */
1924     ConfigFileEntry.idletime = 0;
1925     ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1926     ConfigFileEntry.client_flood = CLIENT_FLOOD_DEFAULT;
1927     ConfigFileEntry.oper_only_umodes = UMODE_DEBUG; /* XXX */
1928 adx 264 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1929 adx 30 UMODE_OPERWALL | UMODE_WALLOP; /* XXX */
1930     DupString(ConfigFileEntry.servlink_path, SLPATH);
1931     #ifdef HAVE_LIBCRYPTO
1932     /* jdc -- This is our default value for a cipher. According to the
1933     * CRYPTLINK document (doc/cryptlink.txt), BF/128 must be supported
1934     * under all circumstances if cryptlinks are enabled. So,
1935     * this will be our default.
1936     *
1937     * NOTE: I apologise for the hard-coded value of "1" (BF/128).
1938     * This should be moved into a find_cipher() routine.
1939     */
1940     ConfigFileEntry.default_cipher_preference = &CipherTable[1];
1941     #endif
1942     ConfigFileEntry.use_egd = NO;
1943     ConfigFileEntry.egdpool_path = NULL;
1944     #ifdef HAVE_LIBZ
1945     ConfigFileEntry.compression_level = 0;
1946     #endif
1947     ConfigFileEntry.throttle_time = 10;
1948     }
1949    
1950     /* read_conf()
1951     *
1952     * inputs - file descriptor pointing to config file to use
1953     * output - None
1954     * side effects - Read configuration file.
1955     */
1956     static void
1957     read_conf(FBFILE *file)
1958     {
1959 michael 593 lineno = 0;
1960 adx 30
1961     set_default_conf(); /* Set default values prior to conf parsing */
1962     ypass = 1;
1963     yyparse(); /* pick up the classes first */
1964    
1965     fbrewind(file);
1966    
1967     ypass = 2;
1968     yyparse(); /* Load the values from the conf */
1969     validate_conf(); /* Check to make sure some values are still okay. */
1970     /* Some global values are also loaded here. */
1971     check_class(); /* Make sure classes are valid */
1972     }
1973    
1974     static void
1975     validate_conf(void)
1976     {
1977     if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1978     ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1979    
1980     if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1981     ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1982    
1983     if (ConfigFileEntry.servlink_path == NULL)
1984     DupString(ConfigFileEntry.servlink_path, SLPATH);
1985    
1986     if (ServerInfo.network_name == NULL)
1987     DupString(ServerInfo.network_name,NETWORK_NAME_DEFAULT);
1988    
1989     if (ServerInfo.network_desc == NULL)
1990     DupString(ServerInfo.network_desc,NETWORK_DESC_DEFAULT);
1991    
1992     if ((ConfigFileEntry.client_flood < CLIENT_FLOOD_MIN) ||
1993     (ConfigFileEntry.client_flood > CLIENT_FLOOD_MAX))
1994     ConfigFileEntry.client_flood = CLIENT_FLOOD_MAX;
1995     }
1996    
1997     /* lookup_confhost()
1998     *
1999     * start DNS lookups of all hostnames in the conf
2000     * line and convert an IP addresses in a.b.c.d number for to IP#s.
2001     */
2002     static void
2003     lookup_confhost(struct ConfItem *conf)
2004     {
2005     struct AccessItem *aconf;
2006     struct addrinfo hints, *res;
2007    
2008     aconf = map_to_conf(conf);
2009    
2010     if (EmptyString(aconf->host) ||
2011     EmptyString(aconf->user))
2012     {
2013     ilog(L_ERROR, "Host/server name error: (%s) (%s)",
2014     aconf->host, conf->name);
2015     return;
2016     }
2017    
2018     if (strchr(aconf->host, '*') ||
2019     strchr(aconf->host, '?'))
2020     return;
2021    
2022     /* Do name lookup now on hostnames given and store the
2023     * ip numbers in conf structure.
2024     */
2025     memset(&hints, 0, sizeof(hints));
2026    
2027     hints.ai_family = AF_UNSPEC;
2028     hints.ai_socktype = SOCK_STREAM;
2029    
2030     /* Get us ready for a bind() and don't bother doing dns lookup */
2031     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2032    
2033     if (irc_getaddrinfo(aconf->host, NULL, &hints, &res))
2034     {
2035     conf_dns_lookup(aconf);
2036     return;
2037     }
2038    
2039     assert(res != NULL);
2040    
2041     memcpy(&aconf->ipnum, res->ai_addr, res->ai_addrlen);
2042     aconf->ipnum.ss_len = res->ai_addrlen;
2043     aconf->ipnum.ss.ss_family = res->ai_family;
2044     irc_freeaddrinfo(res);
2045     }
2046    
2047     /* conf_connect_allowed()
2048     *
2049     * inputs - pointer to inaddr
2050     * - int type ipv4 or ipv6
2051     * output - BANNED or accepted
2052     * side effects - none
2053     */
2054     int
2055     conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
2056     {
2057     struct ip_entry *ip_found;
2058     struct AccessItem *aconf = find_dline_conf(addr, aftype);
2059    
2060     /* DLINE exempt also gets you out of static limits/pacing... */
2061     if (aconf && (aconf->status & CONF_EXEMPTDLINE))
2062     return 0;
2063    
2064     if (aconf != NULL)
2065     return BANNED_CLIENT;
2066    
2067     ip_found = find_or_add_ip(addr);
2068    
2069     if ((CurrentTime - ip_found->last_attempt) <
2070     ConfigFileEntry.throttle_time)
2071     {
2072     ip_found->last_attempt = CurrentTime;
2073     return TOO_FAST;
2074     }
2075    
2076     ip_found->last_attempt = CurrentTime;
2077     return 0;
2078     }
2079    
2080     static struct AccessItem *
2081     find_regexp_kline(const char *uhi[])
2082     {
2083     const dlink_node *ptr = NULL;
2084    
2085     DLINK_FOREACH(ptr, rkconf_items.head)
2086     {
2087     struct AccessItem *aptr = map_to_conf(ptr->data);
2088    
2089     assert(aptr->regexuser);
2090     assert(aptr->regexhost);
2091    
2092     if (!ircd_pcre_exec(aptr->regexuser, uhi[0]) &&
2093     (!ircd_pcre_exec(aptr->regexhost, uhi[1]) ||
2094     !ircd_pcre_exec(aptr->regexhost, uhi[2])))
2095     return aptr;
2096     }
2097    
2098     return NULL;
2099     }
2100    
2101     /* find_kill()
2102     *
2103     * inputs - pointer to client structure
2104     * output - pointer to struct AccessItem if found
2105     * side effects - See if this user is klined already,
2106     * and if so, return struct AccessItem pointer
2107     */
2108     struct AccessItem *
2109     find_kill(struct Client *client_p)
2110     {
2111     struct AccessItem *aconf = NULL;
2112     const char *uhi[3];
2113    
2114     uhi[0] = client_p->username;
2115     uhi[1] = client_p->host;
2116     uhi[2] = client_p->sockhost;
2117    
2118     assert(client_p != NULL);
2119    
2120     aconf = find_kline_conf(client_p->host, client_p->username,
2121     &client_p->localClient->ip,
2122     client_p->localClient->aftype);
2123     if (aconf == NULL)
2124     aconf = find_regexp_kline(uhi);
2125    
2126     if (aconf && (aconf->status & CONF_KLINE))
2127     return aconf;
2128    
2129     return NULL;
2130     }
2131    
2132     struct AccessItem *
2133     find_gline(struct Client *client_p)
2134     {
2135     struct AccessItem *aconf;
2136    
2137     assert(client_p != NULL);
2138    
2139     aconf = find_gline_conf(client_p->host, client_p->username,
2140     &client_p->localClient->ip,
2141     client_p->localClient->aftype);
2142    
2143     if (aconf && (aconf->status & CONF_GLINE))
2144     return aconf;
2145    
2146     return NULL;
2147     }
2148    
2149     /* add_temp_line()
2150     *
2151     * inputs - pointer to struct ConfItem
2152     * output - none
2153     * Side effects - links in given struct ConfItem into
2154     * temporary *line link list
2155     */
2156     void
2157     add_temp_line(struct ConfItem *conf)
2158     {
2159     struct AccessItem *aconf;
2160    
2161     if (conf->type == DLINE_TYPE)
2162     {
2163     aconf = map_to_conf(conf);
2164     SetConfTemporary(aconf);
2165     dlinkAdd(conf, &conf->node, &temporary_dlines);
2166     MyFree(aconf->user);
2167     aconf->user = NULL;
2168     add_conf_by_address(CONF_DLINE, aconf);
2169     }
2170     else if (conf->type == KLINE_TYPE)
2171     {
2172     aconf = map_to_conf(conf);
2173     SetConfTemporary(aconf);
2174     dlinkAdd(conf, &conf->node, &temporary_klines);
2175     add_conf_by_address(CONF_KILL, aconf);
2176     }
2177     else if (conf->type == GLINE_TYPE)
2178     {
2179     aconf = map_to_conf(conf);
2180     SetConfTemporary(aconf);
2181     dlinkAdd(conf, &conf->node, &temporary_glines);
2182     add_conf_by_address(CONF_GLINE, aconf);
2183     }
2184     else if (conf->type == XLINE_TYPE)
2185     {
2186     conf->flags |= CONF_FLAGS_TEMPORARY;
2187     dlinkAdd(conf, make_dlink_node(), &temporary_xlines);
2188     }
2189     else if (conf->type == RXLINE_TYPE)
2190     {
2191     conf->flags |= CONF_FLAGS_TEMPORARY;
2192     dlinkAdd(conf, make_dlink_node(), &temporary_rxlines);
2193     }
2194     else if (conf->type == RKLINE_TYPE)
2195     {
2196     conf->flags |= CONF_FLAGS_TEMPORARY;
2197     dlinkAdd(conf, make_dlink_node(), &temporary_rklines);
2198     }
2199     else if ((conf->type == NRESV_TYPE) || (conf->type == CRESV_TYPE))
2200     {
2201     conf->flags |= CONF_FLAGS_TEMPORARY;
2202     dlinkAdd(conf, make_dlink_node(), &temporary_resv);
2203     }
2204     }
2205    
2206     /* cleanup_tklines()
2207     *
2208     * inputs - NONE
2209     * output - NONE
2210     * side effects - call function to expire temporary k/d lines
2211     * This is an event started off in ircd.c
2212     */
2213     void
2214     cleanup_tklines(void *notused)
2215     {
2216     expire_tklines(&temporary_glines);
2217     expire_tklines(&temporary_klines);
2218     expire_tklines(&temporary_dlines);
2219     expire_tklines(&temporary_xlines);
2220     expire_tklines(&temporary_rxlines);
2221     expire_tklines(&temporary_rklines);
2222     expire_tklines(&temporary_resv);
2223     }
2224    
2225     /* expire_tklines()
2226     *
2227     * inputs - tkline list pointer
2228     * output - NONE
2229     * side effects - expire tklines
2230     */
2231     static void
2232     expire_tklines(dlink_list *tklist)
2233     {
2234     dlink_node *ptr;
2235     dlink_node *next_ptr;
2236     struct ConfItem *conf;
2237     struct MatchItem *xconf;
2238     struct MatchItem *nconf;
2239     struct AccessItem *aconf;
2240     struct ResvChannel *cconf;
2241    
2242     DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
2243     {
2244     conf = ptr->data;
2245     if (conf->type == GLINE_TYPE ||
2246     conf->type == KLINE_TYPE ||
2247     conf->type == DLINE_TYPE)
2248     {
2249     aconf = (struct AccessItem *)map_to_conf(conf);
2250     if (aconf->hold <= CurrentTime)
2251     {
2252     /* XXX - Do we want GLINE expiry notices?? */
2253     /* Alert opers that a TKline expired - Hwy */
2254     if (ConfigFileEntry.tkline_expire_notices)
2255     {
2256     if (aconf->status & CONF_KILL)
2257     {
2258     sendto_realops_flags(UMODE_ALL, L_ALL,
2259     "Temporary K-line for [%s@%s] expired",
2260     (aconf->user) ? aconf->user : "*",
2261     (aconf->host) ? aconf->host : "*");
2262     }
2263     else if (conf->type == DLINE_TYPE)
2264     {
2265     sendto_realops_flags(UMODE_ALL, L_ALL,
2266     "Temporary D-line for [%s] expired",
2267     (aconf->host) ? aconf->host : "*");
2268     }
2269     }
2270    
2271 michael 432 dlinkDelete(ptr, tklist);
2272 adx 30 delete_one_address_conf(aconf->host, aconf);
2273     }
2274     }
2275     else if (conf->type == XLINE_TYPE ||
2276     conf->type == RXLINE_TYPE)
2277     {
2278     xconf = (struct MatchItem *)map_to_conf(conf);
2279     if (xconf->hold <= CurrentTime)
2280     {
2281     if (ConfigFileEntry.tkline_expire_notices)
2282     sendto_realops_flags(UMODE_ALL, L_ALL,
2283     "Temporary X-line for [%s] %sexpired", conf->name,
2284     conf->type == RXLINE_TYPE ? "(REGEX) " : "");
2285     dlinkDelete(ptr, tklist);
2286     free_dlink_node(ptr);
2287     delete_conf_item(conf);
2288     }
2289     }
2290     else if (conf->type == RKLINE_TYPE)
2291     {
2292     aconf = map_to_conf(conf);
2293     if (aconf->hold <= CurrentTime)
2294     {
2295     if (ConfigFileEntry.tkline_expire_notices)
2296     sendto_realops_flags(UMODE_ALL, L_ALL,
2297     "Temporary K-line for [%s@%s] (REGEX) expired",
2298     (aconf->user) ? aconf->user : "*",
2299     (aconf->host) ? aconf->host : "*");
2300     dlinkDelete(ptr, tklist);
2301     free_dlink_node(ptr);
2302     delete_conf_item(conf);
2303     }
2304     }
2305     else if (conf->type == NRESV_TYPE)
2306     {
2307     nconf = (struct MatchItem *)map_to_conf(conf);
2308     if (nconf->hold <= CurrentTime)
2309     {
2310     if (ConfigFileEntry.tkline_expire_notices)
2311     sendto_realops_flags(UMODE_ALL, L_ALL,
2312     "Temporary RESV for [%s] expired", conf->name);
2313     dlinkDelete(ptr, tklist);
2314     free_dlink_node(ptr);
2315     delete_conf_item(conf);
2316     }
2317     }
2318     else if (conf->type == CRESV_TYPE)
2319     {
2320     cconf = (struct ResvChannel *)map_to_conf(conf);
2321     if (cconf->hold <= CurrentTime)
2322     {
2323     if (ConfigFileEntry.tkline_expire_notices)
2324     sendto_realops_flags(UMODE_ALL, L_ALL,
2325     "Temporary RESV for [%s] expired", cconf->name);
2326     dlinkDelete(ptr, tklist);
2327     free_dlink_node(ptr);
2328     delete_conf_item(conf);
2329     }
2330     }
2331     }
2332     }
2333    
2334     /* oper_privs_as_string()
2335     *
2336 michael 58 * inputs - pointer to client_p
2337 adx 30 * output - pointer to static string showing oper privs
2338     * side effects - return as string, the oper privs as derived from port
2339     */
2340 michael 58 static const struct oper_privs
2341     {
2342     const unsigned int oprivs;
2343     const unsigned int hidden;
2344     const unsigned char c;
2345     } flag_list[] = {
2346     { OPER_FLAG_ADMIN, OPER_FLAG_HIDDEN_ADMIN, 'A' },
2347     { OPER_FLAG_REMOTEBAN, 0, 'B' },
2348     { OPER_FLAG_DIE, 0, 'D' },
2349     { OPER_FLAG_GLINE, 0, 'G' },
2350     { OPER_FLAG_REHASH, 0, 'H' },
2351     { OPER_FLAG_K, 0, 'K' },
2352     { OPER_FLAG_OPERWALL, 0, 'L' },
2353     { OPER_FLAG_N, 0, 'N' },
2354     { OPER_FLAG_GLOBAL_KILL, 0, 'O' },
2355     { OPER_FLAG_REMOTE, 0, 'R' },
2356     { OPER_FLAG_OPER_SPY, 0, 'S' },
2357     { OPER_FLAG_UNKLINE, 0, 'U' },
2358     { OPER_FLAG_X, 0, 'X' },
2359     { 0, 0, '\0' }
2360     };
2361 adx 30
2362     char *
2363     oper_privs_as_string(const unsigned int port)
2364     {
2365 michael 58 static char privs_out[16];
2366     char *privs_ptr = privs_out;
2367     unsigned int i = 0;
2368 adx 30
2369 michael 58 for (; flag_list[i].oprivs; ++i)
2370     {
2371     if ((port & flag_list[i].oprivs) &&
2372     (port & flag_list[i].hidden) == 0)
2373     *privs_ptr++ = flag_list[i].c;
2374     else
2375     *privs_ptr++ = ToLowerTab[flag_list[i].c];
2376     }
2377    
2378     *privs_ptr = '\0';
2379    
2380 adx 30 return privs_out;
2381     }
2382    
2383     /*
2384     * Input: A client to find the active oper{} name for.
2385     * Output: The nick!user@host{oper} of the oper.
2386     * "oper" is server name for remote opers
2387     * Side effects: None.
2388     */
2389     char *
2390     get_oper_name(const struct Client *client_p)
2391     {
2392     dlink_node *cnode;
2393     struct ConfItem *conf;
2394     struct AccessItem *aconf;
2395    
2396     /* +5 for !,@,{,} and null */
2397     static char buffer[NICKLEN+USERLEN+HOSTLEN+HOSTLEN+5];
2398    
2399     if (MyConnect(client_p))
2400     {
2401     DLINK_FOREACH(cnode, client_p->localClient->confs.head)
2402     {
2403     conf = cnode->data;
2404     aconf = map_to_conf(conf);
2405    
2406     if (IsConfOperator(aconf))
2407     {
2408     ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
2409     client_p->username, client_p->host,
2410     conf->name);
2411     return buffer;
2412     }
2413     }
2414    
2415     /* Probably should assert here for now. If there is an oper out there
2416     * with no oper{} conf attached, it would be good for us to know...
2417     */
2418     assert(0); /* Oper without oper conf! */
2419     }
2420    
2421     ircsprintf(buffer, "%s!%s@%s{%s}", client_p->name,
2422     client_p->username, client_p->host, client_p->servptr->name);
2423     return buffer;
2424     }
2425    
2426     /* read_conf_files()
2427     *
2428     * inputs - cold start YES or NO
2429     * output - none
2430     * side effects - read all conf files needed, ircd.conf kline.conf etc.
2431     */
2432     void
2433     read_conf_files(int cold)
2434     {
2435     const char *filename;
2436     char chanmodes[32];
2437     char chanlimit[32];
2438    
2439     filename = get_conf_name(CONF_TYPE);
2440    
2441     /* We need to know the initial filename for the yyerror() to report
2442     FIXME: The full path is in conffilenamebuf first time since we
2443     dont know anything else
2444    
2445     - Gozem 2002-07-21
2446     */
2447     strlcpy(conffilebuf, filename, sizeof(conffilebuf));
2448    
2449     if ((conf_fbfile_in = fbopen(filename, "r")) == NULL)
2450     {
2451     if (cold)
2452     {
2453     ilog(L_CRIT, "Unable to read configuration file '%s': %s",
2454     filename, strerror(errno));
2455     exit(-1);
2456     }
2457     else
2458     {
2459     sendto_realops_flags(UMODE_ALL, L_ALL,
2460     "Unable to read configuration file '%s': %s",
2461     filename, strerror(errno));
2462     return;
2463     }
2464     }
2465    
2466     if (!cold)
2467     clear_out_old_conf();
2468    
2469     read_conf(conf_fbfile_in);
2470     fbclose(conf_fbfile_in);
2471    
2472     add_isupport("NETWORK", ServerInfo.network_name, -1);
2473     ircsprintf(chanmodes, "b%s%s:%d", ConfigChannel.use_except ? "e" : "",
2474     ConfigChannel.use_invex ? "I" : "", ConfigChannel.max_bans);
2475     add_isupport("MAXLIST", chanmodes, -1);
2476     add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
2477     if (ConfigChannel.disable_local_channels)
2478     add_isupport("CHANTYPES", "#", -1);
2479     else
2480     add_isupport("CHANTYPES", "#&", -1);
2481     ircsprintf(chanlimit, "%s:%d", ConfigChannel.disable_local_channels ? "#" : "#&",
2482     ConfigChannel.max_chans_per_user);
2483     add_isupport("CHANLIMIT", chanlimit, -1);
2484     ircsprintf(chanmodes, "%s%s%s", ConfigChannel.use_except ? "e" : "",
2485     ConfigChannel.use_invex ? "I" : "", "b,k,l,imnpst");
2486 michael 100 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
2487 adx 30 if (ConfigChannel.use_except)
2488     add_isupport("EXCEPTS", "e", -1);
2489     if (ConfigChannel.use_invex)
2490     add_isupport("INVEX", "I", -1);
2491     add_isupport("CHANMODES", chanmodes, -1);
2492    
2493     /*
2494     * message_locale may have changed. rebuild isupport since it relies
2495     * on strlen(form_str(RPL_ISUPPORT))
2496     */
2497     rebuild_isupport_message_line();
2498    
2499     parse_conf_file(KLINE_TYPE, cold);
2500     parse_conf_file(RKLINE_TYPE, cold);
2501     parse_conf_file(DLINE_TYPE, cold);
2502     parse_conf_file(XLINE_TYPE, cold);
2503     parse_conf_file(RXLINE_TYPE, cold);
2504     parse_conf_file(NRESV_TYPE, cold);
2505     parse_conf_file(CRESV_TYPE, cold);
2506     }
2507    
2508     /* parse_conf_file()
2509     *
2510     * inputs - type of conf file to parse
2511     * output - none
2512     * side effects - conf file for givenconf type is opened and read then parsed
2513     */
2514     static void
2515     parse_conf_file(int type, int cold)
2516     {
2517     FBFILE *file = NULL;
2518     const char *filename = get_conf_name(type);
2519    
2520     if ((file = fbopen(filename, "r")) == NULL)
2521     {
2522     if (cold)
2523     ilog(L_ERROR, "Unable to read configuration file '%s': %s",
2524     filename, strerror(errno));
2525     else
2526     sendto_realops_flags(UMODE_ALL, L_ALL,
2527     "Unable to read configuration file '%s': %s",
2528     filename, strerror(errno));
2529     }
2530     else
2531     {
2532     parse_csv_file(file, type);
2533     fbclose(file);
2534     }
2535     }
2536    
2537     /* clear_out_old_conf()
2538     *
2539     * inputs - none
2540     * output - none
2541     * side effects - Clear out the old configuration
2542     */
2543     static void
2544     clear_out_old_conf(void)
2545     {
2546     dlink_node *ptr = NULL, *next_ptr = NULL;
2547     struct ConfItem *conf;
2548     struct AccessItem *aconf;
2549     struct ClassItem *cltmp;
2550     struct MatchItem *match_item;
2551     dlink_list *free_items [] = {
2552     &server_items, &oconf_items, &hub_items, &leaf_items,
2553     &uconf_items, &xconf_items, &rxconf_items, &rkconf_items,
2554     &nresv_items, &cluster_items, &gdeny_items, NULL
2555     };
2556    
2557     dlink_list ** iterator = free_items; /* C is dumb */
2558    
2559     /* We only need to free anything allocated by yyparse() here.
2560     * Resetting structs, etc, is taken care of by set_default_conf().
2561     */
2562    
2563     for (; *iterator != NULL; iterator++)
2564     {
2565     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2566     {
2567     conf = ptr->data;
2568     /* XXX This is less than pretty */
2569     if (conf->type == SERVER_TYPE)
2570     {
2571 michael 671 aconf = map_to_conf(conf);
2572    
2573 adx 30 if (aconf->clients != 0)
2574     {
2575     SetConfIllegal(aconf);
2576     dlinkDelete(&conf->node, &server_items);
2577     }
2578     else
2579     {
2580     delete_conf_item(conf);
2581     }
2582     }
2583     else if (conf->type == OPER_TYPE)
2584     {
2585 michael 671 aconf = map_to_conf(conf);
2586    
2587 adx 30 if (aconf->clients != 0)
2588     {
2589     SetConfIllegal(aconf);
2590     dlinkDelete(&conf->node, &oconf_items);
2591     }
2592     else
2593     {
2594     delete_conf_item(conf);
2595     }
2596     }
2597     else if (conf->type == CLIENT_TYPE)
2598     {
2599 michael 671 aconf = map_to_conf(conf);
2600    
2601 adx 30 if (aconf->clients != 0)
2602     {
2603     SetConfIllegal(aconf);
2604     }
2605     else
2606     {
2607     delete_conf_item(conf);
2608     }
2609     }
2610     else if (conf->type == XLINE_TYPE ||
2611     conf->type == RXLINE_TYPE ||
2612     conf->type == RKLINE_TYPE)
2613     {
2614     /* temporary (r)xlines are also on
2615     * the (r)xconf items list */
2616     if (conf->flags & CONF_FLAGS_TEMPORARY)
2617     continue;
2618    
2619     delete_conf_item(conf);
2620     }
2621     else
2622     {
2623     if ((conf->type == LEAF_TYPE) || (conf->type == HUB_TYPE))
2624     {
2625 michael 671 match_item = map_to_conf(conf);
2626     if (match_item->ref_count <= 0)
2627 adx 30 delete_conf_item(conf);
2628     else
2629     {
2630     match_item->illegal = 1;
2631     dlinkDelete(&conf->node, *iterator);
2632     }
2633     }
2634     else
2635     delete_conf_item(conf);
2636     }
2637     }
2638     }
2639    
2640 michael 671 /*
2641     * don't delete the class table, rather mark all entries
2642 adx 30 * for deletion. The table is cleaned up by check_class. - avalon
2643     */
2644     DLINK_FOREACH(ptr, class_items.head)
2645     {
2646 michael 671 cltmp = map_to_conf(ptr->data);
2647    
2648 adx 30 if (ptr != class_items.tail) /* never mark the "default" class */
2649 michael 671 cltmp->active = 0;
2650 adx 30 }
2651    
2652     clear_out_address_conf();
2653    
2654     /* clean out module paths */
2655     #ifndef STATIC_MODULES
2656     mod_clear_paths();
2657     #endif
2658    
2659     /* clean out ServerInfo */
2660     MyFree(ServerInfo.description);
2661     ServerInfo.description = NULL;
2662     MyFree(ServerInfo.network_name);
2663     ServerInfo.network_name = NULL;
2664     MyFree(ServerInfo.network_desc);
2665     ServerInfo.network_desc = NULL;
2666     MyFree(ConfigFileEntry.egdpool_path);
2667     ConfigFileEntry.egdpool_path = NULL;
2668     #ifdef HAVE_LIBCRYPTO
2669     if (ServerInfo.rsa_private_key != NULL)
2670     {
2671     RSA_free(ServerInfo.rsa_private_key);
2672     ServerInfo.rsa_private_key = NULL;
2673     }
2674    
2675     MyFree(ServerInfo.rsa_private_key_file);
2676     ServerInfo.rsa_private_key_file = NULL;
2677     #endif
2678    
2679     /* clean out old resvs from the conf */
2680     clear_conf_resv();
2681    
2682     /* clean out AdminInfo */
2683     MyFree(AdminInfo.name);
2684     AdminInfo.name = NULL;
2685     MyFree(AdminInfo.email);
2686     AdminInfo.email = NULL;
2687     MyFree(AdminInfo.description);
2688     AdminInfo.description = NULL;
2689    
2690     /* operator{} and class{} blocks are freed above */
2691     /* clean out listeners */
2692     close_listeners();
2693    
2694     /* auth{}, quarantine{}, shared{}, connect{}, kill{}, deny{},
2695     * exempt{} and gecos{} blocks are freed above too
2696     */
2697    
2698     /* clean out general */
2699     MyFree(ConfigFileEntry.servlink_path);
2700     ConfigFileEntry.servlink_path = NULL;
2701     #ifdef HAVE_LIBCRYPTO
2702     ConfigFileEntry.default_cipher_preference = NULL;
2703     #endif /* HAVE_LIBCRYPTO */
2704     delete_isupport("INVEX");
2705     delete_isupport("EXCEPTS");
2706     }
2707    
2708     /* flush_deleted_I_P()
2709     *
2710     * inputs - none
2711     * output - none
2712     * side effects - This function removes I/P conf items
2713     */
2714     static void
2715     flush_deleted_I_P(void)
2716     {
2717     dlink_node *ptr;
2718     dlink_node *next_ptr;
2719     struct ConfItem *conf;
2720     struct AccessItem *aconf;
2721     dlink_list * free_items [] = {
2722 db 151 &server_items, &oconf_items, NULL
2723 adx 30 };
2724     dlink_list ** iterator = free_items; /* C is dumb */
2725    
2726     /* flush out deleted I and P lines
2727     * although still in use.
2728     */
2729     for (; *iterator != NULL; iterator++)
2730     {
2731     DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
2732     {
2733     conf = ptr->data;
2734     aconf = (struct AccessItem *)map_to_conf(conf);
2735    
2736     if (IsConfIllegal(aconf))
2737     {
2738     dlinkDelete(ptr, *iterator);
2739    
2740     if (aconf->clients == 0)
2741     delete_conf_item(conf);
2742     }
2743     }
2744     }
2745     }
2746    
2747     /* get_conf_name()
2748     *
2749     * inputs - type of conf file to return name of file for
2750     * output - pointer to filename for type of conf
2751     * side effects - none
2752     */
2753     const char *
2754     get_conf_name(ConfType type)
2755     {
2756     switch (type)
2757     {
2758     case CONF_TYPE:
2759     return ConfigFileEntry.configfile;
2760     break;
2761     case KLINE_TYPE:
2762     return ConfigFileEntry.klinefile;
2763     break;
2764     case RKLINE_TYPE:
2765     return ConfigFileEntry.rklinefile;
2766     break;
2767     case DLINE_TYPE:
2768     return ConfigFileEntry.dlinefile;
2769     break;
2770     case XLINE_TYPE:
2771     return ConfigFileEntry.xlinefile;
2772     break;
2773     case RXLINE_TYPE:
2774     return ConfigFileEntry.rxlinefile;
2775     break;
2776     case CRESV_TYPE:
2777     return ConfigFileEntry.cresvfile;
2778     break;
2779     case NRESV_TYPE:
2780     return ConfigFileEntry.nresvfile;
2781     break;
2782     case GLINE_TYPE:
2783     return ConfigFileEntry.glinefile;
2784     break;
2785    
2786     default:
2787     return NULL; /* This should NEVER HAPPEN since we call this function
2788     only with the above values, this will cause us to core
2789     at some point if this happens so we know where it was */
2790     }
2791     }
2792    
2793     #define BAD_PING (-1)
2794    
2795     /* get_conf_ping()
2796     *
2797     * inputs - pointer to struct AccessItem
2798     * - pointer to a variable that receives ping warning time
2799     * output - ping frequency
2800     * side effects - NONE
2801     */
2802     static int
2803     get_conf_ping(struct ConfItem *conf, int *pingwarn)
2804     {
2805     struct ClassItem *aclass;
2806     struct AccessItem *aconf;
2807    
2808     if (conf != NULL)
2809     {
2810     aconf = (struct AccessItem *)map_to_conf(conf);
2811     if (aconf->class_ptr != NULL)
2812     {
2813     aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
2814     *pingwarn = PingWarning(aclass);
2815     return PingFreq(aclass);
2816     }
2817     }
2818    
2819     return BAD_PING;
2820     }
2821    
2822     /* get_client_class()
2823     *
2824     * inputs - pointer to client struct
2825     * output - pointer to name of class
2826     * side effects - NONE
2827     */
2828     const char *
2829     get_client_class(struct Client *target_p)
2830     {
2831     dlink_node *ptr;
2832     struct ConfItem *conf;
2833     struct AccessItem *aconf;
2834    
2835     if (target_p != NULL && !IsMe(target_p) &&
2836     target_p->localClient->confs.head != NULL)
2837     {
2838     DLINK_FOREACH(ptr, target_p->localClient->confs.head)
2839     {
2840     conf = ptr->data;
2841    
2842     if (conf->type == CLIENT_TYPE || conf->type == SERVER_TYPE ||
2843     conf->type == OPER_TYPE)
2844     {
2845     aconf = (struct AccessItem *) map_to_conf(conf);
2846     if (aconf->class_ptr != NULL)
2847     return aconf->class_ptr->name;
2848     }
2849     }
2850     }
2851    
2852     return "default";
2853     }
2854    
2855     /* get_client_ping()
2856     *
2857     * inputs - pointer to client struct
2858     * - pointer to a variable that receives ping warning time
2859     * output - ping frequency
2860     * side effects - NONE
2861     */
2862     int
2863     get_client_ping(struct Client *target_p, int *pingwarn)
2864     {
2865     int ping;
2866     struct ConfItem *conf;
2867     dlink_node *nlink;
2868    
2869     if (target_p->localClient->confs.head != NULL)
2870     DLINK_FOREACH(nlink, target_p->localClient->confs.head)
2871     {
2872     conf = nlink->data;
2873    
2874     if ((conf->type == CLIENT_TYPE) || (conf->type == SERVER_TYPE) ||
2875     (conf->type == OPER_TYPE))
2876     {
2877     ping = get_conf_ping(conf, pingwarn);
2878     if (ping > 0)
2879     return ping;
2880     }
2881     }
2882    
2883     *pingwarn = 0;
2884     return DEFAULT_PINGFREQUENCY;
2885     }
2886    
2887     /* find_class()
2888     *
2889     * inputs - string name of class
2890     * output - corresponding Class pointer
2891     * side effects - NONE
2892     */
2893     struct ConfItem *
2894     find_class(const char *classname)
2895     {
2896     struct ConfItem *conf;
2897    
2898     if ((conf = find_exact_name_conf(CLASS_TYPE, classname, NULL, NULL)) != NULL)
2899 michael 671 return conf;
2900 adx 30
2901     return class_default;
2902     }
2903    
2904     /* check_class()
2905     *
2906     * inputs - NONE
2907     * output - NONE
2908     * side effects -
2909     */
2910     void
2911     check_class(void)
2912     {
2913 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
2914 adx 30
2915     DLINK_FOREACH_SAFE(ptr, next_ptr, class_items.head)
2916     {
2917 michael 671 struct ClassItem *aclass = map_to_conf(ptr->data);
2918 adx 30
2919 michael 671 if (!aclass->active)
2920 adx 30 {
2921     destroy_cidr_class(aclass);
2922 michael 671
2923     if (!CurrUserCount(aclass))
2924     delete_conf_item(ptr->data);
2925 adx 30 }
2926     }
2927     }
2928    
2929     /* init_class()
2930     *
2931     * inputs - NONE
2932     * output - NONE
2933     * side effects -
2934     */
2935     void
2936     init_class(void)
2937     {
2938     struct ClassItem *aclass;
2939    
2940     class_default = make_conf_item(CLASS_TYPE);
2941 michael 671
2942     aclass = map_to_conf(class_default);
2943     aclass->active = 1;
2944 adx 30 DupString(class_default->name, "default");
2945     ConFreq(aclass) = DEFAULT_CONNECTFREQUENCY;
2946     PingFreq(aclass) = DEFAULT_PINGFREQUENCY;
2947     MaxTotal(aclass) = MAXIMUM_LINKS_DEFAULT;
2948     MaxSendq(aclass) = DEFAULT_SENDQ;
2949    
2950     client_check_cb = register_callback("check_client", check_client);
2951     }
2952    
2953     /* get_sendq()
2954     *
2955     * inputs - pointer to client
2956     * output - sendq for this client as found from its class
2957     * side effects - NONE
2958     */
2959     unsigned long
2960     get_sendq(struct Client *client_p)
2961     {
2962     unsigned long sendq = DEFAULT_SENDQ;
2963     dlink_node *ptr;
2964     struct ConfItem *conf;
2965     struct ConfItem *class_conf;
2966     struct ClassItem *aclass;
2967     struct AccessItem *aconf;
2968    
2969     if (client_p && !IsMe(client_p) && (client_p->localClient->confs.head))
2970     {
2971     DLINK_FOREACH(ptr, client_p->localClient->confs.head)
2972     {
2973     conf = ptr->data;
2974     if ((conf->type == SERVER_TYPE) || (conf->type == OPER_TYPE)
2975     || (conf->type == CLIENT_TYPE))
2976     {
2977     aconf = (struct AccessItem *)map_to_conf(conf);
2978     if ((class_conf = aconf->class_ptr) == NULL)
2979     continue;
2980     aclass = (struct ClassItem *)map_to_conf(class_conf);
2981     sendq = MaxSendq(aclass);
2982     return sendq;
2983     }
2984     }
2985     }
2986     /* XXX return a default?
2987     * if here, then there wasn't an attached conf with a sendq
2988     * that is very bad -Dianora
2989     */
2990     return DEFAULT_SENDQ;
2991     }
2992    
2993     /* conf_add_class_to_conf()
2994     *
2995     * inputs - pointer to config item
2996     * output - NONE
2997     * side effects - Add a class pointer to a conf
2998     */
2999     void
3000     conf_add_class_to_conf(struct ConfItem *conf, const char *class_name)
3001     {
3002 michael 671 struct AccessItem *aconf = map_to_conf(conf);
3003     struct ClassItem *class = NULL;
3004 adx 30
3005     if (class_name == NULL)
3006     {
3007     aconf->class_ptr = class_default;
3008 michael 671
3009 adx 30 if (conf->type == CLIENT_TYPE)
3010     sendto_realops_flags(UMODE_ALL, L_ALL,
3011     "Warning *** Defaulting to default class for %s@%s",
3012     aconf->user, aconf->host);
3013     else
3014     sendto_realops_flags(UMODE_ALL, L_ALL,
3015     "Warning *** Defaulting to default class for %s",
3016     conf->name);
3017     }
3018     else
3019     aconf->class_ptr = find_class(class_name);
3020    
3021 michael 671 if (aconf->class_ptr)
3022     class = map_to_conf(aconf->class_ptr);
3023    
3024     if (aconf->class_ptr == NULL || !class->active)
3025 adx 30 {
3026     if (conf->type == CLIENT_TYPE)
3027     sendto_realops_flags(UMODE_ALL, L_ALL,
3028     "Warning *** Defaulting to default class for %s@%s",
3029     aconf->user, aconf->host);
3030     else
3031     sendto_realops_flags(UMODE_ALL, L_ALL,
3032     "Warning *** Defaulting to default class for %s",
3033     conf->name);
3034     aconf->class_ptr = class_default;
3035     }
3036     }
3037    
3038     /* conf_add_server()
3039     *
3040     * inputs - pointer to config item
3041     * - pointer to link count already on this conf
3042     * output - NONE
3043     * side effects - Add a connect block
3044     */
3045     int
3046 michael 593 conf_add_server(struct ConfItem *conf, const char *class_name)
3047 adx 30 {
3048     struct AccessItem *aconf;
3049 michael 593 struct split_nuh_item nuh;
3050     char conf_user[USERLEN + 1];
3051     char conf_host[HOSTLEN + 1];
3052 adx 30
3053     aconf = map_to_conf(conf);
3054    
3055     conf_add_class_to_conf(conf, class_name);
3056    
3057 michael 593 if (!aconf->host || !conf->name)
3058 adx 30 {
3059     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block");
3060     ilog(L_WARN, "Bad connect block");
3061     return -1;
3062     }
3063    
3064     if (EmptyString(aconf->passwd) && !IsConfCryptLink(aconf))
3065     {
3066     sendto_realops_flags(UMODE_ALL, L_ALL, "Bad connect block, name %s",
3067     conf->name);
3068     ilog(L_WARN, "Bad connect block, host %s", conf->name);
3069     return -1;
3070     }
3071    
3072 michael 593 nuh.nuhmask = aconf->host;
3073     nuh.nickptr = NULL;
3074     nuh.userptr = conf_user;
3075     nuh.hostptr = conf_host;
3076    
3077     nuh.nicksize = 0;
3078     nuh.usersize = sizeof(conf_user);
3079     nuh.hostsize = sizeof(conf_host);
3080    
3081     split_nuh(&nuh);
3082    
3083     MyFree(aconf->host);
3084     aconf->host = NULL;
3085    
3086     DupString(aconf->user, conf_user); /* somehow username checking for servers
3087     got lost in H6/7, will have to be re-added */
3088     DupString(aconf->host, conf_host);
3089    
3090 adx 30 lookup_confhost(conf);
3091    
3092     return 0;
3093     }
3094    
3095     /* conf_add_d_conf()
3096     *
3097     * inputs - pointer to config item
3098     * output - NONE
3099     * side effects - Add a d/D line
3100     */
3101     void
3102     conf_add_d_conf(struct AccessItem *aconf)
3103     {
3104     if (aconf->host == NULL)
3105     return;
3106    
3107     aconf->user = NULL;
3108    
3109     /* XXX - Should 'd' ever be in the old conf? For new conf we don't
3110     * need this anyway, so I will disable it for now... -A1kmm
3111     */
3112     if (parse_netmask(aconf->host, NULL, NULL) == HM_HOST)
3113     {
3114     ilog(L_WARN, "Invalid Dline %s ignored", aconf->host);
3115     free_access_item(aconf);
3116     }
3117     else
3118     {
3119     /* XXX ensure user is NULL */
3120     MyFree(aconf->user);
3121     aconf->user = NULL;
3122     add_conf_by_address(CONF_DLINE, aconf);
3123     }
3124     }
3125    
3126     /* yyerror()
3127     *
3128     * inputs - message from parser
3129     * output - NONE
3130     * side effects - message to opers and log file entry is made
3131     */
3132     void
3133     yyerror(const char *msg)
3134     {
3135     char newlinebuf[IRCD_BUFSIZE];
3136    
3137     if (ypass != 1)
3138     return;
3139    
3140     strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
3141     sendto_realops_flags(UMODE_ALL, L_ALL, "\"%s\", line %u: %s: %s",
3142     conffilebuf, lineno + 1, msg, newlinebuf);
3143     ilog(L_WARN, "\"%s\", line %u: %s: %s",
3144     conffilebuf, lineno + 1, msg, newlinebuf);
3145     }
3146    
3147     int
3148     conf_fbgets(char *lbuf, unsigned int max_size, FBFILE *fb)
3149     {
3150     if (fbgets(lbuf, max_size, fb) == NULL)
3151     return 0;
3152    
3153     return strlen(lbuf);
3154     }
3155    
3156     int
3157     conf_yy_fatal_error(const char *msg)
3158     {
3159     return 0;
3160     }
3161    
3162     /*
3163     * valid_tkline()
3164     *
3165     * inputs - pointer to ascii string to check
3166     * - whether the specified time is in seconds or minutes
3167     * output - -1 not enough parameters
3168     * - 0 if not an integer number, else the number
3169     * side effects - none
3170     * Originally written by Dianora (Diane, db@db.net)
3171     */
3172     time_t
3173     valid_tkline(char *p, int minutes)
3174     {
3175     time_t result = 0;
3176    
3177     while (*p)
3178     {
3179     if (IsDigit(*p))
3180     {
3181     result *= 10;
3182     result += ((*p) & 0xF);
3183     p++;
3184     }
3185     else
3186     return 0;
3187     }
3188    
3189     /* in the degenerate case where oper does a /quote kline 0 user@host :reason
3190     * i.e. they specifically use 0, I am going to return 1 instead
3191     * as a return value of non-zero is used to flag it as a temporary kline
3192     */
3193    
3194     if (result == 0)
3195     result = 1;
3196    
3197     /*
3198     * If the incoming time is in seconds convert it to minutes for the purpose
3199     * of this calculation
3200     */
3201     if (!minutes)
3202     result = result / (time_t)60;
3203    
3204     if (result > MAX_TDKLINE_TIME)
3205     result = MAX_TDKLINE_TIME;
3206    
3207     result = result * (time_t)60; /* turn it into seconds */
3208    
3209     return result;
3210     }
3211    
3212     /* valid_wild_card()
3213     *
3214     * input - pointer to client
3215     * - int flag, 0 for no warning oper 1 for warning oper
3216     * - count of following varargs to check
3217     * output - 0 if not valid, 1 if valid
3218     * side effects - NOTICE is given to source_p if warn is 1
3219     */
3220     int
3221     valid_wild_card(struct Client *source_p, int warn, int count, ...)
3222     {
3223     char *p;
3224     char tmpch;
3225     int nonwild = 0;
3226     va_list args;
3227    
3228     /*
3229     * Now we must check the user and host to make sure there
3230     * are at least NONWILDCHARS non-wildcard characters in
3231     * them, otherwise assume they are attempting to kline
3232     * *@* or some variant of that. This code will also catch
3233     * people attempting to kline *@*.tld, as long as NONWILDCHARS
3234     * is greater than 3. In that case, there are only 3 non-wild
3235     * characters (tld), so if NONWILDCHARS is 4, the kline will
3236     * be disallowed.
3237     * -wnder
3238     */
3239    
3240     va_start(args, count);
3241    
3242     while (count--)
3243     {
3244     p = va_arg(args, char *);
3245     if (p == NULL)
3246     continue;
3247    
3248     while ((tmpch = *p++))
3249     {
3250     if (!IsKWildChar(tmpch))
3251     {
3252     /*
3253     * If we find enough non-wild characters, we can
3254     * break - no point in searching further.
3255     */
3256     if (++nonwild >= ConfigFileEntry.min_nonwildcard)
3257     return 1;
3258     }
3259     }
3260     }
3261    
3262     if (warn)
3263     sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
3264     me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
3265     return 0;
3266     }
3267    
3268     /* XXX should this go into a separate file ? -Dianora */
3269     /* parse_aline
3270     *
3271     * input - pointer to cmd name being used
3272     * - pointer to client using cmd
3273     * - parc parameter count
3274     * - parv[] list of parameters to parse
3275     * - parse_flags bit map of things to test
3276     * - pointer to user or string to parse into
3277     * - pointer to host or NULL to parse into if non NULL
3278     * - pointer to optional tkline time or NULL
3279     * - pointer to target_server to parse into if non NULL
3280     * - pointer to reason to parse into
3281     *
3282     * output - 1 if valid, -1 if not valid
3283     * side effects - A generalised k/d/x etc. line parser,
3284     * "ALINE [time] user@host|string [ON] target :reason"
3285     * will parse returning a parsed user, host if
3286     * h_p pointer is non NULL, string otherwise.
3287     * if tkline_time pointer is non NULL a tk line will be set
3288     * to non zero if found.
3289     * if tkline_time pointer is NULL and tk line is found,
3290     * error is reported.
3291     * if target_server is NULL and an "ON" is found error
3292     * is reported.
3293     * if reason pointer is NULL ignore pointer,
3294     * this allows usee of parse_a_line in unkline etc.
3295     *
3296     * - Dianora
3297     */
3298     int
3299     parse_aline(const char *cmd, struct Client *source_p,
3300     int parc, char **parv,
3301     int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
3302     char **target_server, char **reason)
3303     {
3304     int found_tkline_time=0;
3305     static char def_reason[] = "No Reason";
3306     static char user[USERLEN*4+1];
3307     static char host[HOSTLEN*4+1];
3308    
3309     parv++;
3310     parc--;
3311    
3312     found_tkline_time = valid_tkline(*parv, TK_MINUTES);
3313    
3314     if (found_tkline_time != 0)
3315     {
3316     parv++;
3317     parc--;
3318    
3319     if (tkline_time != NULL)
3320     *tkline_time = found_tkline_time;
3321     else
3322     {
3323     sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
3324     me.name, source_p->name, cmd);
3325     return -1;
3326     }
3327     }
3328    
3329     if (parc == 0)
3330     {
3331     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3332     me.name, source_p->name, cmd);
3333     return -1;
3334     }
3335    
3336     if (h_p == NULL)
3337     *up_p = *parv;
3338     else
3339     {
3340     if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
3341     return -1;
3342    
3343     *up_p = user;
3344     *h_p = host;
3345     }
3346    
3347     parc--;
3348     parv++;
3349    
3350     if (parc != 0)
3351     {
3352     if (irccmp(*parv, "ON") == 0)
3353     {
3354     parc--;
3355     parv++;
3356    
3357     if (target_server == NULL)
3358     {
3359     sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
3360     me.name, source_p->name, cmd);
3361     return -1;
3362     }
3363    
3364     if (!IsOperRemoteBan(source_p))
3365     {
3366     sendto_one(source_p, form_str(ERR_NOPRIVS),
3367     me.name, source_p->name, "remoteban");
3368     return -1;
3369     }
3370    
3371     if (parc == 0 || EmptyString(*parv))
3372     {
3373     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
3374     me.name, source_p->name, cmd);
3375     return -1;
3376     }
3377    
3378     *target_server = *parv;
3379     parc--;
3380     parv++;
3381     }
3382     else
3383     {
3384     /* Make sure target_server *is* NULL if no ON server found
3385     * caller probably NULL'd it first, but no harm to do it again -db
3386     */
3387     if (target_server != NULL)
3388     *target_server = NULL;
3389     }
3390     }
3391    
3392     if (h_p != NULL)
3393     {
3394     if (strchr(user, '!') != NULL)
3395     {
3396     sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
3397     me.name, source_p->name);
3398     return -1;
3399     }
3400    
3401     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 2, *up_p, *h_p))
3402     return -1;
3403     }
3404     else
3405     if ((parse_flags & AWILD) && !valid_wild_card(source_p, YES, 1, *up_p))
3406     return -1;
3407    
3408     if (reason != NULL)
3409     {
3410     if (parc != 0)
3411     {
3412     *reason = *parv;
3413     if (!valid_comment(source_p, *reason, YES))
3414     return -1;
3415     }
3416     else
3417     *reason = def_reason;
3418     }
3419    
3420     return 1;
3421     }
3422    
3423     /* find_user_host()
3424     *
3425     * inputs - pointer to client placing kline
3426     * - pointer to user_host_or_nick
3427     * - pointer to user buffer
3428     * - pointer to host buffer
3429     * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
3430     * side effects -
3431     */
3432     static int
3433     find_user_host(struct Client *source_p, char *user_host_or_nick,
3434     char *luser, char *lhost, unsigned int flags)
3435     {
3436     struct Client *target_p = NULL;
3437     char *hostp = NULL;
3438    
3439     if (lhost == NULL)
3440     {
3441     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
3442     return 1;
3443     }
3444    
3445     if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
3446     {
3447     /* Explicit user@host mask given */
3448    
3449 michael 593 if (hostp != NULL) /* I'm a little user@host */
3450 adx 30 {
3451     *(hostp++) = '\0'; /* short and squat */
3452     if (*user_host_or_nick)
3453     strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
3454     else
3455     strcpy(luser, "*");
3456     if (*hostp)
3457     strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
3458     else
3459     strcpy(lhost, "*");
3460     }
3461     else
3462     {
3463     luser[0] = '*'; /* no @ found, assume its *@somehost */
3464     luser[1] = '\0';
3465     strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
3466     }
3467    
3468     return 1;
3469     }
3470     else if (!(flags & NOUSERLOOKUP))
3471     {
3472     /* Try to find user@host mask from nick */
3473     /* Okay to use source_p as the first param, because source_p == client_p */
3474     if ((target_p =
3475     find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
3476     return 0;
3477    
3478     if (IsExemptKline(target_p))
3479     {
3480     if (!IsServer(source_p))
3481     sendto_one(source_p,
3482     ":%s NOTICE %s :%s is E-lined",
3483     me.name, source_p->name, target_p->name);
3484     return 0;
3485     }
3486    
3487     /*
3488     * turn the "user" bit into "*user", blow away '~'
3489     * if found in original user name (non-idented)
3490     */
3491     strlcpy(luser, target_p->username, USERLEN*4 + 1);
3492    
3493     if (target_p->username[0] == '~')
3494     luser[0] = '*';
3495    
3496     if (target_p->sockhost[0] == '\0' ||
3497     (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
3498     strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
3499     else
3500     strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
3501     return 1;
3502     }
3503    
3504     return 0;
3505     }
3506    
3507     /* valid_comment()
3508     *
3509     * inputs - pointer to client
3510     * - pointer to comment
3511     * output - 0 if no valid comment,
3512     * - 1 if valid
3513     * side effects - truncates reason where necessary
3514     */
3515     int
3516     valid_comment(struct Client *source_p, char *comment, int warn)
3517     {
3518     if (strchr(comment, '"'))
3519     {
3520     if (warn)
3521     sendto_one(source_p, ":%s NOTICE %s :Invalid character '\"' in comment",
3522     me.name, source_p->name);
3523     return 0;
3524     }
3525    
3526     if (strlen(comment) > REASONLEN)
3527     comment[REASONLEN-1] = '\0';
3528    
3529     return 1;
3530     }
3531    
3532     /* match_conf_password()
3533     *
3534     * inputs - pointer to given password
3535     * - pointer to Conf
3536     * output - 1 or 0 if match
3537     * side effects - none
3538     */
3539     int
3540     match_conf_password(const char *password, const struct AccessItem *aconf)
3541     {
3542     const char *encr = NULL;
3543    
3544     if (password == NULL || aconf->passwd == NULL)
3545     return 0;
3546    
3547     if (aconf->flags & CONF_FLAGS_ENCRYPTED)
3548     {
3549     /* use first two chars of the password they send in as salt */
3550     /* If the password in the conf is MD5, and ircd is linked
3551     * to scrypt on FreeBSD, or the standard crypt library on
3552     * glibc Linux, then this code will work fine on generating
3553     * the proper encrypted hash for comparison.
3554     */
3555     if (*aconf->passwd)
3556     encr = crypt(password, aconf->passwd);
3557     else
3558     encr = "";
3559     }
3560     else
3561     encr = password;
3562    
3563     return !strcmp(encr, aconf->passwd);
3564     }
3565    
3566     /*
3567     * cluster_a_line
3568     *
3569     * inputs - client sending the cluster
3570     * - command name "KLINE" "XLINE" etc.
3571     * - capab -- CAP_KLN etc. from s_serv.h
3572     * - cluster type -- CLUSTER_KLINE etc. from s_conf.h
3573     * - pattern and args to send along
3574     * output - none
3575     * side effects - Take source_p send the pattern with args given
3576     * along to all servers that match capab and cluster type
3577     */
3578     void
3579     cluster_a_line(struct Client *source_p, const char *command,
3580 michael 593 int capab, int cluster_type, const char *pattern, ...)
3581 adx 30 {
3582     va_list args;
3583     char buffer[IRCD_BUFSIZE];
3584 michael 593 const dlink_node *ptr = NULL;
3585 adx 30
3586     va_start(args, pattern);
3587     vsnprintf(buffer, sizeof(buffer), pattern, args);
3588     va_end(args);
3589    
3590     DLINK_FOREACH(ptr, cluster_items.head)
3591     {
3592 michael 593 const struct ConfItem *conf = ptr->data;
3593 adx 30
3594     if (conf->flags & cluster_type)
3595     sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
3596     "%s %s %s", command, conf->name, buffer);
3597     }
3598     }
3599    
3600     /*
3601     * split_nuh
3602     *
3603     * inputs - pointer to original mask (modified in place)
3604     * - pointer to pointer where nick should go
3605     * - pointer to pointer where user should go
3606     * - pointer to pointer where host should go
3607     * output - NONE
3608     * side effects - mask is modified in place
3609     * If nick pointer is NULL, ignore writing to it
3610     * this allows us to use this function elsewhere.
3611     *
3612     * mask nick user host
3613     * ---------------------- ------- ------- ------
3614     * Dianora!db@db.net Dianora db db.net
3615     * Dianora Dianora * *
3616     * db.net * * db.net
3617     * OR if nick pointer is NULL
3618     * Dianora - * Dianora
3619     * Dianora! Dianora * *
3620     * Dianora!@ Dianora * *
3621     * Dianora!db Dianora db *
3622     * Dianora!@db.net Dianora * db.net
3623     * db@db.net * db db.net
3624     * !@ * * *
3625     * @ * * *
3626     * ! * * *
3627     */
3628     void
3629 michael 593 split_nuh(struct split_nuh_item *const iptr)
3630 adx 30 {
3631     char *p = NULL, *q = NULL;
3632    
3633 michael 593 if (iptr->nickptr)
3634     strlcpy(iptr->nickptr, "*", iptr->nicksize);
3635     if (iptr->userptr)
3636     strlcpy(iptr->userptr, "*", iptr->usersize);
3637     if (iptr->hostptr)
3638     strlcpy(iptr->hostptr, "*", iptr->hostsize);
3639    
3640     if ((p = strchr(iptr->nuhmask, '!')))
3641 adx 30 {
3642     *p = '\0';
3643    
3644 michael 593 if (iptr->nickptr && *iptr->nuhmask != '\0')
3645     strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3646 adx 30
3647 michael 593 if ((q = strchr(++p, '@'))) {
3648     *q++ = '\0';
3649    
3650 adx 30 if (*p != '\0')
3651 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3652 adx 30
3653 michael 593 if (*q != '\0')
3654     strlcpy(iptr->hostptr, q, iptr->hostsize);
3655 adx 30 }
3656     else
3657     {
3658     if (*p != '\0')
3659 michael 593 strlcpy(iptr->userptr, p, iptr->usersize);
3660 adx 30 }
3661     }
3662 michael 593 else
3663 adx 30 {
3664 michael 593 /* No ! found so lets look for a user@host */
3665     if ((p = strchr(iptr->nuhmask, '@')))
3666 adx 30 {
3667 michael 593 /* if found a @ */
3668     *p++ = '\0';
3669 adx 30
3670 michael 593 if (*iptr->nuhmask != '\0')
3671     strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
3672 adx 30
3673 michael 593 if (*p != '\0')
3674     strlcpy(iptr->hostptr, p, iptr->hostsize);
3675 adx 30 }
3676 michael 593 else
3677 adx 30 {
3678 michael 593 /* no @ found */
3679     if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
3680     strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
3681 adx 30 else
3682 michael 593 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
3683 adx 30 }
3684     }
3685     }
3686    
3687     /*
3688     * flags_to_ascii
3689     *
3690     * inputs - flags is a bitmask
3691     * - pointer to table of ascii letters corresponding
3692     * to each bit
3693     * - flag 1 for convert ToLower if bit missing
3694     * 0 if ignore.
3695     * output - none
3696     * side effects - string pointed to by p has bitmap chars written to it
3697     */
3698     static void
3699     flags_to_ascii(unsigned int flags, const unsigned int bit_table[], char *p,
3700     int lowerit)
3701     {
3702     unsigned int mask = 1;
3703     int i = 0;
3704    
3705     for (mask = 1; (mask != 0) && (bit_table[i] != 0); mask <<= 1, i++)
3706     {
3707     if (flags & mask)
3708     *p++ = bit_table[i];
3709 michael 593 else if (lowerit)
3710 adx 30 *p++ = ToLower(bit_table[i]);
3711     }
3712     *p = '\0';
3713     }
3714    
3715     /*
3716     * cidr_limit_reached
3717     *
3718     * inputs - int flag allowing over_rule of limits
3719     * - pointer to the ip to be added
3720     * - pointer to the class
3721     * output - non zero if limit reached
3722     * 0 if limit not reached
3723     * side effects -
3724     */
3725     static int
3726     cidr_limit_reached(int over_rule,
3727     struct irc_ssaddr *ip, struct ClassItem *aclass)
3728     {
3729     dlink_node *ptr = NULL;
3730     struct CidrItem *cidr;
3731    
3732     if (NumberPerCidr(aclass) <= 0)
3733     return 0;
3734    
3735     if (ip->ss.ss_family == AF_INET)
3736     {
3737     if (CidrBitlenIPV4(aclass) <= 0)
3738     return 0;
3739    
3740     DLINK_FOREACH(ptr, aclass->list_ipv4.head)
3741     {
3742     cidr = ptr->data;
3743     if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3744     {
3745     if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3746     return -1;
3747     cidr->number_on_this_cidr++;
3748     return 0;
3749     }
3750     }
3751     cidr = MyMalloc(sizeof(struct CidrItem));
3752     cidr->number_on_this_cidr = 1;
3753     cidr->mask = *ip;
3754     mask_addr(&cidr->mask, CidrBitlenIPV4(aclass));
3755     dlinkAdd(cidr, &cidr->node, &aclass->list_ipv4);
3756     }
3757     #ifdef IPV6
3758     else if (CidrBitlenIPV6(aclass) > 0)
3759     {
3760     DLINK_FOREACH(ptr, aclass->list_ipv6.head)
3761     {
3762     cidr = ptr->data;
3763     if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3764     {
3765     if (!over_rule && (cidr->number_on_this_cidr >= NumberPerCidr(aclass)))
3766     return -1;
3767     cidr->number_on_this_cidr++;
3768     return 0;
3769     }
3770     }
3771     cidr = MyMalloc(sizeof(struct CidrItem));
3772     cidr->number_on_this_cidr = 1;
3773     cidr->mask = *ip;
3774     mask_addr(&cidr->mask, CidrBitlenIPV6(aclass));
3775     dlinkAdd(cidr, &cidr->node, &aclass->list_ipv6);
3776     }
3777     #endif
3778     return 0;
3779     }
3780    
3781     /*
3782     * remove_from_cidr_check
3783     *
3784     * inputs - pointer to the ip to be removed
3785     * - pointer to the class
3786     * output - NONE
3787     * side effects -
3788     */
3789     static void
3790     remove_from_cidr_check(struct irc_ssaddr *ip, struct ClassItem *aclass)
3791     {
3792     dlink_node *ptr = NULL;
3793     dlink_node *next_ptr = NULL;
3794     struct CidrItem *cidr;
3795    
3796     if (NumberPerCidr(aclass) == 0)
3797     return;
3798    
3799     if (ip->ss.ss_family == AF_INET)
3800     {
3801     if (CidrBitlenIPV4(aclass) <= 0)
3802     return;
3803    
3804     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv4.head)
3805     {
3806     cidr = ptr->data;
3807     if (match_ipv4(ip, &cidr->mask, CidrBitlenIPV4(aclass)))
3808     {
3809     cidr->number_on_this_cidr--;
3810     if (cidr->number_on_this_cidr == 0)
3811     {
3812     dlinkDelete(ptr, &aclass->list_ipv4);
3813     MyFree(cidr);
3814     return;
3815     }
3816     }
3817     }
3818     }
3819     #ifdef IPV6
3820     else if (CidrBitlenIPV6(aclass) > 0)
3821     {
3822     DLINK_FOREACH_SAFE(ptr, next_ptr, aclass->list_ipv6.head)
3823     {
3824     cidr = ptr->data;
3825     if (match_ipv6(ip, &cidr->mask, CidrBitlenIPV6(aclass)))
3826     {
3827     cidr->number_on_this_cidr--;
3828     if (cidr->number_on_this_cidr == 0)
3829     {
3830     dlinkDelete(ptr, &aclass->list_ipv6);
3831     MyFree(cidr);
3832     return;
3833     }
3834     }
3835     }
3836     }
3837     #endif
3838     }
3839    
3840     static void
3841     rebuild_cidr_list(int aftype, struct ConfItem *oldcl, struct ClassItem *newcl,
3842     dlink_list *old_list, dlink_list *new_list, int changed)
3843     {
3844     dlink_node *ptr;
3845     struct Client *client_p;
3846     struct ConfItem *conf;
3847     struct AccessItem *aconf;
3848    
3849     if (!changed)
3850     {
3851     *new_list = *old_list;
3852     old_list->head = old_list->tail = NULL;
3853     old_list->length = 0;
3854     return;
3855     }
3856    
3857     DLINK_FOREACH(ptr, local_client_list.head)
3858     {
3859     client_p = ptr->data;
3860     if (client_p->localClient->aftype != aftype)
3861     continue;
3862     if (dlink_list_length(&client_p->localClient->confs) == 0)
3863     continue;
3864    
3865     conf = client_p->localClient->confs.tail->data;
3866     if (conf->type == CLIENT_TYPE)
3867     {
3868     aconf = map_to_conf(conf);
3869     if (aconf->class_ptr == oldcl)
3870     cidr_limit_reached(1, &client_p->localClient->ip, newcl);
3871     }
3872     }
3873     }
3874    
3875     /*
3876     * rebuild_cidr_class
3877     *
3878     * inputs - pointer to old conf
3879     * - pointer to new_class
3880     * output - none
3881     * side effects - rebuilds the class link list of cidr blocks
3882     */
3883     void
3884     rebuild_cidr_class(struct ConfItem *conf, struct ClassItem *new_class)
3885     {
3886     struct ClassItem *old_class = map_to_conf(conf);
3887    
3888     if (NumberPerCidr(old_class) > 0 && NumberPerCidr(new_class) > 0)
3889     {
3890     if (CidrBitlenIPV4(old_class) > 0 && CidrBitlenIPV4(new_class) > 0)
3891     rebuild_cidr_list(AF_INET, conf, new_class,
3892     &old_class->list_ipv4, &new_class->list_ipv4,
3893     CidrBitlenIPV4(old_class) != CidrBitlenIPV4(new_class));
3894    
3895     #ifdef IPV6
3896     if (CidrBitlenIPV6(old_class) > 0 && CidrBitlenIPV6(new_class) > 0)
3897     rebuild_cidr_list(AF_INET6, conf, new_class,
3898     &old_class->list_ipv6, &new_class->list_ipv6,
3899     CidrBitlenIPV6(old_class) != CidrBitlenIPV6(new_class));
3900     #endif
3901     }
3902    
3903     destroy_cidr_class(old_class);
3904     }
3905    
3906     /*
3907     * destroy_cidr_list
3908     *
3909     * inputs - pointer to class dlink list of cidr blocks
3910     * output - none
3911     * side effects - completely destroys the class link list of cidr blocks
3912     */
3913     static void
3914     destroy_cidr_list(dlink_list *list)
3915     {
3916 michael 671 dlink_node *ptr = NULL, *next_ptr = NULL;
3917 adx 30
3918     DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
3919     {
3920     dlinkDelete(ptr, list);
3921 michael 671 MyFree(ptr->data);
3922 adx 30 }
3923     }
3924    
3925     /*
3926     * destroy_cidr_class
3927     *
3928     * inputs - pointer to class
3929     * output - none
3930     * side effects - completely destroys the class link list of cidr blocks
3931     */
3932     static void
3933     destroy_cidr_class(struct ClassItem *aclass)
3934     {
3935     destroy_cidr_list(&aclass->list_ipv4);
3936     destroy_cidr_list(&aclass->list_ipv6);
3937     }

Properties

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