ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1156
Committed: Tue Aug 9 20:29:20 2011 UTC (12 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 99290 byte(s)
Log Message:
- create ircd-hybrid-8 "branch"

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

Properties

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