ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 632
Committed: Thu Jun 1 10:53:00 2006 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: 101434 byte(s)
Log Message:
- Added channel::disable_fake_channels which disallows creation of channels
  that have ascii 2, 3, 31 and 160 in their names.
- Minor improvements and cleanups to channel name validation routines
  backported from 7.3

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

Properties

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