ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_conf.c
Revision: 855
Committed: Mon Feb 26 22:06:45 2007 UTC (17 years, 1 month ago) by db
Content type: text/x-csrc
File size: 100729 byte(s)
Log Message:
- fix core in temp channel resv
- remove unused variable in m_join
- update RELNOTES


File Contents

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

Properties

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