ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 593
Committed: Fri May 12 05:47:32 2006 UTC (17 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 101676 byte(s)
Log Message:
- Backported RKLINE fix so the user and host portion of a banmask don't get
  cut off after 10 and 63 chars, respectively.
  A split_nuh() rewrite was required for this.
- Removed now unused xstrldup() function

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

Properties

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