ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 619
Committed: Tue May 23 07:22:23 2006 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 101431 byte(s)
Log Message:
- Backported r376 (STATS y now shows the total number of clients in a class)
- Rebuilt y.tab.c using bison 2.2

File Contents

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

Properties

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