ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/conf.c
Revision: 618
Committed: Tue May 23 07:07:53 2006 UTC (17 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/s_conf.c
File size: 101401 byte(s)
Log Message:
- attach_conf():  We even need to increment CurrUserCount if a class got
  attached to a server or operator.  Spotted by stu.
- Removed IRCD_SOCKET_ERROR define

File Contents

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

Properties

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