ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 1285
Committed: Sun Feb 5 15:12:59 2012 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_conf.c
File size: 100850 byte(s)
Log Message:
- added CIDR support for operator{} blocks
- operator "name"{} is no longer supported

File Contents

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

Properties

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