ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/s_conf.c
Revision: 948
Committed: Tue Jul 21 17:34:06 2009 UTC (14 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 100578 byte(s)
Log Message:
- lp64\llp64\ilp32 portability fixes

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

Properties

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