ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 671
Committed: Tue Jun 13 07:15:38 2006 UTC (19 years, 2 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 100999 byte(s)
Log Message:
- Fixed class limit bug as spotted by stu.  ("REHASH" would always reset
  current user count)
- Made "STATS y|Y" show inactive (deleted) classes that still have attached
  clients

File Contents

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

Properties

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