ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1353
Committed: Sun Apr 15 18:35:55 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
File size: 99663 byte(s)
Log Message:
- move conf_yy_input and conf_yy_fatal_error to conf_lexer.l
- conf_lexer.l: replace a strcpy with strlcpy

File Contents

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

Properties

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