ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1316
Committed: Tue Mar 27 17:05:51 2012 UTC (13 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/conf.c
File size: 99937 byte(s)
Log Message:
- Removed 'ssl_server_protocol' configuration directive and
  added 'ssl_client_method' and 'ssl_server_method' instead.

  Both of these options can now be changed at runtime.

- src/Makefile.am: swapped order of conf_parser.y and conf_lexer.l
- Update example configuration files

File Contents

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

Properties

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