ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 967
Committed: Sun Aug 2 18:05:28 2009 UTC (16 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100641 byte(s)
Log Message:
- added ssl_server_protocol configuration option to servinfo{}.
  valid flags are 'sslv3' and 'tlsv1'

File Contents

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

Properties

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