ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/conf.c
Revision: 1921
Committed: Tue Apr 30 14:54:20 2013 UTC (12 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 62625 byte(s)
Log Message:
- Forward-port -r1920 [Dropped PCRE support]

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * 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 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h"
27 #include "ircd_defs.h"
28 #include "conf.h"
29 #include "s_serv.h"
30 #include "resv.h"
31 #include "channel.h"
32 #include "client.h"
33 #include "event.h"
34 #include "hook.h"
35 #include "irc_string.h"
36 #include "s_bsd.h"
37 #include "ircd.h"
38 #include "listener.h"
39 #include "hostmask.h"
40 #include "modules.h"
41 #include "numeric.h"
42 #include "fdlist.h"
43 #include "log.h"
44 #include "send.h"
45 #include "s_gline.h"
46 #include "memory.h"
47 #include "mempool.h"
48 #include "irc_res.h"
49 #include "userhost.h"
50 #include "s_user.h"
51 #include "channel_mode.h"
52 #include "parse.h"
53 #include "s_misc.h"
54 #include "conf_db.h"
55 #include "conf_class.h"
56
57 struct config_server_hide ConfigServerHide;
58
59 /* general conf items link list root, other than k lines etc. */
60 dlink_list service_items = { NULL, NULL, 0 };
61 dlink_list server_items = { NULL, NULL, 0 };
62 dlink_list cluster_items = { NULL, NULL, 0 };
63 dlink_list oconf_items = { NULL, NULL, 0 };
64 dlink_list uconf_items = { NULL, NULL, 0 };
65 dlink_list xconf_items = { NULL, NULL, 0 };
66 dlink_list nresv_items = { NULL, NULL, 0 };
67 dlink_list temporary_resv = { NULL, NULL, 0 };
68
69 extern unsigned int lineno;
70 extern char linebuf[];
71 extern char conffilebuf[IRCD_BUFSIZE];
72 extern int yyparse(); /* defined in y.tab.c */
73
74 struct conf_parser_context conf_parser_ctx = { 0, 0, NULL };
75
76 /* internally defined functions */
77 static void read_conf(FILE *);
78 static void clear_out_old_conf(void);
79 static void expire_tklines(dlink_list *);
80 static void garbage_collect_ip_entries(void);
81 static int hash_ip(struct irc_ssaddr *);
82 static int verify_access(struct Client *);
83 static int attach_iline(struct Client *, struct MaskItem *);
84 static struct ip_entry *find_or_add_ip(struct irc_ssaddr *);
85 static dlink_list *map_to_list(enum maskitem_type);
86 static int find_user_host(struct Client *, char *, char *, char *, unsigned int);
87
88
89 /* usually, with hash tables, you use a prime number...
90 * but in this case I am dealing with ip addresses,
91 * not ascii strings.
92 */
93 #define IP_HASH_SIZE 0x1000
94
95 struct ip_entry
96 {
97 struct irc_ssaddr ip;
98 unsigned int count;
99 time_t last_attempt;
100 struct ip_entry *next;
101 };
102
103 static struct ip_entry *ip_hash_table[IP_HASH_SIZE];
104 static mp_pool_t *ip_entry_pool = NULL;
105 static int ip_entries_count = 0;
106
107
108 /* conf_dns_callback()
109 *
110 * inputs - pointer to struct MaskItem
111 * - pointer to DNSReply reply
112 * output - none
113 * side effects - called when resolver query finishes
114 * if the query resulted in a successful search, hp will contain
115 * a non-null pointer, otherwise hp will be null.
116 * if successful save hp in the conf item it was called with
117 */
118 static void
119 conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
120 {
121 struct MaskItem *conf = vptr;
122
123 conf->dns_pending = 0;
124
125 if (addr != NULL)
126 memcpy(&conf->addr, addr, sizeof(conf->addr));
127 else
128 conf->dns_failed = 1;
129 }
130
131 /* conf_dns_lookup()
132 *
133 * do a nameserver lookup of the conf host
134 * if the conf entry is currently doing a ns lookup do nothing, otherwise
135 * allocate a dns_query and start ns lookup.
136 */
137 static void
138 conf_dns_lookup(struct MaskItem *conf)
139 {
140 if (!conf->dns_pending)
141 {
142 conf->dns_pending = 1;
143 gethost_byname(conf_dns_callback, conf, conf->host);
144 }
145 }
146
147 struct MaskItem *
148 conf_make(enum maskitem_type type)
149 {
150 struct MaskItem *conf = MyMalloc(sizeof(*conf));
151 dlink_list *list = NULL;
152
153 conf->type = type;
154 conf->active = 1;
155 conf->aftype = AF_INET;
156
157 if ((list = map_to_list(type)))
158 dlinkAdd(conf, &conf->node, list);
159 return conf;
160 }
161
162 void
163 conf_free(struct MaskItem *conf)
164 {
165 dlink_node *ptr = NULL, *ptr_next = NULL;
166 dlink_list *list = NULL;
167
168 if (conf->node.next)
169 if ((list = map_to_list(conf->type)))
170 dlinkDelete(&conf->node, list);
171
172 MyFree(conf->name);
173
174 if (conf->dns_pending)
175 delete_resolver_queries(conf);
176 if (conf->passwd != NULL)
177 memset(conf->passwd, 0, strlen(conf->passwd));
178 if (conf->spasswd != NULL)
179 memset(conf->spasswd, 0, strlen(conf->spasswd));
180
181 conf->class = NULL;
182
183 MyFree(conf->passwd);
184 MyFree(conf->spasswd);
185 MyFree(conf->reason);
186 MyFree(conf->user);
187 MyFree(conf->host);
188 #ifdef HAVE_LIBCRYPTO
189 MyFree(conf->cipher_list);
190
191 if (conf->rsa_public_key)
192 RSA_free(conf->rsa_public_key);
193 #endif
194 DLINK_FOREACH_SAFE(ptr, ptr_next, conf->hub_list.head)
195 {
196 MyFree(ptr->data);
197 free_dlink_node(ptr);
198 }
199
200 DLINK_FOREACH_SAFE(ptr, ptr_next, conf->leaf_list.head)
201 {
202 MyFree(ptr->data);
203 free_dlink_node(ptr);
204 }
205
206 DLINK_FOREACH_SAFE(ptr, ptr_next, conf->exempt_list.head)
207 {
208 struct exempt *exptr = ptr->data;
209
210 MyFree(exptr->name);
211 MyFree(exptr->user);
212 MyFree(exptr->host);
213 MyFree(exptr);
214 }
215
216 MyFree(conf);
217 }
218
219 static const struct shared_flags
220 {
221 const unsigned int type;
222 const unsigned char letter;
223 } flag_table[] = {
224 { SHARED_KLINE, 'K' },
225 { SHARED_UNKLINE, 'U' },
226 { SHARED_XLINE, 'X' },
227 { SHARED_UNXLINE, 'Y' },
228 { SHARED_RESV, 'Q' },
229 { SHARED_UNRESV, 'R' },
230 { SHARED_LOCOPS, 'L' },
231 { SHARED_DLINE, 'D' },
232 { SHARED_UNDLINE, 'E' },
233 { 0, '\0' }
234 };
235
236 /*
237 * inputs - pointer to client requesting confitem report
238 * - ConfType to report
239 * output - none
240 * side effects -
241 */
242 void
243 report_confitem_types(struct Client *source_p, enum maskitem_type type)
244 {
245 dlink_node *ptr = NULL, *dptr = NULL;
246 struct MaskItem *conf = NULL;
247 const struct ClassItem *class = NULL;
248 const struct shared_flags *shared = NULL;
249 char buf[12];
250 char *p = NULL;
251
252 switch (type)
253 {
254 case CONF_XLINE:
255 DLINK_FOREACH(ptr, xconf_items.head)
256 {
257 conf = ptr->data;
258
259 sendto_one(source_p, form_str(RPL_STATSXLINE),
260 me.name, source_p->name,
261 conf->until ? 'x': 'X', conf->count,
262 conf->name, conf->reason);
263 }
264 break;
265
266 case CONF_ULINE:
267 shared = flag_table;
268 DLINK_FOREACH(ptr, uconf_items.head)
269 {
270 conf = ptr->data;
271
272 p = buf;
273
274 *p++ = 'c';
275 for (; shared->type; ++shared)
276 if (shared->type & conf->flags)
277 *p++ = shared->letter;
278 else
279 *p++ = ToLower(shared->letter);
280
281 sendto_one(source_p, form_str(RPL_STATSULINE),
282 me.name, source_p->name, conf->name,
283 conf->user?conf->user: "*",
284 conf->host?conf->host: "*", buf);
285 }
286
287 shared = flag_table;
288 DLINK_FOREACH(ptr, cluster_items.head)
289 {
290 conf = ptr->data;
291
292 p = buf;
293
294 *p++ = 'C';
295 for (; shared->type; ++shared)
296 if (shared->type & conf->flags)
297 *p++ = shared->letter;
298 else
299 *p++ = ToLower(shared->letter);
300
301 sendto_one(source_p, form_str(RPL_STATSULINE),
302 me.name, source_p->name, conf->name,
303 "*", "*", buf);
304 }
305
306 break;
307
308 case CONF_OPER:
309 DLINK_FOREACH(ptr, oconf_items.head)
310 {
311 conf = ptr->data;
312
313 /* Don't allow non opers to see oper privs */
314 if (HasUMode(source_p, UMODE_OPER))
315 sendto_one(source_p, form_str(RPL_STATSOLINE),
316 me.name, source_p->name, 'O', conf->user, conf->host,
317 conf->name, oper_privs_as_string(conf->port),
318 conf->class ? conf->class->name : "<default>");
319 else
320 sendto_one(source_p, form_str(RPL_STATSOLINE),
321 me.name, source_p->name, 'O', conf->user, conf->host,
322 conf->name, "0",
323 conf->class ? conf->class->name : "<default>");
324 }
325 break;
326
327 case CONF_CLASS:
328 DLINK_FOREACH(ptr, class_get_list()->head)
329 {
330 class = ptr->data;
331 sendto_one(source_p, form_str(RPL_STATSYLINE),
332 me.name, source_p->name, 'Y',
333 class->name, class->ping_freq,
334 class->con_freq,
335 class->max_total, class->max_sendq,
336 class->max_recvq,
337 class->ref_count,
338 class->number_per_cidr, class->cidr_bitlen_ipv4,
339 class->number_per_cidr, class->cidr_bitlen_ipv6,
340 class->active ? "active" : "disabled");
341 }
342 break;
343
344 case CONF_SERVICE:
345 DLINK_FOREACH(ptr, service_items.head)
346 {
347 conf = ptr->data;
348 sendto_one(source_p, form_str(RPL_STATSSERVICE),
349 me.name, source_p->name, 'S', "*", conf->name, 0, 0);
350 }
351 break;
352
353 case CONF_SERVER:
354 DLINK_FOREACH(ptr, server_items.head)
355 {
356 p = buf;
357 conf = ptr->data;
358
359 buf[0] = '\0';
360
361 if (IsConfAllowAutoConn(conf))
362 *p++ = 'A';
363 if (IsConfSSL(conf))
364 *p++ = 'S';
365 if (buf[0] == '\0')
366 *p++ = '*';
367
368 *p = '\0';
369
370 /*
371 * Allow admins to see actual ips unless hide_server_ips is enabled
372 */
373 if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
374 sendto_one(source_p, form_str(RPL_STATSCLINE),
375 me.name, source_p->name, 'C', conf->host,
376 buf, conf->name, conf->port,
377 conf->class ? conf->class->name : "<default>");
378 else
379 sendto_one(source_p, form_str(RPL_STATSCLINE),
380 me.name, source_p->name, 'C',
381 "*@127.0.0.1", buf, conf->name, conf->port,
382 conf->class ? conf->class->name : "<default>");
383 }
384 break;
385
386 case CONF_HUB:
387 DLINK_FOREACH(ptr, server_items.head)
388 {
389 conf = ptr->data;
390
391 DLINK_FOREACH(dptr, conf->hub_list.head)
392 sendto_one(source_p, form_str(RPL_STATSHLINE), me.name,
393 source_p->name, 'H', dptr->data, conf->name, 0, "*");
394 }
395
396 DLINK_FOREACH(ptr, server_items.head)
397 {
398 conf = ptr->data;
399
400 DLINK_FOREACH(dptr, conf->leaf_list.head)
401 sendto_one(source_p, form_str(RPL_STATSLLINE), me.name,
402 source_p->name, 'L', dptr->data, conf->name, 0, "*");
403 }
404
405 break;
406
407 default:
408 break;
409 }
410 }
411
412 /* check_client()
413 *
414 * inputs - pointer to client
415 * output - 0 = Success
416 * NOT_AUTHORIZED (-1) = Access denied (no I line match)
417 * IRCD_SOCKET_ERROR (-2) = Bad socket.
418 * I_LINE_FULL (-3) = I-line is full
419 * TOO_MANY (-4) = Too many connections from hostname
420 * BANNED_CLIENT (-5) = K-lined
421 * side effects - Ordinary client access check.
422 * Look for conf lines which have the same
423 * status as the flags passed.
424 */
425 int
426 check_client(struct Client *source_p)
427 {
428 int i;
429
430 if ((i = verify_access(source_p)))
431 ilog(LOG_TYPE_IRCD, "Access denied: %s[%s]",
432 source_p->name, source_p->sockhost);
433
434 switch (i)
435 {
436 case TOO_MANY:
437 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
438 "Too many on IP for %s (%s).",
439 get_client_name(source_p, SHOW_IP),
440 source_p->sockhost);
441 ilog(LOG_TYPE_IRCD, "Too many connections on IP from %s.",
442 get_client_name(source_p, SHOW_IP));
443 ++ServerStats.is_ref;
444 exit_client(source_p, &me, "No more connections allowed on that IP");
445 break;
446
447 case I_LINE_FULL:
448 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
449 "auth{} block is full for %s (%s).",
450 get_client_name(source_p, SHOW_IP),
451 source_p->sockhost);
452 ilog(LOG_TYPE_IRCD, "Too many connections from %s.",
453 get_client_name(source_p, SHOW_IP));
454 ++ServerStats.is_ref;
455 exit_client(source_p, &me,
456 "No more connections allowed in your connection class");
457 break;
458
459 case NOT_AUTHORIZED:
460 ++ServerStats.is_ref;
461 /* jdc - lists server name & port connections are on */
462 /* a purely cosmetical change */
463 sendto_realops_flags(UMODE_UNAUTH, L_ALL, SEND_NOTICE,
464 "Unauthorized client connection from %s [%s] on [%s/%u].",
465 get_client_name(source_p, SHOW_IP),
466 source_p->sockhost,
467 source_p->localClient->listener->name,
468 source_p->localClient->listener->port);
469 ilog(LOG_TYPE_IRCD,
470 "Unauthorized client connection from %s on [%s/%u].",
471 get_client_name(source_p, SHOW_IP),
472 source_p->localClient->listener->name,
473 source_p->localClient->listener->port);
474
475 exit_client(source_p, &me, "You are not authorized to use this server");
476 break;
477
478 case BANNED_CLIENT:
479 exit_client(source_p, &me, "Banned");
480 ++ServerStats.is_ref;
481 break;
482
483 case 0:
484 default:
485 break;
486 }
487
488 return (i < 0 ? 0 : 1);
489 }
490
491 /* verify_access()
492 *
493 * inputs - pointer to client to verify
494 * output - 0 if success -'ve if not
495 * side effect - find the first (best) I line to attach.
496 */
497 static int
498 verify_access(struct Client *client_p)
499 {
500 struct MaskItem *conf = NULL, *rkconf = NULL;
501 char non_ident[USERLEN + 1] = { '~', '\0' };
502
503 if (IsGotId(client_p))
504 {
505 conf = find_address_conf(client_p->host, client_p->username,
506 &client_p->localClient->ip,
507 client_p->localClient->aftype,
508 client_p->localClient->passwd);
509 }
510 else
511 {
512 strlcpy(non_ident+1, client_p->username, sizeof(non_ident)-1);
513 conf = find_address_conf(client_p->host,non_ident,
514 &client_p->localClient->ip,
515 client_p->localClient->aftype,
516 client_p->localClient->passwd);
517 }
518
519 if (conf != NULL)
520 {
521 if (IsConfClient(conf))
522 {
523 if (IsConfRedir(conf))
524 {
525 sendto_one(client_p, form_str(RPL_REDIR),
526 me.name, client_p->name,
527 conf->name ? conf->name : "",
528 conf->port);
529 return(NOT_AUTHORIZED);
530 }
531
532 if (IsConfDoIdentd(conf))
533 SetNeedId(client_p);
534
535 /* Thanks for spoof idea amm */
536 if (IsConfDoSpoofIp(conf))
537 {
538 if (!ConfigFileEntry.hide_spoof_ips && IsConfSpoofNotice(conf))
539 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
540 "%s spoofing: %s as %s",
541 client_p->name, client_p->host, conf->name);
542 strlcpy(client_p->host, conf->name, sizeof(client_p->host));
543 SetIPSpoof(client_p);
544 }
545
546 return(attach_iline(client_p, conf));
547 }
548 else if (IsConfKill(conf) || (ConfigFileEntry.glines && IsConfGline(conf)))
549 {
550 if (IsConfGline(conf))
551 sendto_one(client_p, ":%s NOTICE %s :*** G-lined", me.name,
552 client_p->name);
553 sendto_one(client_p, ":%s NOTICE %s :*** Banned: %s",
554 me.name, client_p->name, conf->reason);
555 return(BANNED_CLIENT);
556 }
557 }
558
559 return(NOT_AUTHORIZED);
560 }
561
562 /* attach_iline()
563 *
564 * inputs - client pointer
565 * - conf pointer
566 * output -
567 * side effects - do actual attach
568 */
569 static int
570 attach_iline(struct Client *client_p, struct MaskItem *conf)
571 {
572 struct ClassItem *class = NULL;
573 struct ip_entry *ip_found;
574 int a_limit_reached = 0;
575 unsigned int local = 0, global = 0, ident = 0;
576
577 ip_found = find_or_add_ip(&client_p->localClient->ip);
578 ip_found->count++;
579 SetIpHash(client_p);
580
581 if (conf->class == NULL)
582 return NOT_AUTHORIZED; /* If class is missing, this is best */
583
584 class = conf->class;
585
586 count_user_host(client_p->username, client_p->host,
587 &global, &local, &ident);
588
589 /* XXX blah. go down checking the various silly limits
590 * setting a_limit_reached if any limit is reached.
591 * - Dianora
592 */
593 if (class->max_total != 0 && class->ref_count >= class->max_total)
594 a_limit_reached = 1;
595 else if (class->max_perip != 0 && ip_found->count > class->max_perip)
596 a_limit_reached = 1;
597 else if (class->max_local != 0 && local >= class->max_local)
598 a_limit_reached = 1;
599 else if (class->max_global != 0 && global >= class->max_global)
600 a_limit_reached = 1;
601 else if (class->max_ident != 0 && ident >= class->max_ident &&
602 client_p->username[0] != '~')
603 a_limit_reached = 1;
604
605 if (a_limit_reached)
606 {
607 if (!IsConfExemptLimits(conf))
608 return TOO_MANY; /* Already at maximum allowed */
609
610 sendto_one(client_p,
611 ":%s NOTICE %s :*** Your connection class is full, "
612 "but you have exceed_limit = yes;", me.name, client_p->name);
613 }
614
615 return attach_conf(client_p, conf);
616 }
617
618 /* init_ip_hash_table()
619 *
620 * inputs - NONE
621 * output - NONE
622 * side effects - allocate memory for ip_entry(s)
623 * - clear the ip hash table
624 */
625 void
626 init_ip_hash_table(void)
627 {
628 ip_entry_pool = mp_pool_new(sizeof(struct ip_entry),
629 2 * hard_fdlimit);
630 memset(ip_hash_table, 0, sizeof(ip_hash_table));
631 }
632
633 /* find_or_add_ip()
634 *
635 * inputs - pointer to struct irc_ssaddr
636 * output - pointer to a struct ip_entry
637 * side effects -
638 *
639 * If the ip # was not found, a new struct ip_entry is created, and the ip
640 * count set to 0.
641 */
642 static struct ip_entry *
643 find_or_add_ip(struct irc_ssaddr *ip_in)
644 {
645 struct ip_entry *ptr, *newptr;
646 int hash_index = hash_ip(ip_in), res;
647 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
648 #ifdef IPV6
649 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
650 #endif
651
652 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
653 {
654 #ifdef IPV6
655 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
656 continue;
657 if (ip_in->ss.ss_family == AF_INET6)
658 {
659 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
660 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
661 }
662 else
663 #endif
664 {
665 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
666 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
667 }
668 if (res == 0)
669 {
670 /* Found entry already in hash, return it. */
671 return ptr;
672 }
673 }
674
675 if (ip_entries_count >= 2 * hard_fdlimit)
676 garbage_collect_ip_entries();
677
678 newptr = mp_pool_get(ip_entry_pool);
679 memset(newptr, 0, sizeof(*newptr));
680 ip_entries_count++;
681 memcpy(&newptr->ip, ip_in, sizeof(struct irc_ssaddr));
682
683 newptr->next = ip_hash_table[hash_index];
684 ip_hash_table[hash_index] = newptr;
685
686 return newptr;
687 }
688
689 /* remove_one_ip()
690 *
691 * inputs - unsigned long IP address value
692 * output - NONE
693 * side effects - The ip address given, is looked up in ip hash table
694 * and number of ip#'s for that ip decremented.
695 * If ip # count reaches 0 and has expired,
696 * the struct ip_entry is returned to the ip_entry_heap
697 */
698 void
699 remove_one_ip(struct irc_ssaddr *ip_in)
700 {
701 struct ip_entry *ptr;
702 struct ip_entry *last_ptr = NULL;
703 int hash_index = hash_ip(ip_in), res;
704 struct sockaddr_in *v4 = (struct sockaddr_in *)ip_in, *ptr_v4;
705 #ifdef IPV6
706 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)ip_in, *ptr_v6;
707 #endif
708
709 for (ptr = ip_hash_table[hash_index]; ptr; ptr = ptr->next)
710 {
711 #ifdef IPV6
712 if (ptr->ip.ss.ss_family != ip_in->ss.ss_family)
713 continue;
714 if (ip_in->ss.ss_family == AF_INET6)
715 {
716 ptr_v6 = (struct sockaddr_in6 *)&ptr->ip;
717 res = memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr));
718 }
719 else
720 #endif
721 {
722 ptr_v4 = (struct sockaddr_in *)&ptr->ip;
723 res = memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr));
724 }
725 if (res)
726 continue;
727 if (ptr->count > 0)
728 ptr->count--;
729 if (ptr->count == 0 &&
730 (CurrentTime-ptr->last_attempt) >= ConfigFileEntry.throttle_time)
731 {
732 if (last_ptr != NULL)
733 last_ptr->next = ptr->next;
734 else
735 ip_hash_table[hash_index] = ptr->next;
736
737 mp_pool_release(ptr);
738 ip_entries_count--;
739 return;
740 }
741 last_ptr = ptr;
742 }
743 }
744
745 /* hash_ip()
746 *
747 * input - pointer to an irc_inaddr
748 * output - integer value used as index into hash table
749 * side effects - hopefully, none
750 */
751 static int
752 hash_ip(struct irc_ssaddr *addr)
753 {
754 if (addr->ss.ss_family == AF_INET)
755 {
756 struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
757 int hash;
758 uint32_t ip;
759
760 ip = ntohl(v4->sin_addr.s_addr);
761 hash = ((ip >> 12) + ip) & (IP_HASH_SIZE-1);
762 return hash;
763 }
764 #ifdef IPV6
765 else
766 {
767 int hash;
768 struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr;
769 uint32_t *ip = (uint32_t *)&v6->sin6_addr.s6_addr;
770
771 hash = ip[0] ^ ip[3];
772 hash ^= hash >> 16;
773 hash ^= hash >> 8;
774 hash = hash & (IP_HASH_SIZE - 1);
775 return hash;
776 }
777 #else
778 return 0;
779 #endif
780 }
781
782 /* count_ip_hash()
783 *
784 * inputs - pointer to counter of number of ips hashed
785 * - pointer to memory used for ip hash
786 * output - returned via pointers input
787 * side effects - NONE
788 *
789 * number of hashed ip #'s is counted up, plus the amount of memory
790 * used in the hash.
791 */
792 void
793 count_ip_hash(unsigned int *number_ips_stored, uint64_t *mem_ips_stored)
794 {
795 struct ip_entry *ptr;
796 int i;
797
798 *number_ips_stored = 0;
799 *mem_ips_stored = 0;
800
801 for (i = 0; i < IP_HASH_SIZE; i++)
802 {
803 for (ptr = ip_hash_table[i]; ptr; ptr = ptr->next)
804 {
805 *number_ips_stored += 1;
806 *mem_ips_stored += sizeof(struct ip_entry);
807 }
808 }
809 }
810
811 /* garbage_collect_ip_entries()
812 *
813 * input - NONE
814 * output - NONE
815 * side effects - free up all ip entries with no connections
816 */
817 static void
818 garbage_collect_ip_entries(void)
819 {
820 struct ip_entry *ptr;
821 struct ip_entry *last_ptr;
822 struct ip_entry *next_ptr;
823 int i;
824
825 for (i = 0; i < IP_HASH_SIZE; i++)
826 {
827 last_ptr = NULL;
828
829 for (ptr = ip_hash_table[i]; ptr; ptr = next_ptr)
830 {
831 next_ptr = ptr->next;
832
833 if (ptr->count == 0 &&
834 (CurrentTime - ptr->last_attempt) >= ConfigFileEntry.throttle_time)
835 {
836 if (last_ptr != NULL)
837 last_ptr->next = ptr->next;
838 else
839 ip_hash_table[i] = ptr->next;
840 mp_pool_release(ptr);
841 ip_entries_count--;
842 }
843 else
844 last_ptr = ptr;
845 }
846 }
847 }
848
849 /* detach_conf()
850 *
851 * inputs - pointer to client to detach
852 * - type of conf to detach
853 * output - 0 for success, -1 for failure
854 * side effects - Disassociate configuration from the client.
855 * Also removes a class from the list if marked for deleting.
856 */
857 void
858 detach_conf(struct Client *client_p, enum maskitem_type type)
859 {
860 dlink_node *ptr = NULL, *next_ptr = NULL;
861
862 DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->confs.head)
863 {
864 struct MaskItem *conf = ptr->data;
865
866 assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
867 assert(conf->ref_count > 0);
868 assert(conf->class->ref_count > 0);
869
870 if (!(conf->type & type))
871 continue;
872
873 dlinkDelete(ptr, &client_p->localClient->confs);
874 free_dlink_node(ptr);
875
876 if (conf->type == CONF_CLIENT)
877 remove_from_cidr_check(&client_p->localClient->ip, conf->class);
878
879 if (--conf->class->ref_count == 0 && conf->class->active == 0)
880 {
881 class_free(conf->class);
882 conf->class = NULL;
883 }
884
885 if (--conf->ref_count == 0 && conf->active == 0)
886 conf_free(conf);
887 }
888 }
889
890 /* attach_conf()
891 *
892 * inputs - client pointer
893 * - conf pointer
894 * output -
895 * side effects - Associate a specific configuration entry to a *local*
896 * client (this is the one which used in accepting the
897 * connection). Note, that this automatically changes the
898 * attachment if there was an old one...
899 */
900 int
901 attach_conf(struct Client *client_p, struct MaskItem *conf)
902 {
903 if (dlinkFind(&client_p->localClient->confs, conf) != NULL)
904 return 1;
905
906 if (conf->type == CONF_CLIENT)
907 if (cidr_limit_reached(IsConfExemptLimits(conf),
908 &client_p->localClient->ip, conf->class))
909 return TOO_MANY; /* Already at maximum allowed */
910
911 conf->class->ref_count++;
912 conf->ref_count++;
913
914 dlinkAdd(conf, make_dlink_node(), &client_p->localClient->confs);
915
916 return 0;
917 }
918
919 /* attach_connect_block()
920 *
921 * inputs - pointer to server to attach
922 * - name of server
923 * - hostname of server
924 * output - true (1) if both are found, otherwise return false (0)
925 * side effects - find connect block and attach them to connecting client
926 */
927 int
928 attach_connect_block(struct Client *client_p, const char *name,
929 const char *host)
930 {
931 dlink_node *ptr;
932 struct MaskItem *conf = NULL;
933
934 assert(client_p != NULL);
935 assert(host != NULL);
936
937 if (client_p == NULL || host == NULL)
938 return 0;
939
940 DLINK_FOREACH(ptr, server_items.head)
941 {
942 conf = ptr->data;
943
944 if (match(conf->name, name) || match(conf->host, host))
945 continue;
946
947 attach_conf(client_p, conf);
948 return -1;
949 }
950
951 return 0;
952 }
953
954 /* find_conf_name()
955 *
956 * inputs - pointer to conf link list to search
957 * - pointer to name to find
958 * - int mask of type of conf to find
959 * output - NULL or pointer to conf found
960 * side effects - find a conf entry which matches the name
961 * and has the given mask.
962 */
963 struct MaskItem *
964 find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
965 {
966 dlink_node *ptr;
967 struct MaskItem* conf;
968
969 DLINK_FOREACH(ptr, list->head)
970 {
971 conf = ptr->data;
972
973 if (conf->type == type)
974 {
975 if (conf->name && (irccmp(conf->name, name) == 0 ||
976 !match(conf->name, name)))
977 return conf;
978 }
979 }
980
981 return NULL;
982 }
983
984 /* map_to_list()
985 *
986 * inputs - ConfType conf
987 * output - pointer to dlink_list to use
988 * side effects - none
989 */
990 static dlink_list *
991 map_to_list(enum maskitem_type type)
992 {
993 switch(type)
994 {
995 case CONF_XLINE:
996 return(&xconf_items);
997 break;
998 case CONF_ULINE:
999 return(&uconf_items);
1000 break;
1001 case CONF_NRESV:
1002 return(&nresv_items);
1003 break;
1004 case CONF_CRESV:
1005 return(&resv_channel_list);
1006 case CONF_OPER:
1007 return(&oconf_items);
1008 break;
1009 case CONF_SERVER:
1010 return(&server_items);
1011 break;
1012 case CONF_SERVICE:
1013 return(&service_items);
1014 break;
1015 case CONF_CLUSTER:
1016 return(&cluster_items);
1017 break;
1018 default:
1019 return NULL;
1020 }
1021 }
1022
1023 /* find_matching_name_conf()
1024 *
1025 * inputs - type of link list to look in
1026 * - pointer to name string to find
1027 * - pointer to user
1028 * - pointer to host
1029 * - optional flags to match on as well
1030 * output - NULL or pointer to found struct MaskItem
1031 * side effects - looks for a match on name field
1032 */
1033 struct MaskItem *
1034 find_matching_name_conf(enum maskitem_type type, const char *name, const char *user,
1035 const char *host, unsigned int flags)
1036 {
1037 dlink_node *ptr=NULL;
1038 struct MaskItem *conf=NULL;
1039 dlink_list *list_p = map_to_list(type);
1040
1041 switch (type)
1042 {
1043 case CONF_SERVICE:
1044 DLINK_FOREACH(ptr, list_p->head)
1045 {
1046 conf = ptr->data;
1047
1048 if (EmptyString(conf->name))
1049 continue;
1050 if ((name != NULL) && !irccmp(name, conf->name))
1051 return conf;
1052 }
1053 break;
1054
1055 case CONF_XLINE:
1056 case CONF_ULINE:
1057 case CONF_NRESV:
1058 case CONF_CRESV:
1059 DLINK_FOREACH(ptr, list_p->head)
1060 {
1061 conf = ptr->data;
1062
1063 if (EmptyString(conf->name))
1064 continue;
1065 if ((name != NULL) && !match(conf->name, name))
1066 {
1067 if ((user == NULL && (host == NULL)))
1068 return conf;
1069 if ((conf->flags & flags) != flags)
1070 continue;
1071 if (EmptyString(conf->user) || EmptyString(conf->host))
1072 return conf;
1073 if (!match(conf->user, user) && !match(conf->host, host))
1074 return conf;
1075 }
1076 }
1077 break;
1078
1079 case CONF_SERVER:
1080 DLINK_FOREACH(ptr, list_p->head)
1081 {
1082 conf = ptr->data;
1083
1084 if ((name != NULL) && !match(name, conf->name))
1085 return conf;
1086 else if ((host != NULL) && !match(host, conf->host))
1087 return conf;
1088 }
1089 break;
1090
1091 default:
1092 break;
1093 }
1094 return NULL;
1095 }
1096
1097 /* find_exact_name_conf()
1098 *
1099 * inputs - type of link list to look in
1100 * - pointer to name string to find
1101 * - pointer to user
1102 * - pointer to host
1103 * output - NULL or pointer to found struct MaskItem
1104 * side effects - looks for an exact match on name field
1105 */
1106 struct MaskItem *
1107 find_exact_name_conf(enum maskitem_type type, const struct Client *who, const char *name,
1108 const char *user, const char *host)
1109 {
1110 dlink_node *ptr = NULL;
1111 struct MaskItem *conf;
1112 dlink_list *list_p = map_to_list(type);
1113
1114 switch(type)
1115 {
1116 case CONF_XLINE:
1117 case CONF_ULINE:
1118 case CONF_NRESV:
1119 case CONF_CRESV:
1120
1121 DLINK_FOREACH(ptr, list_p->head)
1122 {
1123 conf = ptr->data;
1124
1125 if (EmptyString(conf->name))
1126 continue;
1127
1128 if (irccmp(conf->name, name) == 0)
1129 {
1130 if ((user == NULL && (host == NULL)))
1131 return (conf);
1132 if (EmptyString(conf->user) || EmptyString(conf->host))
1133 return (conf);
1134 if (!match(conf->user, user) && !match(conf->host, host))
1135 return (conf);
1136 }
1137 }
1138 break;
1139
1140 case CONF_OPER:
1141 DLINK_FOREACH(ptr, list_p->head)
1142 {
1143 conf = ptr->data;
1144
1145 if (EmptyString(conf->name))
1146 continue;
1147
1148 if (!irccmp(conf->name, name))
1149 {
1150 if (!who)
1151 return conf;
1152 if (EmptyString(conf->user) || EmptyString(conf->host))
1153 return NULL;
1154 if (!match(conf->user, who->username))
1155 {
1156 switch (conf->htype)
1157 {
1158 case HM_HOST:
1159 if (!match(conf->host, who->host) || !match(conf->host, who->sockhost))
1160 if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
1161 return conf;
1162 break;
1163 case HM_IPV4:
1164 if (who->localClient->aftype == AF_INET)
1165 if (match_ipv4(&who->localClient->ip, &conf->addr, conf->bits))
1166 if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
1167 return conf;
1168 break;
1169 #ifdef IPV6
1170 case HM_IPV6:
1171 if (who->localClient->aftype == AF_INET6)
1172 if (match_ipv6(&who->localClient->ip, &conf->addr, conf->bits))
1173 if (!conf->class->max_total || conf->class->ref_count < conf->class->max_total)
1174 return conf;
1175 break;
1176 #endif
1177 default:
1178 assert(0);
1179 }
1180 }
1181 }
1182 }
1183
1184 break;
1185
1186 case CONF_SERVER:
1187 DLINK_FOREACH(ptr, list_p->head)
1188 {
1189 conf = ptr->data;
1190
1191 if (EmptyString(conf->name))
1192 continue;
1193
1194 if (name == NULL)
1195 {
1196 if (EmptyString(conf->host))
1197 continue;
1198 if (irccmp(conf->host, host) == 0)
1199 return(conf);
1200 }
1201 else if (irccmp(conf->name, name) == 0)
1202 {
1203 return (conf);
1204 }
1205 }
1206 break;
1207
1208 default:
1209 break;
1210 }
1211 return(NULL);
1212 }
1213
1214 /* rehash()
1215 *
1216 * Actual REHASH service routine. Called with sig == 0 if it has been called
1217 * as a result of an operator issuing this command, else assume it has been
1218 * called as a result of the server receiving a HUP signal.
1219 */
1220 int
1221 rehash(int sig)
1222 {
1223 if (sig != 0)
1224 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1225 "Got signal SIGHUP, reloading ircd.conf file");
1226
1227 restart_resolver();
1228
1229 /* don't close listeners until we know we can go ahead with the rehash */
1230
1231 /* Check to see if we magically got(or lost) IPv6 support */
1232 check_can_use_v6();
1233
1234 read_conf_files(0);
1235
1236 if (ServerInfo.description != NULL)
1237 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
1238
1239 load_conf_modules();
1240
1241 rehashed_klines = 1;
1242
1243 return 0;
1244 }
1245
1246 /* set_default_conf()
1247 *
1248 * inputs - NONE
1249 * output - NONE
1250 * side effects - Set default values here.
1251 * This is called **PRIOR** to parsing the
1252 * configuration file. If you want to do some validation
1253 * of values later, put them in validate_conf().
1254 */
1255 static void
1256 set_default_conf(void)
1257 {
1258 /* verify init_class() ran, this should be an unnecessary check
1259 * but its not much work.
1260 */
1261 assert(class_default == class_get_list()->tail->data);
1262
1263 #ifdef HAVE_LIBCRYPTO
1264 ServerInfo.rsa_private_key = NULL;
1265 ServerInfo.rsa_private_key_file = NULL;
1266 #endif
1267
1268 /* ServerInfo.name is not rehashable */
1269 /* ServerInfo.name = ServerInfo.name; */
1270 ServerInfo.description = NULL;
1271 ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1272 ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1273
1274 memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
1275 ServerInfo.specific_ipv4_vhost = 0;
1276 memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
1277 ServerInfo.specific_ipv6_vhost = 0;
1278
1279 ServerInfo.max_clients = MAXCLIENTS_MAX;
1280 ServerInfo.max_nick_length = 9;
1281 ServerInfo.max_topic_length = 80;
1282
1283 ServerInfo.hub = 0;
1284 ServerInfo.dns_host.sin_addr.s_addr = 0;
1285 ServerInfo.dns_host.sin_port = 0;
1286 AdminInfo.name = NULL;
1287 AdminInfo.email = NULL;
1288 AdminInfo.description = NULL;
1289
1290 log_del_all();
1291
1292 ConfigLoggingEntry.use_logging = 1;
1293
1294 ConfigChannel.disable_fake_channels = 0;
1295 ConfigChannel.knock_delay = 300;
1296 ConfigChannel.knock_delay_channel = 60;
1297 ConfigChannel.max_chans_per_user = 25;
1298 ConfigChannel.max_chans_per_oper = 50;
1299 ConfigChannel.quiet_on_ban = 1;
1300 ConfigChannel.max_bans = 25;
1301 ConfigChannel.default_split_user_count = 0;
1302 ConfigChannel.default_split_server_count = 0;
1303 ConfigChannel.no_join_on_split = 0;
1304 ConfigChannel.no_create_on_split = 0;
1305
1306 ConfigServerHide.flatten_links = 0;
1307 ConfigServerHide.links_delay = 300;
1308 ConfigServerHide.hidden = 0;
1309 ConfigServerHide.hide_servers = 0;
1310 ConfigServerHide.hide_services = 0;
1311 ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
1312 ConfigServerHide.hide_server_ips = 0;
1313
1314
1315 ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1316 ConfigFileEntry.max_watch = WATCHSIZE_DEFAULT;
1317 ConfigFileEntry.glines = 0;
1318 ConfigFileEntry.gline_time = 12 * 3600;
1319 ConfigFileEntry.gline_request_time = GLINE_REQUEST_EXPIRE_DEFAULT;
1320 ConfigFileEntry.gline_min_cidr = 16;
1321 ConfigFileEntry.gline_min_cidr6 = 48;
1322 ConfigFileEntry.invisible_on_connect = 1;
1323 ConfigFileEntry.tkline_expire_notices = 1;
1324 ConfigFileEntry.hide_spoof_ips = 1;
1325 ConfigFileEntry.ignore_bogus_ts = 0;
1326 ConfigFileEntry.disable_auth = 0;
1327 ConfigFileEntry.disable_remote = 0;
1328 ConfigFileEntry.kill_chase_time_limit = 90;
1329 ConfigFileEntry.default_floodcount = 8;
1330 ConfigFileEntry.failed_oper_notice = 1;
1331 ConfigFileEntry.dots_in_ident = 0;
1332 ConfigFileEntry.min_nonwildcard = 4;
1333 ConfigFileEntry.min_nonwildcard_simple = 3;
1334 ConfigFileEntry.max_accept = 20;
1335 ConfigFileEntry.anti_nick_flood = 0;
1336 ConfigFileEntry.max_nick_time = 20;
1337 ConfigFileEntry.max_nick_changes = 5;
1338 ConfigFileEntry.anti_spam_exit_message_time = 0;
1339 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1340 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1341 ConfigFileEntry.warn_no_nline = 1;
1342 ConfigFileEntry.stats_o_oper_only = 0;
1343 ConfigFileEntry.stats_k_oper_only = 1; /* masked */
1344 ConfigFileEntry.stats_i_oper_only = 1; /* masked */
1345 ConfigFileEntry.stats_P_oper_only = 0;
1346 ConfigFileEntry.caller_id_wait = 60;
1347 ConfigFileEntry.opers_bypass_callerid = 0;
1348 ConfigFileEntry.pace_wait = 10;
1349 ConfigFileEntry.pace_wait_simple = 1;
1350 ConfigFileEntry.short_motd = 0;
1351 ConfigFileEntry.ping_cookie = 0;
1352 ConfigFileEntry.no_oper_flood = 0;
1353 ConfigFileEntry.true_no_oper_flood = 0;
1354 ConfigFileEntry.oper_pass_resv = 1;
1355 ConfigFileEntry.max_targets = MAX_TARGETS_DEFAULT;
1356 ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
1357 ConfigFileEntry.oper_umodes = UMODE_BOTS | UMODE_LOCOPS | UMODE_SERVNOTICE |
1358 UMODE_OPERWALL | UMODE_WALLOP;
1359 ConfigFileEntry.use_egd = 0;
1360 ConfigFileEntry.egdpool_path = NULL;
1361 ConfigFileEntry.throttle_time = 10;
1362 }
1363
1364 static void
1365 validate_conf(void)
1366 {
1367 if (ConfigFileEntry.ts_warn_delta < TS_WARN_DELTA_MIN)
1368 ConfigFileEntry.ts_warn_delta = TS_WARN_DELTA_DEFAULT;
1369
1370 if (ConfigFileEntry.ts_max_delta < TS_MAX_DELTA_MIN)
1371 ConfigFileEntry.ts_max_delta = TS_MAX_DELTA_DEFAULT;
1372
1373 if (ServerInfo.network_name == NULL)
1374 ServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
1375
1376 if (ServerInfo.network_desc == NULL)
1377 ServerInfo.network_desc = xstrdup(NETWORK_DESC_DEFAULT);
1378
1379 if (ConfigFileEntry.service_name == NULL)
1380 ConfigFileEntry.service_name = xstrdup(SERVICE_NAME_DEFAULT);
1381
1382 ConfigFileEntry.max_watch = IRCD_MAX(ConfigFileEntry.max_watch, WATCHSIZE_MIN);
1383 }
1384
1385 /* read_conf()
1386 *
1387 * inputs - file descriptor pointing to config file to use
1388 * output - None
1389 * side effects - Read configuration file.
1390 */
1391 static void
1392 read_conf(FILE *file)
1393 {
1394 lineno = 0;
1395
1396 set_default_conf(); /* Set default values prior to conf parsing */
1397 conf_parser_ctx.pass = 1;
1398 yyparse(); /* pick up the classes first */
1399
1400 rewind(file);
1401
1402 conf_parser_ctx.pass = 2;
1403 yyparse(); /* Load the values from the conf */
1404 validate_conf(); /* Check to make sure some values are still okay. */
1405 /* Some global values are also loaded here. */
1406 class_delete_marked(); /* Make sure classes are valid */
1407 }
1408
1409 /* lookup_confhost()
1410 *
1411 * start DNS lookups of all hostnames in the conf
1412 * line and convert an IP addresses in a.b.c.d number for to IP#s.
1413 */
1414 void
1415 lookup_confhost(struct MaskItem *conf)
1416 {
1417 struct addrinfo hints, *res;
1418
1419 /* Do name lookup now on hostnames given and store the
1420 * ip numbers in conf structure.
1421 */
1422 memset(&hints, 0, sizeof(hints));
1423
1424 hints.ai_family = AF_UNSPEC;
1425 hints.ai_socktype = SOCK_STREAM;
1426
1427 /* Get us ready for a bind() and don't bother doing dns lookup */
1428 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1429
1430 if (getaddrinfo(conf->host, NULL, &hints, &res))
1431 {
1432 conf_dns_lookup(conf);
1433 return;
1434 }
1435
1436 assert(res != NULL);
1437
1438 memcpy(&conf->addr, res->ai_addr, res->ai_addrlen);
1439 conf->addr.ss_len = res->ai_addrlen;
1440 conf->addr.ss.ss_family = res->ai_family;
1441
1442 freeaddrinfo(res);
1443 }
1444
1445 /* conf_connect_allowed()
1446 *
1447 * inputs - pointer to inaddr
1448 * - int type ipv4 or ipv6
1449 * output - BANNED or accepted
1450 * side effects - none
1451 */
1452 int
1453 conf_connect_allowed(struct irc_ssaddr *addr, int aftype)
1454 {
1455 struct ip_entry *ip_found;
1456 struct MaskItem *conf = find_dline_conf(addr, aftype);
1457
1458 /* DLINE exempt also gets you out of static limits/pacing... */
1459 if (conf && (conf->type == CONF_EXEMPT))
1460 return 0;
1461
1462 if (conf != NULL)
1463 return BANNED_CLIENT;
1464
1465 ip_found = find_or_add_ip(addr);
1466
1467 if ((CurrentTime - ip_found->last_attempt) <
1468 ConfigFileEntry.throttle_time)
1469 {
1470 ip_found->last_attempt = CurrentTime;
1471 return TOO_FAST;
1472 }
1473
1474 ip_found->last_attempt = CurrentTime;
1475 return 0;
1476 }
1477
1478 /* find_kill()
1479 *
1480 * inputs - pointer to client structure
1481 * output - pointer to struct MaskItem if found
1482 * side effects - See if this user is klined already,
1483 * and if so, return struct MaskItem pointer
1484 */
1485 struct MaskItem *
1486 find_kill(struct Client *client_p)
1487 {
1488 struct MaskItem *conf = NULL;
1489
1490 assert(client_p != NULL);
1491
1492 conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1493 CONF_KLINE, client_p->localClient->aftype,
1494 client_p->username, NULL, 1);
1495 return conf;
1496 }
1497
1498 struct MaskItem *
1499 find_gline(struct Client *client_p)
1500 {
1501 struct MaskItem *conf;
1502
1503 assert(client_p != NULL);
1504
1505 conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
1506 CONF_GLINE, client_p->localClient->aftype,
1507 client_p->username, NULL, 1);
1508 return conf;
1509 }
1510
1511 /* cleanup_tklines()
1512 *
1513 * inputs - NONE
1514 * output - NONE
1515 * side effects - call function to expire temporary k/d lines
1516 * This is an event started off in ircd.c
1517 */
1518 void
1519 cleanup_tklines(void *notused)
1520 {
1521 hostmask_expire_temporary();
1522 expire_tklines(&xconf_items);
1523 expire_tklines(&nresv_items);
1524 expire_tklines(&resv_channel_list);
1525 }
1526
1527 /* expire_tklines()
1528 *
1529 * inputs - tkline list pointer
1530 * output - NONE
1531 * side effects - expire tklines
1532 */
1533 static void
1534 expire_tklines(dlink_list *tklist)
1535 {
1536 dlink_node *ptr;
1537 dlink_node *next_ptr;
1538 struct MaskItem *conf;
1539
1540 DLINK_FOREACH_SAFE(ptr, next_ptr, tklist->head)
1541 {
1542 conf = ptr->data;
1543
1544 if (!conf->until || conf->until > CurrentTime)
1545 continue;
1546
1547 if (conf->type == CONF_XLINE)
1548 {
1549 if (ConfigFileEntry.tkline_expire_notices)
1550 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1551 "Temporary X-line for [%s] expired", conf->name);
1552 conf_free(conf);
1553 }
1554 else if (conf->type == CONF_NRESV || conf->type == CONF_CRESV)
1555 {
1556 if (ConfigFileEntry.tkline_expire_notices)
1557 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1558 "Temporary RESV for [%s] expired", conf->name);
1559 conf_free(conf);
1560 }
1561 }
1562 }
1563
1564 /* oper_privs_as_string()
1565 *
1566 * inputs - pointer to client_p
1567 * output - pointer to static string showing oper privs
1568 * side effects - return as string, the oper privs as derived from port
1569 */
1570 static const struct oper_privs
1571 {
1572 const unsigned int flag;
1573 const unsigned char c;
1574 } flag_list[] = {
1575 { OPER_FLAG_ADMIN, 'A' },
1576 { OPER_FLAG_REMOTEBAN, 'B' },
1577 { OPER_FLAG_DIE, 'D' },
1578 { OPER_FLAG_GLINE, 'G' },
1579 { OPER_FLAG_REHASH, 'H' },
1580 { OPER_FLAG_K, 'K' },
1581 { OPER_FLAG_OPERWALL, 'L' },
1582 { OPER_FLAG_GLOBAL_KILL, 'O' },
1583 { OPER_FLAG_REMOTE, 'R' },
1584 { OPER_FLAG_OPER_SPY, 'S' },
1585 { OPER_FLAG_UNKLINE, 'U' },
1586 { OPER_FLAG_X, 'X' },
1587 { 0, '\0' }
1588 };
1589
1590 char *
1591 oper_privs_as_string(const unsigned int port)
1592 {
1593 static char privs_out[16];
1594 char *privs_ptr = privs_out;
1595 const struct oper_privs *opriv = flag_list;
1596
1597 for (; opriv->flag; ++opriv)
1598 {
1599 if (port & opriv->flag)
1600 *privs_ptr++ = opriv->c;
1601 else
1602 *privs_ptr++ = ToLower(opriv->c);
1603 }
1604
1605 *privs_ptr = '\0';
1606
1607 return privs_out;
1608 }
1609
1610 /*
1611 * Input: A client to find the active oper{} name for.
1612 * Output: The nick!user@host{oper} of the oper.
1613 * "oper" is server name for remote opers
1614 * Side effects: None.
1615 */
1616 const char *
1617 get_oper_name(const struct Client *client_p)
1618 {
1619 dlink_node *cnode = NULL;
1620 /* +5 for !,@,{,} and null */
1621 static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
1622
1623 if (MyConnect(client_p))
1624 {
1625 if ((cnode = client_p->localClient->confs.head))
1626 {
1627 struct MaskItem *conf = cnode->data;
1628
1629 if (IsConfOperator(conf))
1630 {
1631 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1632 client_p->username, client_p->host, conf->name);
1633 return buffer;
1634 }
1635 }
1636
1637 /* Probably should assert here for now. If there is an oper out there
1638 * with no oper{} conf attached, it would be good for us to know...
1639 */
1640 assert(0); /* Oper without oper conf! */
1641 }
1642
1643 snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}", client_p->name,
1644 client_p->username, client_p->host, client_p->servptr->name);
1645 return buffer;
1646 }
1647
1648 /* read_conf_files()
1649 *
1650 * inputs - cold start YES or NO
1651 * output - none
1652 * side effects - read all conf files needed, ircd.conf kline.conf etc.
1653 */
1654 void
1655 read_conf_files(int cold)
1656 {
1657 const char *filename;
1658 char chanmodes[32];
1659 char chanlimit[32];
1660
1661 conf_parser_ctx.boot = cold;
1662 filename = ConfigFileEntry.configfile;
1663
1664 /* We need to know the initial filename for the yyerror() to report
1665 FIXME: The full path is in conffilenamebuf first time since we
1666 dont know anything else
1667
1668 - Gozem 2002-07-21
1669 */
1670 strlcpy(conffilebuf, filename, sizeof(conffilebuf));
1671
1672 if ((conf_parser_ctx.conf_file = fopen(filename, "r")) == NULL)
1673 {
1674 if (cold)
1675 {
1676 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
1677 filename, strerror(errno));
1678 exit(-1);
1679 }
1680 else
1681 {
1682 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1683 "Unable to read configuration file '%s': %s",
1684 filename, strerror(errno));
1685 return;
1686 }
1687 }
1688
1689 if (!cold)
1690 clear_out_old_conf();
1691
1692 read_conf(conf_parser_ctx.conf_file);
1693 fclose(conf_parser_ctx.conf_file);
1694
1695 log_reopen_all();
1696
1697 add_isupport("NICKLEN", NULL, ServerInfo.max_nick_length);
1698 add_isupport("NETWORK", ServerInfo.network_name, -1);
1699
1700 snprintf(chanmodes, sizeof(chanmodes), "beI:%d", ConfigChannel.max_bans);
1701 add_isupport("MAXLIST", chanmodes, -1);
1702 add_isupport("MAXTARGETS", NULL, ConfigFileEntry.max_targets);
1703 add_isupport("CHANTYPES", "#", -1);
1704
1705 snprintf(chanlimit, sizeof(chanlimit), "#:%d",
1706 ConfigChannel.max_chans_per_user);
1707 add_isupport("CHANLIMIT", chanlimit, -1);
1708 snprintf(chanmodes, sizeof(chanmodes), "%s", "beI,k,l,imnprstORS");
1709 add_isupport("CHANNELLEN", NULL, LOCAL_CHANNELLEN);
1710 add_isupport("TOPICLEN", NULL, ServerInfo.max_topic_length);
1711 add_isupport("EXCEPTS", "e", -1);
1712 add_isupport("INVEX", "I", -1);
1713 add_isupport("CHANMODES", chanmodes, -1);
1714
1715 /*
1716 * message_locale may have changed. rebuild isupport since it relies
1717 * on strlen(form_str(RPL_ISUPPORT))
1718 */
1719 rebuild_isupport_message_line();
1720 }
1721
1722 /* clear_out_old_conf()
1723 *
1724 * inputs - none
1725 * output - none
1726 * side effects - Clear out the old configuration
1727 */
1728 static void
1729 clear_out_old_conf(void)
1730 {
1731 dlink_node *ptr = NULL, *next_ptr = NULL;
1732 struct MaskItem *conf;
1733 dlink_list *free_items [] = {
1734 &server_items, &oconf_items,
1735 &uconf_items, &xconf_items,
1736 &nresv_items, &cluster_items, &service_items, &resv_channel_list, NULL
1737 };
1738
1739 dlink_list ** iterator = free_items; /* C is dumb */
1740
1741 /* We only need to free anything allocated by yyparse() here.
1742 * Resetting structs, etc, is taken care of by set_default_conf().
1743 */
1744
1745 for (; *iterator != NULL; iterator++)
1746 {
1747 DLINK_FOREACH_SAFE(ptr, next_ptr, (*iterator)->head)
1748 {
1749 conf = ptr->data;
1750
1751 dlinkDelete(&conf->node, map_to_list(conf->type));
1752
1753 /* XXX This is less than pretty */
1754 if (conf->type == CONF_SERVER || conf->type == CONF_OPER)
1755 {
1756 if (!conf->ref_count)
1757 conf_free(conf);
1758 }
1759 else if (conf->type == CONF_XLINE)
1760 {
1761 if (!conf->until)
1762 conf_free(conf);
1763 }
1764 else
1765 conf_free(conf);
1766 }
1767 }
1768
1769 /*
1770 * don't delete the class table, rather mark all entries
1771 * for deletion. The table is cleaned up by class_delete_marked. - avalon
1772 */
1773 class_mark_for_deletion();
1774
1775 clear_out_address_conf();
1776
1777 /* clean out module paths */
1778 mod_clear_paths();
1779
1780 /* clean out ServerInfo */
1781 MyFree(ServerInfo.description);
1782 ServerInfo.description = NULL;
1783 MyFree(ServerInfo.network_name);
1784 ServerInfo.network_name = NULL;
1785 MyFree(ServerInfo.network_desc);
1786 ServerInfo.network_desc = NULL;
1787 MyFree(ConfigFileEntry.egdpool_path);
1788 ConfigFileEntry.egdpool_path = NULL;
1789 #ifdef HAVE_LIBCRYPTO
1790 if (ServerInfo.rsa_private_key != NULL)
1791 {
1792 RSA_free(ServerInfo.rsa_private_key);
1793 ServerInfo.rsa_private_key = NULL;
1794 }
1795
1796 MyFree(ServerInfo.rsa_private_key_file);
1797 ServerInfo.rsa_private_key_file = NULL;
1798
1799 if (ServerInfo.server_ctx)
1800 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2|
1801 SSL_OP_NO_SSLv3|
1802 SSL_OP_NO_TLSv1);
1803 if (ServerInfo.client_ctx)
1804 SSL_CTX_set_options(ServerInfo.client_ctx, SSL_OP_NO_SSLv2|
1805 SSL_OP_NO_SSLv3|
1806 SSL_OP_NO_TLSv1);
1807 #endif
1808
1809 /* clean out AdminInfo */
1810 MyFree(AdminInfo.name);
1811 AdminInfo.name = NULL;
1812 MyFree(AdminInfo.email);
1813 AdminInfo.email = NULL;
1814 MyFree(AdminInfo.description);
1815 AdminInfo.description = NULL;
1816
1817 /* clean out listeners */
1818 close_listeners();
1819
1820 /* clean out general */
1821 MyFree(ConfigFileEntry.service_name);
1822 ConfigFileEntry.service_name = NULL;
1823
1824 delete_isupport("INVEX");
1825 delete_isupport("EXCEPTS");
1826 }
1827
1828 /* conf_add_class_to_conf()
1829 *
1830 * inputs - pointer to config item
1831 * output - NONE
1832 * side effects - Add a class pointer to a conf
1833 */
1834 void
1835 conf_add_class_to_conf(struct MaskItem *conf, const char *class_name)
1836 {
1837 if (class_name == NULL)
1838 {
1839 conf->class = class_default;
1840
1841 if (conf->type == CONF_CLIENT)
1842 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1843 "Warning *** Defaulting to default class for %s@%s",
1844 conf->user, conf->host);
1845 else
1846 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1847 "Warning *** Defaulting to default class for %s",
1848 conf->name);
1849 }
1850 else
1851 conf->class = class_find(class_name, 1);
1852
1853 if (conf->class == NULL)
1854 {
1855 if (conf->type == CONF_CLIENT)
1856 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1857 "Warning *** Defaulting to default class for %s@%s",
1858 conf->user, conf->host);
1859 else
1860 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1861 "Warning *** Defaulting to default class for %s",
1862 conf->name);
1863 conf->class = class_default;
1864 }
1865 }
1866
1867 /* yyerror()
1868 *
1869 * inputs - message from parser
1870 * output - NONE
1871 * side effects - message to opers and log file entry is made
1872 */
1873 void
1874 yyerror(const char *msg)
1875 {
1876 char newlinebuf[IRCD_BUFSIZE];
1877
1878 if (conf_parser_ctx.pass != 1)
1879 return;
1880
1881 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1882 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1883 "\"%s\", line %u: %s: %s",
1884 conffilebuf, lineno + 1, msg, newlinebuf);
1885 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1886 conffilebuf, lineno + 1, msg, newlinebuf);
1887 }
1888
1889 void
1890 conf_error_report(const char *msg)
1891 {
1892 char newlinebuf[IRCD_BUFSIZE];
1893
1894 strip_tabs(newlinebuf, linebuf, sizeof(newlinebuf));
1895 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1896 "\"%s\", line %u: %s: %s",
1897 conffilebuf, lineno + 1, msg, newlinebuf);
1898 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1899 conffilebuf, lineno + 1, msg, newlinebuf);
1900 }
1901
1902 /*
1903 * valid_tkline()
1904 *
1905 * inputs - pointer to ascii string to check
1906 * - whether the specified time is in seconds or minutes
1907 * output - -1 not enough parameters
1908 * - 0 if not an integer number, else the number
1909 * side effects - none
1910 * Originally written by Dianora (Diane, db@db.net)
1911 */
1912 time_t
1913 valid_tkline(const char *p, int minutes)
1914 {
1915 time_t result = 0;
1916
1917 for (; *p; ++p)
1918 {
1919 if (!IsDigit(*p))
1920 return 0;
1921
1922 result *= 10;
1923 result += ((*p) & 0xF);
1924 }
1925
1926 /*
1927 * In the degenerate case where oper does a /quote kline 0 user@host :reason
1928 * i.e. they specifically use 0, I am going to return 1 instead
1929 * as a return value of non-zero is used to flag it as a temporary kline
1930 */
1931 if (result == 0)
1932 result = 1;
1933
1934 /*
1935 * If the incoming time is in seconds convert it to minutes for the purpose
1936 * of this calculation
1937 */
1938 if (!minutes)
1939 result = result / (time_t)60;
1940
1941 if (result > MAX_TDKLINE_TIME)
1942 result = MAX_TDKLINE_TIME;
1943
1944 result = result * (time_t)60; /* turn it into seconds */
1945
1946 return result;
1947 }
1948
1949 /* valid_wild_card()
1950 *
1951 * input - pointer to client
1952 * - int flag, 0 for no warning oper 1 for warning oper
1953 * - count of following varargs to check
1954 * output - 0 if not valid, 1 if valid
1955 * side effects - NOTICE is given to source_p if warn is 1
1956 */
1957 int
1958 valid_wild_card(struct Client *source_p, int warn, int count, ...)
1959 {
1960 char *p;
1961 char tmpch;
1962 int nonwild = 0;
1963 va_list args;
1964
1965 /*
1966 * Now we must check the user and host to make sure there
1967 * are at least NONWILDCHARS non-wildcard characters in
1968 * them, otherwise assume they are attempting to kline
1969 * *@* or some variant of that. This code will also catch
1970 * people attempting to kline *@*.tld, as long as NONWILDCHARS
1971 * is greater than 3. In that case, there are only 3 non-wild
1972 * characters (tld), so if NONWILDCHARS is 4, the kline will
1973 * be disallowed.
1974 * -wnder
1975 */
1976
1977 va_start(args, count);
1978
1979 while (count--)
1980 {
1981 p = va_arg(args, char *);
1982 if (p == NULL)
1983 continue;
1984
1985 while ((tmpch = *p++))
1986 {
1987 if (!IsKWildChar(tmpch))
1988 {
1989 /*
1990 * If we find enough non-wild characters, we can
1991 * break - no point in searching further.
1992 */
1993 if (++nonwild >= ConfigFileEntry.min_nonwildcard)
1994 return 1;
1995 }
1996 }
1997 }
1998
1999 if (warn)
2000 sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the mask",
2001 me.name, source_p->name, ConfigFileEntry.min_nonwildcard);
2002 return 0;
2003 }
2004
2005 /* XXX should this go into a separate file ? -Dianora */
2006 /* parse_aline
2007 *
2008 * input - pointer to cmd name being used
2009 * - pointer to client using cmd
2010 * - parc parameter count
2011 * - parv[] list of parameters to parse
2012 * - parse_flags bit map of things to test
2013 * - pointer to user or string to parse into
2014 * - pointer to host or NULL to parse into if non NULL
2015 * - pointer to optional tkline time or NULL
2016 * - pointer to target_server to parse into if non NULL
2017 * - pointer to reason to parse into
2018 *
2019 * output - 1 if valid, -1 if not valid
2020 * side effects - A generalised k/d/x etc. line parser,
2021 * "ALINE [time] user@host|string [ON] target :reason"
2022 * will parse returning a parsed user, host if
2023 * h_p pointer is non NULL, string otherwise.
2024 * if tkline_time pointer is non NULL a tk line will be set
2025 * to non zero if found.
2026 * if tkline_time pointer is NULL and tk line is found,
2027 * error is reported.
2028 * if target_server is NULL and an "ON" is found error
2029 * is reported.
2030 * if reason pointer is NULL ignore pointer,
2031 * this allows use of parse_a_line in unkline etc.
2032 *
2033 * - Dianora
2034 */
2035 int
2036 parse_aline(const char *cmd, struct Client *source_p,
2037 int parc, char **parv,
2038 int parse_flags, char **up_p, char **h_p, time_t *tkline_time,
2039 char **target_server, char **reason)
2040 {
2041 int found_tkline_time=0;
2042 static char def_reason[] = "No Reason";
2043 static char user[USERLEN*4+1];
2044 static char host[HOSTLEN*4+1];
2045
2046 parv++;
2047 parc--;
2048
2049 found_tkline_time = valid_tkline(*parv, TK_MINUTES);
2050
2051 if (found_tkline_time != 0)
2052 {
2053 parv++;
2054 parc--;
2055
2056 if (tkline_time != NULL)
2057 *tkline_time = found_tkline_time;
2058 else
2059 {
2060 sendto_one(source_p, ":%s NOTICE %s :temp_line not supported by %s",
2061 me.name, source_p->name, cmd);
2062 return -1;
2063 }
2064 }
2065
2066 if (parc == 0)
2067 {
2068 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
2069 me.name, source_p->name, cmd);
2070 return -1;
2071 }
2072
2073 if (h_p == NULL)
2074 *up_p = *parv;
2075 else
2076 {
2077 if (find_user_host(source_p, *parv, user, host, parse_flags) == 0)
2078 return -1;
2079
2080 *up_p = user;
2081 *h_p = host;
2082 }
2083
2084 parc--;
2085 parv++;
2086
2087 if (parc != 0)
2088 {
2089 if (irccmp(*parv, "ON") == 0)
2090 {
2091 parc--;
2092 parv++;
2093
2094 if (target_server == NULL)
2095 {
2096 sendto_one(source_p, ":%s NOTICE %s :ON server not supported by %s",
2097 me.name, source_p->name, cmd);
2098 return -1;
2099 }
2100
2101 if (!HasOFlag(source_p, OPER_FLAG_REMOTEBAN))
2102 {
2103 sendto_one(source_p, form_str(ERR_NOPRIVS),
2104 me.name, source_p->name, "remoteban");
2105 return -1;
2106 }
2107
2108 if (parc == 0 || EmptyString(*parv))
2109 {
2110 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
2111 me.name, source_p->name, cmd);
2112 return -1;
2113 }
2114
2115 *target_server = *parv;
2116 parc--;
2117 parv++;
2118 }
2119 else
2120 {
2121 /* Make sure target_server *is* NULL if no ON server found
2122 * caller probably NULL'd it first, but no harm to do it again -db
2123 */
2124 if (target_server != NULL)
2125 *target_server = NULL;
2126 }
2127 }
2128
2129 if (h_p != NULL)
2130 {
2131 if (strchr(user, '!') != NULL)
2132 {
2133 sendto_one(source_p, ":%s NOTICE %s :Invalid character '!' in kline",
2134 me.name, source_p->name);
2135 return -1;
2136 }
2137
2138 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 2, *up_p, *h_p))
2139 return -1;
2140 }
2141 else
2142 if ((parse_flags & AWILD) && !valid_wild_card(source_p, 1, 1, *up_p))
2143 return -1;
2144
2145 if (reason != NULL)
2146 {
2147 if (parc != 0 && !EmptyString(*parv))
2148 {
2149 *reason = *parv;
2150 if (!valid_comment(source_p, *reason, 1))
2151 return -1;
2152 }
2153 else
2154 *reason = def_reason;
2155 }
2156
2157 return 1;
2158 }
2159
2160 /* find_user_host()
2161 *
2162 * inputs - pointer to client placing kline
2163 * - pointer to user_host_or_nick
2164 * - pointer to user buffer
2165 * - pointer to host buffer
2166 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
2167 * side effects -
2168 */
2169 static int
2170 find_user_host(struct Client *source_p, char *user_host_or_nick,
2171 char *luser, char *lhost, unsigned int flags)
2172 {
2173 struct Client *target_p = NULL;
2174 char *hostp = NULL;
2175
2176 if (lhost == NULL)
2177 {
2178 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1);
2179 return 1;
2180 }
2181
2182 if ((hostp = strchr(user_host_or_nick, '@')) || *user_host_or_nick == '*')
2183 {
2184 /* Explicit user@host mask given */
2185
2186 if (hostp != NULL) /* I'm a little user@host */
2187 {
2188 *(hostp++) = '\0'; /* short and squat */
2189 if (*user_host_or_nick)
2190 strlcpy(luser, user_host_or_nick, USERLEN*4 + 1); /* here is my user */
2191 else
2192 strcpy(luser, "*");
2193 if (*hostp)
2194 strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
2195 else
2196 strcpy(lhost, "*");
2197 }
2198 else
2199 {
2200 luser[0] = '*'; /* no @ found, assume its *@somehost */
2201 luser[1] = '\0';
2202 strlcpy(lhost, user_host_or_nick, HOSTLEN*4 + 1);
2203 }
2204
2205 return 1;
2206 }
2207 else
2208 {
2209 /* Try to find user@host mask from nick */
2210 /* Okay to use source_p as the first param, because source_p == client_p */
2211 if ((target_p =
2212 find_chasing(source_p, source_p, user_host_or_nick, NULL)) == NULL)
2213 return 0;
2214
2215 if (IsExemptKline(target_p))
2216 {
2217 if (!IsServer(source_p))
2218 sendto_one(source_p,
2219 ":%s NOTICE %s :%s is E-lined",
2220 me.name, source_p->name, target_p->name);
2221 return 0;
2222 }
2223
2224 /*
2225 * turn the "user" bit into "*user", blow away '~'
2226 * if found in original user name (non-idented)
2227 */
2228 strlcpy(luser, target_p->username, USERLEN*4 + 1);
2229
2230 if (target_p->username[0] == '~')
2231 luser[0] = '*';
2232
2233 if (target_p->sockhost[0] == '\0' ||
2234 (target_p->sockhost[0] == '0' && target_p->sockhost[1] == '\0'))
2235 strlcpy(lhost, target_p->host, HOSTLEN*4 + 1);
2236 else
2237 strlcpy(lhost, target_p->sockhost, HOSTLEN*4 + 1);
2238 return 1;
2239 }
2240
2241 return 0;
2242 }
2243
2244 /* valid_comment()
2245 *
2246 * inputs - pointer to client
2247 * - pointer to comment
2248 * output - 0 if no valid comment,
2249 * - 1 if valid
2250 * side effects - truncates reason where necessary
2251 */
2252 int
2253 valid_comment(struct Client *source_p, char *comment, int warn)
2254 {
2255 if (strlen(comment) > REASONLEN)
2256 comment[REASONLEN-1] = '\0';
2257
2258 return 1;
2259 }
2260
2261 /* match_conf_password()
2262 *
2263 * inputs - pointer to given password
2264 * - pointer to Conf
2265 * output - 1 or 0 if match
2266 * side effects - none
2267 */
2268 int
2269 match_conf_password(const char *password, const struct MaskItem *conf)
2270 {
2271 const char *encr = NULL;
2272
2273 if (EmptyString(password) || EmptyString(conf->passwd))
2274 return 0;
2275
2276 if (conf->flags & CONF_FLAGS_ENCRYPTED)
2277 encr = crypt(password, conf->passwd);
2278 else
2279 encr = password;
2280
2281 return !strcmp(encr, conf->passwd);
2282 }
2283
2284 /*
2285 * cluster_a_line
2286 *
2287 * inputs - client sending the cluster
2288 * - command name "KLINE" "XLINE" etc.
2289 * - capab -- CAP_KLN etc. from s_serv.h
2290 * - cluster type -- CLUSTER_KLINE etc. from conf.h
2291 * - pattern and args to send along
2292 * output - none
2293 * side effects - Take source_p send the pattern with args given
2294 * along to all servers that match capab and cluster type
2295 */
2296 void
2297 cluster_a_line(struct Client *source_p, const char *command,
2298 int capab, int cluster_type, const char *pattern, ...)
2299 {
2300 va_list args;
2301 char buffer[IRCD_BUFSIZE];
2302 const dlink_node *ptr = NULL;
2303
2304 va_start(args, pattern);
2305 vsnprintf(buffer, sizeof(buffer), pattern, args);
2306 va_end(args);
2307
2308 DLINK_FOREACH(ptr, cluster_items.head)
2309 {
2310 const struct MaskItem *conf = ptr->data;
2311
2312 if (conf->flags & cluster_type)
2313 sendto_match_servs(source_p, conf->name, CAP_CLUSTER|capab,
2314 "%s %s %s", command, conf->name, buffer);
2315 }
2316 }
2317
2318 /*
2319 * split_nuh
2320 *
2321 * inputs - pointer to original mask (modified in place)
2322 * - pointer to pointer where nick should go
2323 * - pointer to pointer where user should go
2324 * - pointer to pointer where host should go
2325 * output - NONE
2326 * side effects - mask is modified in place
2327 * If nick pointer is NULL, ignore writing to it
2328 * this allows us to use this function elsewhere.
2329 *
2330 * mask nick user host
2331 * ---------------------- ------- ------- ------
2332 * Dianora!db@db.net Dianora db db.net
2333 * Dianora Dianora * *
2334 * db.net * * db.net
2335 * OR if nick pointer is NULL
2336 * Dianora - * Dianora
2337 * Dianora! Dianora * *
2338 * Dianora!@ Dianora * *
2339 * Dianora!db Dianora db *
2340 * Dianora!@db.net Dianora * db.net
2341 * db@db.net * db db.net
2342 * !@ * * *
2343 * @ * * *
2344 * ! * * *
2345 */
2346 void
2347 split_nuh(struct split_nuh_item *const iptr)
2348 {
2349 char *p = NULL, *q = NULL;
2350
2351 if (iptr->nickptr)
2352 strlcpy(iptr->nickptr, "*", iptr->nicksize);
2353 if (iptr->userptr)
2354 strlcpy(iptr->userptr, "*", iptr->usersize);
2355 if (iptr->hostptr)
2356 strlcpy(iptr->hostptr, "*", iptr->hostsize);
2357
2358 if ((p = strchr(iptr->nuhmask, '!')))
2359 {
2360 *p = '\0';
2361
2362 if (iptr->nickptr && *iptr->nuhmask != '\0')
2363 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2364
2365 if ((q = strchr(++p, '@'))) {
2366 *q++ = '\0';
2367
2368 if (*p != '\0')
2369 strlcpy(iptr->userptr, p, iptr->usersize);
2370
2371 if (*q != '\0')
2372 strlcpy(iptr->hostptr, q, iptr->hostsize);
2373 }
2374 else
2375 {
2376 if (*p != '\0')
2377 strlcpy(iptr->userptr, p, iptr->usersize);
2378 }
2379 }
2380 else
2381 {
2382 /* No ! found so lets look for a user@host */
2383 if ((p = strchr(iptr->nuhmask, '@')))
2384 {
2385 /* if found a @ */
2386 *p++ = '\0';
2387
2388 if (*iptr->nuhmask != '\0')
2389 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
2390
2391 if (*p != '\0')
2392 strlcpy(iptr->hostptr, p, iptr->hostsize);
2393 }
2394 else
2395 {
2396 /* no @ found */
2397 if (!iptr->nickptr || strpbrk(iptr->nuhmask, ".:"))
2398 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
2399 else
2400 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
2401 }
2402 }
2403 }

Properties

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