ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 885
Committed: Wed Oct 31 18:09:24 2007 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100841 byte(s)
Log Message:
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

File Contents

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

Properties

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