/[svn]/ircd-hybrid/trunk/src/conf.c
ViewVC logotype

Contents of /ircd-hybrid/trunk/src/conf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9917 - (show annotations)
Sat Jan 30 21:20:07 2021 UTC (2 years, 4 months ago) by michael
File MIME type: text/x-chdr
File size: 37115 byte(s)
- conf.c:attach_iline(): just let the client silently in if their class is full and they are exempted from limits. No point
  in explicitely telling them that their class is full and they have exceed_limit = yes

1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2021 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file conf.c
23 * \brief Configuration file functions.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "ircd_defs.h"
30 #include "parse.h"
31 #include "conf.h"
32 #include "conf_cluster.h"
33 #include "conf_gecos.h"
34 #include "conf_pseudo.h"
35 #include "conf_resv.h"
36 #include "conf_service.h"
37 #include "conf_shared.h"
38 #include "server.h"
39 #include "channel.h"
40 #include "client.h"
41 #include "event.h"
42 #include "irc_string.h"
43 #include "s_bsd.h"
44 #include "ircd.h"
45 #include "listener.h"
46 #include "hostmask.h"
47 #include "modules.h"
48 #include "numeric.h"
49 #include "fdlist.h"
50 #include "log.h"
51 #include "send.h"
52 #include "memory.h"
53 #include "res.h"
54 #include "user.h"
55 #include "channel_mode.h"
56 #include "misc.h"
57 #include "conf_db.h"
58 #include "conf_class.h"
59 #include "motd.h"
60 #include "ipcache.h"
61 #include "isupport.h"
62 #include "whowas.h"
63
64
65 struct config_channel_entry ConfigChannel;
66 struct config_serverhide_entry ConfigServerHide;
67 struct config_general_entry ConfigGeneral;
68 struct config_log_entry ConfigLog = { .use_logging = 1 };
69 struct config_serverinfo_entry ConfigServerInfo;
70 struct config_admin_entry ConfigAdminInfo;
71 struct conf_parser_context conf_parser_ctx;
72
73 /* general conf items link list root, other than k lines etc. */
74 dlink_list connect_items;
75 dlink_list operator_items;
76
77 extern unsigned int lineno;
78 extern char linebuf[];
79 extern char conffilebuf[IRCD_BUFSIZE];
80 extern int yyparse(); /* defined in y.tab.c */
81
82
83 /* conf_dns_callback()
84 *
85 * inputs - pointer to struct MaskItem
86 * - pointer to DNSReply reply
87 * output - none
88 * side effects - called when resolver query finishes
89 * if the query resulted in a successful search, hp will contain
90 * a non-null pointer, otherwise hp will be null.
91 * if successful save hp in the conf item it was called with
92 */
93 static void
94 conf_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name, size_t namelength)
95 {
96 struct MaskItem *const conf = vptr;
97
98 conf->dns_pending = false;
99
100 if (addr)
101 *conf->addr = *addr;
102 else
103 conf->dns_failed = true;
104 }
105
106 /* conf_resolve_host()
107 *
108 * start DNS lookups of all hostnames in the conf
109 * line and convert an IP addresses in a.b.c.d number for to IP#s.
110 */
111 void
112 conf_dns_lookup(struct MaskItem *conf)
113 {
114 struct addrinfo hints, *res;
115
116 /*
117 * Do name lookup now on hostnames given and store the
118 * ip numbers in conf structure.
119 */
120 memset(&hints, 0, sizeof(hints));
121
122 hints.ai_family = AF_UNSPEC;
123 hints.ai_socktype = SOCK_STREAM;
124
125 /* Get us ready for a bind() and don't bother doing dns lookup */
126 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
127
128 if (getaddrinfo(conf->host, NULL, &hints, &res))
129 {
130 /*
131 * By this point conf->host possibly is not a numerical network address. Do a nameserver
132 * lookup of the conf host. If the conf entry is currently doing a ns lookup do nothing.
133 */
134 if (conf->dns_pending == true)
135 return;
136
137 conf->dns_pending = true;
138
139 if (conf->aftype == AF_INET)
140 gethost_byname_type(conf_dns_callback, conf, conf->host, T_A);
141 else
142 gethost_byname_type(conf_dns_callback, conf, conf->host, T_AAAA);
143 return;
144 }
145
146 assert(res);
147
148 memcpy(conf->addr, res->ai_addr, res->ai_addrlen);
149 conf->addr->ss_len = res->ai_addrlen;
150
151 freeaddrinfo(res);
152 }
153
154 /* map_to_list()
155 *
156 * inputs - ConfType conf
157 * output - pointer to dlink_list to use
158 * side effects - none
159 */
160 static dlink_list *
161 map_to_list(enum maskitem_type type)
162 {
163 switch (type)
164 {
165 case CONF_OPER:
166 return &operator_items;
167 break;
168 case CONF_SERVER:
169 return &connect_items;
170 break;
171 default:
172 return NULL;
173 }
174 }
175
176 struct MaskItem *
177 conf_make(enum maskitem_type type)
178 {
179 struct MaskItem *const conf = xcalloc(sizeof(*conf));
180 dlink_list *list = NULL;
181
182 conf->type = type;
183 conf->active = true;
184 conf->aftype = AF_INET;
185
186 if ((list = map_to_list(type)))
187 dlinkAdd(conf, &conf->node, list);
188 return conf;
189 }
190
191 void
192 conf_free(struct MaskItem *conf)
193 {
194 dlink_node *node = NULL, *node_next = NULL;
195 dlink_list *list = NULL;
196
197 if ((list = map_to_list(conf->type)))
198 dlinkFindDelete(list, conf);
199
200 xfree(conf->name);
201
202 if (conf->dns_pending == true)
203 delete_resolver_queries(conf);
204 if (conf->passwd)
205 memset(conf->passwd, 0, strlen(conf->passwd));
206 if (conf->spasswd)
207 memset(conf->spasswd, 0, strlen(conf->spasswd));
208
209 conf->class = NULL;
210
211 xfree(conf->passwd);
212 xfree(conf->spasswd);
213 xfree(conf->reason);
214 xfree(conf->certfp);
215 xfree(conf->whois);
216 xfree(conf->user);
217 xfree(conf->host);
218 xfree(conf->addr);
219 xfree(conf->bind);
220 xfree(conf->cipher_list);
221
222 DLINK_FOREACH_SAFE(node, node_next, conf->hub_list.head)
223 {
224 xfree(node->data);
225 dlinkDelete(node, &conf->hub_list);
226 free_dlink_node(node);
227 }
228
229 DLINK_FOREACH_SAFE(node, node_next, conf->leaf_list.head)
230 {
231 xfree(node->data);
232 dlinkDelete(node, &conf->leaf_list);
233 free_dlink_node(node);
234 }
235
236 xfree(conf);
237 }
238
239 /* attach_iline()
240 *
241 * inputs - client pointer
242 * - conf pointer
243 * output -
244 * side effects - do actual attach
245 */
246 static int
247 attach_iline(struct Client *client, struct MaskItem *conf)
248 {
249 const struct ClassItem *const class = conf->class;
250 bool a_limit_reached = false;
251
252 struct ip_entry *ipcache = ipcache_record_find_or_add(&client->ip);
253 ++ipcache->count_local;
254 AddFlag(client, FLAGS_IPHASH);
255
256 if (class->max_total && class->ref_count >= class->max_total)
257 a_limit_reached = true;
258 else if (class->max_perip_local && ipcache->count_local > class->max_perip_local)
259 a_limit_reached = true;
260 else if (class->max_perip_global &&
261 (ipcache->count_local + ipcache->count_remote) > class->max_perip_global)
262 a_limit_reached = true;
263 else if (class_ip_limit_add(conf->class, &client->ip, IsConfExemptLimits(conf)) == true)
264 a_limit_reached = true;
265
266 if (a_limit_reached == true)
267 if (!IsConfExemptLimits(conf))
268 return TOO_MANY; /* Already at maximum allowed */
269
270 return conf_attach(client, conf);
271 }
272
273 /* verify_access()
274 *
275 * inputs - pointer to client to verify
276 * output - 0 if success -'ve if not
277 * side effect - find the first (best) I line to attach.
278 */
279 static int
280 verify_access(struct Client *client)
281 {
282 struct MaskItem *conf;
283
284 if (HasFlag(client, FLAGS_GOTID))
285 conf = find_address_conf(client->host, client->username, &client->ip,
286 client->connection->password);
287 else
288 {
289 char non_ident[USERLEN + 1] = "~";
290
291 strlcpy(non_ident + 1, client->username, sizeof(non_ident) - 1);
292 conf = find_address_conf(client->host, non_ident, &client->ip,
293 client->connection->password);
294 }
295
296 if (conf == NULL)
297 return NOT_AUTHORIZED;
298
299 assert(IsConfClient(conf) || IsConfKill(conf));
300
301 if (IsConfKill(conf))
302 {
303 sendto_one_notice(client, &me, ":*** Banned: %s", conf->reason);
304 return BANNED_CLIENT;
305 }
306
307 if (IsConfRedir(conf))
308 {
309 sendto_one_numeric(client, &me, RPL_REDIR,
310 conf->name ? conf->name : "",
311 conf->port);
312 return NOT_AUTHORIZED;
313 }
314
315 /* Preserve x->host in x->realhost before it gets overwritten. */
316 strlcpy(client->realhost, client->host, sizeof(client->realhost));
317
318 if (IsConfDoSpoofIp(conf))
319 strlcpy(client->host, conf->name, sizeof(client->host));
320
321 return attach_iline(client, conf);
322 }
323
324 /* check_client()
325 *
326 * inputs - pointer to client
327 * output - 0 = Success
328 * NOT_AUTHORIZED (-1) = Access denied (no I line match)
329 * IRCD_SOCKET_ERROR (-2) = Bad socket.
330 * I_LINE_FULL (-3) = I-line is full
331 * TOO_MANY (-4) = Too many connections from hostname
332 * BANNED_CLIENT (-5) = K-lined
333 * side effects - Ordinary client access check.
334 * Look for conf lines which have the same
335 * status as the flags passed.
336 */
337 bool
338 conf_check_client(struct Client *client)
339 {
340 const char *error = NULL;
341 bool warn = true;
342
343 switch (verify_access(client))
344 {
345 case TOO_MANY:
346 error = "too many connections on IP";
347 break;
348 case I_LINE_FULL:
349 error = "connection class is full";
350 break;
351 case NOT_AUTHORIZED:
352 error = "not authorized";
353 break;
354 case BANNED_CLIENT:
355 error = "banned from server";
356 warn = false;
357 break;
358 }
359
360 if (error)
361 {
362 char buf[REASONLEN + 1];
363 snprintf(buf, sizeof(buf), "Connection rejected - %s", error);
364
365 ++ServerStats.is_ref;
366
367 if (warn == true)
368 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Rejecting client connection from %s: %s",
369 client_get_name(client, SHOW_IP), error);
370
371 ilog(LOG_TYPE_IRCD, "Rejecting client connection from %s: %s",
372 client_get_name(client, SHOW_IP), error);
373 exit_client(client, buf);
374 return false;
375 }
376
377 return true;
378 }
379
380 /*! \brief Disassociate configuration from the client. Also removes a class
381 * from the list if marked for deleting.
382 * \param client Client to operate on
383 * \param type Type of conf to detach
384 */
385 void
386 conf_detach(struct Client *client, enum maskitem_type type)
387 {
388 dlink_node *node, *node_next;
389
390 DLINK_FOREACH_SAFE(node, node_next, client->connection->confs.head)
391 {
392 struct MaskItem *conf = node->data;
393
394 assert(conf->type & (CONF_CLIENT | CONF_OPER | CONF_SERVER));
395 assert(conf->ref_count > 0);
396 assert(conf->class->ref_count > 0);
397
398 if (!(conf->type & type))
399 continue;
400
401 dlinkDelete(node, &client->connection->confs);
402 free_dlink_node(node);
403
404 if (conf->type == CONF_CLIENT)
405 class_ip_limit_remove(conf->class, &client->ip);
406
407 if (--conf->class->ref_count == 0 && conf->class->active == false)
408 {
409 class_free(conf->class);
410 conf->class = NULL;
411 }
412
413 if (--conf->ref_count == 0 && conf->active == false)
414 conf_free(conf);
415 }
416 }
417
418 /*! \brief Associate a specific configuration entry to a *local* client (this
419 * is the one which used in accepting the connection). Note, that this
420 * automatically changes the attachment if there was an old one.
421 * \param client Client to attach the conf to
422 * \param conf Configuration record to attach
423 */
424 int
425 conf_attach(struct Client *client, struct MaskItem *conf)
426 {
427 if (dlinkFind(&client->connection->confs, conf))
428 return 1;
429
430 conf->class->ref_count++;
431 conf->ref_count++;
432
433 dlinkAdd(conf, make_dlink_node(), &client->connection->confs);
434
435 return 0;
436 }
437
438 /* find_conf_name()
439 *
440 * inputs - pointer to conf link list to search
441 * - pointer to name to find
442 * - int mask of type of conf to find
443 * output - NULL or pointer to conf found
444 * side effects - find a conf entry which matches the name
445 * and has the given mask.
446 */
447 struct MaskItem *
448 find_conf_name(dlink_list *list, const char *name, enum maskitem_type type)
449 {
450 dlink_node *node = NULL;
451
452 DLINK_FOREACH(node, list->head)
453 {
454 struct MaskItem *conf = node->data;
455
456 if (conf->type == type)
457 {
458 if (conf->name && !irccmp(conf->name, name))
459 return conf;
460 }
461 }
462
463 return NULL;
464 }
465
466 /*! \brief Find a connect {} conf that has a name that matches \a name.
467 * \param name Name to match
468 * \param compare Pointer to function to be used for string matching
469 */
470 struct MaskItem *
471 connect_find(const char *name, int (*compare)(const char *, const char *))
472 {
473 dlink_node *node;
474
475 DLINK_FOREACH(node, connect_items.head)
476 {
477 struct MaskItem *conf = node->data;
478
479 if (compare(name, conf->name) == 0)
480 return conf;
481 }
482
483 return NULL;
484 }
485
486 /* find_exact_name_conf()
487 *
488 * inputs - type of link list to look in
489 * - pointer to name string to find
490 * - pointer to user
491 * - pointer to host
492 * output - NULL or pointer to found struct MaskItem
493 * side effects - looks for an exact match on name field
494 */
495 struct MaskItem *
496 operator_find(const struct Client *client, const char *name)
497 {
498 dlink_node *node;
499
500 DLINK_FOREACH(node, operator_items.head)
501 {
502 struct MaskItem *conf = node->data;
503
504 if (irccmp(conf->name, name) == 0)
505 {
506 if (client == NULL)
507 return conf;
508
509 if (conf->class->max_total &&
510 conf->class->max_total <= conf->class->ref_count)
511 continue;
512
513 if (match(conf->user, client->username) == 0)
514 {
515 switch (conf->htype)
516 {
517 case HM_HOST:
518 if (match(conf->host, client->realhost) == 0 ||
519 match(conf->host, client->sockhost) == 0 || match(conf->host, client->host) == 0)
520 return conf;
521 break;
522 case HM_IPV6:
523 case HM_IPV4:
524 if (address_compare(&client->ip, conf->addr, false, false, conf->bits) == true)
525 return conf;
526 break;
527 default:
528 assert(0);
529 }
530 }
531 }
532 }
533
534 return NULL;
535 }
536
537 /* conf_set_defaults()
538 *
539 * inputs - NONE
540 * output - NONE
541 * side effects - Set default values here.
542 * This is called **PRIOR** to parsing the
543 * configuration file. If you want to do some validation
544 * of values later, put them in validate_conf().
545 */
546 static void
547 conf_set_defaults(void)
548 {
549 /*
550 * Verify init_class() ran, this should be an unnecessary check
551 * but it's not much work.
552 */
553 assert(class_default == class_get_list()->tail->data);
554
555 ConfigServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
556 ConfigServerInfo.network_description = xstrdup(NETWORK_DESCRIPTION_DEFAULT);
557 ConfigServerInfo.default_max_clients = MAXCLIENTS_MAX;
558 ConfigServerInfo.max_nick_length = 9;
559 ConfigServerInfo.max_topic_length = 80;
560 ConfigServerInfo.hub = 0;
561
562 log_iterate(log_free);
563
564 ConfigLog.use_logging = 1;
565
566 ConfigChannel.enable_extbans = 0;
567 ConfigChannel.disable_fake_channels = 0;
568 ConfigChannel.invite_client_count = 10;
569 ConfigChannel.invite_client_time = 300;
570 ConfigChannel.invite_delay_channel = 5;
571 ConfigChannel.invite_expire_time = 1800;
572 ConfigChannel.knock_client_count = 1;
573 ConfigChannel.knock_client_time = 300;
574 ConfigChannel.knock_delay_channel = 60;
575 ConfigChannel.max_channels = 25;
576 ConfigChannel.max_invites = 20;
577 ConfigChannel.max_bans = 100;
578 ConfigChannel.max_bans_large = 500;
579 ConfigChannel.default_join_flood_count = 18;
580 ConfigChannel.default_join_flood_time = 6;
581
582 ConfigServerHide.flatten_links = 0;
583 ConfigServerHide.flatten_links_delay = 300;
584 ConfigServerHide.hidden = 0;
585 ConfigServerHide.hide_servers = 0;
586 ConfigServerHide.hide_services = 0;
587 ConfigServerHide.hidden_name = xstrdup(NETWORK_NAME_DEFAULT);
588 ConfigServerHide.hide_server_ips = 0;
589 ConfigServerHide.disable_remote_commands = 0;
590
591 ConfigGeneral.away_count = 2;
592 ConfigGeneral.away_time = 10;
593 ConfigGeneral.max_monitor = 50;
594 ConfigGeneral.whowas_history_length = 15000;
595 ConfigGeneral.cycle_on_host_change = 1;
596 ConfigGeneral.dline_min_cidr = 16;
597 ConfigGeneral.dline_min_cidr6 = 48;
598 ConfigGeneral.kline_min_cidr = 16;
599 ConfigGeneral.kline_min_cidr6 = 48;
600 ConfigGeneral.invisible_on_connect = 1;
601 ConfigGeneral.disable_auth = 0;
602 ConfigGeneral.kill_chase_time_limit = 90;
603 ConfigGeneral.default_floodcount = 8;
604 ConfigGeneral.default_floodtime = 1;
605 ConfigGeneral.failed_oper_notice = 1;
606 ConfigGeneral.specials_in_ident = 0;
607 ConfigGeneral.min_nonwildcard = 4;
608 ConfigGeneral.min_nonwildcard_simple = 3;
609 ConfigGeneral.max_accept = 50;
610 ConfigGeneral.anti_nick_flood = 0;
611 ConfigGeneral.max_nick_time = 20;
612 ConfigGeneral.max_nick_changes = 5;
613 ConfigGeneral.anti_spam_exit_message_time = 0;
614 ConfigGeneral.ts_warn_delta = 30;
615 ConfigGeneral.ts_max_delta = 600;
616 ConfigGeneral.warn_no_connect_block = 1;
617 ConfigGeneral.stats_e_disabled = 0;
618 ConfigGeneral.stats_i_oper_only = 1; /* 1 = masked */
619 ConfigGeneral.stats_k_oper_only = 1; /* 1 = masked */
620 ConfigGeneral.stats_o_oper_only = 1;
621 ConfigGeneral.stats_m_oper_only = 1;
622 ConfigGeneral.stats_P_oper_only = 0;
623 ConfigGeneral.stats_u_oper_only = 0;
624 ConfigGeneral.caller_id_wait = 60;
625 ConfigGeneral.opers_bypass_callerid = 1;
626 ConfigGeneral.pace_wait = 10;
627 ConfigGeneral.pace_wait_simple = 1;
628 ConfigGeneral.short_motd = 0;
629 ConfigGeneral.ping_cookie = 0;
630 ConfigGeneral.no_oper_flood = 0;
631 ConfigGeneral.max_targets = MAX_TARGETS_DEFAULT;
632 ConfigGeneral.oper_only_umodes = UMODE_DEBUG | UMODE_LOCOPS | UMODE_HIDDEN | UMODE_FARCONNECT |
633 UMODE_EXTERNAL | UMODE_FLOOD | UMODE_NCHANGE |
634 UMODE_SPY | UMODE_SKILL | UMODE_REJ | UMODE_CCONN;
635 ConfigGeneral.oper_umodes = UMODE_FLOOD | UMODE_LOCOPS | UMODE_SERVNOTICE | UMODE_WALLOP;
636 ConfigGeneral.throttle_count = 1;
637 ConfigGeneral.throttle_time = 1;
638 }
639
640 static void
641 conf_validate(void)
642 {
643 if (EmptyString(ConfigServerInfo.network_name))
644 ConfigServerInfo.network_name = xstrdup(NETWORK_NAME_DEFAULT);
645
646 if (EmptyString(ConfigServerInfo.network_description))
647 ConfigServerInfo.network_description = xstrdup(NETWORK_DESCRIPTION_DEFAULT);
648 }
649
650 /* conf_read()
651 *
652 * inputs - file descriptor pointing to config file to use
653 * output - None
654 * side effects - Read configuration file.
655 */
656 static void
657 conf_read(FILE *file)
658 {
659 lineno = 1;
660
661 conf_set_defaults(); /* Set default values prior to conf parsing */
662 conf_parser_ctx.pass = 1;
663 yyparse(); /* Pick up the classes first */
664
665 rewind(file);
666
667 conf_parser_ctx.pass = 2;
668 yyparse(); /* Load the values from the conf */
669 conf_validate(); /* Check to make sure some values are still okay. */
670 /* Some global values are also loaded here. */
671 whowas_trim(); /* Attempt to trim whowas list if necessary */
672 class_delete_marked(); /* Delete unused classes that are marked for deletion */
673 }
674
675 /* conf_rehash()
676 *
677 * Actual REHASH service routine. Called with sig == 0 if it has been called
678 * as a result of an operator issuing this command, else assume it has been
679 * called as a result of the server receiving a HUP signal.
680 */
681 void
682 conf_rehash(bool sig)
683 {
684 if (sig == true)
685 {
686 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
687 "Got signal SIGHUP, reloading configuration file(s)");
688 ilog(LOG_TYPE_IRCD, "Got signal SIGHUP, reloading configuration file(s)");
689 }
690
691 restart_resolver();
692
693 /* don't close listeners until we know we can go ahead with the rehash */
694
695 conf_read_files(false);
696
697 load_conf_modules();
698 check_conf_klines();
699 }
700
701 /* conf_connect_allowed()
702 *
703 * inputs - pointer to inaddr
704 * - int type ipv4 or ipv6
705 * output - BANNED or accepted
706 * side effects - none
707 */
708 int
709 conf_connect_allowed(struct irc_ssaddr *addr)
710 {
711 const struct MaskItem *conf = find_dline_conf(addr);
712
713 if (conf)
714 {
715 /* DLINE exempt also gets you out of static limits/pacing... */
716 if (conf->type == CONF_EXEMPT)
717 return 0;
718 return BANNED_CLIENT;
719 }
720
721 struct ip_entry *ip_found = ipcache_record_find_or_add(addr);
722 if ((event_base->time.sec_monotonic - ip_found->last_attempt) < ConfigGeneral.throttle_time)
723 {
724 if (ip_found->connection_count >= ConfigGeneral.throttle_count)
725 return TOO_FAST;
726
727 ++ip_found->connection_count;
728 }
729 else
730 ip_found->connection_count = 1;
731
732 ip_found->last_attempt = event_base->time.sec_monotonic;
733 return 0;
734 }
735
736 /* cleanup_tklines()
737 *
738 * inputs - NONE
739 * output - NONE
740 * side effects - call function to expire temporary k/d lines
741 * This is an event started off in ircd.c
742 */
743 void
744 cleanup_tklines(void *unused)
745 {
746 hostmask_expire_temporary();
747 gecos_expire();
748 resv_expire();
749 }
750
751 /*
752 * Input: A client to find the active operator {} name for.
753 * Output: The nick!user@host{oper} of the oper.
754 * "oper" is server name for remote opers
755 * Side effects: None.
756 */
757 const char *
758 get_oper_name(const struct Client *client)
759 {
760 static char buf[IRCD_BUFSIZE];
761
762 if (IsServer(client))
763 return client->name;
764
765 if (MyConnect(client))
766 {
767 const dlink_node *const node = client->connection->confs.head;
768
769 if (node)
770 {
771 const struct MaskItem *const conf = node->data;
772
773 if (conf->type == CONF_OPER)
774 {
775 snprintf(buf, sizeof(buf), "%s!%s@%s{%s}", client->name,
776 client->username, client->host, conf->name);
777 return buf;
778 }
779 }
780
781 /*
782 * Probably should assert here for now. If there is an oper out there
783 * with no operator {} conf attached, it would be good for us to know...
784 */
785 assert(0); /* Oper without oper conf! */
786 }
787
788 snprintf(buf, sizeof(buf), "%s!%s@%s{%s}", client->name,
789 client->username, client->host, client->servptr->name);
790 return buf;
791 }
792
793 /* conf_clear()
794 *
795 * inputs - none
796 * output - none
797 * side effects - Clear out the old configuration
798 */
799 static void
800 conf_clear(void)
801 {
802 dlink_node *node = NULL, *node_next = NULL;
803 dlink_list *free_items [] = {
804 &connect_items, &operator_items, NULL
805 };
806
807 dlink_list ** iterator = free_items; /* C is dumb */
808
809 /* We only need to free anything allocated by yyparse() here.
810 * Resetting structs, etc, is taken care of by conf_set_defaults().
811 */
812
813 for (; *iterator; iterator++)
814 {
815 DLINK_FOREACH_SAFE(node, node_next, (*iterator)->head)
816 {
817 struct MaskItem *conf = node->data;
818
819 conf->active = false;
820 dlinkDelete(&conf->node, *iterator);
821
822 if (!conf->ref_count)
823 conf_free(conf);
824 }
825 }
826
827 /*
828 * Don't delete the class table, rather mark all entries for deletion.
829 * The table is cleaned up by class_delete_marked. - avalon
830 */
831 class_mark_for_deletion();
832
833 clear_out_address_conf();
834
835 modules_conf_clear(); /* Clear modules {} items */
836
837 motd_clear(); /* Clear motd {} items and re-cache default motd */
838
839 cluster_clear(); /* Clear cluster {} items */
840
841 gecos_clear(); /* Clear gecos {} items */
842
843 resv_clear(); /* Clear resv {} items */
844
845 service_clear(); /* Clear service {} items */
846
847 shared_clear(); /* Clear shared {} items */
848
849 pseudo_clear(); /* Clear pseudo {} items */
850
851 /* Clean out ConfigServerInfo */
852 xfree(ConfigServerInfo.description);
853 ConfigServerInfo.description = NULL;
854 xfree(ConfigServerInfo.network_name);
855 ConfigServerInfo.network_name = NULL;
856 xfree(ConfigServerInfo.network_description);
857 ConfigServerInfo.network_description = NULL;
858 xfree(ConfigServerInfo.rsa_private_key_file);
859 ConfigServerInfo.rsa_private_key_file = NULL;
860 xfree(ConfigServerInfo.tls_certificate_file);
861 ConfigServerInfo.tls_certificate_file = NULL;
862 xfree(ConfigServerInfo.tls_dh_param_file);
863 ConfigServerInfo.tls_dh_param_file = NULL;
864 xfree(ConfigServerInfo.tls_supported_groups);
865 ConfigServerInfo.tls_supported_groups = NULL;
866 xfree(ConfigServerInfo.tls_cipher_list);
867 ConfigServerInfo.tls_cipher_list = NULL;
868 xfree(ConfigServerInfo.tls_cipher_suites);
869 ConfigServerInfo.tls_cipher_suites = NULL;
870 xfree(ConfigServerInfo.tls_message_digest_algorithm);
871 ConfigServerInfo.tls_message_digest_algorithm = NULL;
872
873 /* Clean out ConfigAdminInfo */
874 xfree(ConfigAdminInfo.name);
875 ConfigAdminInfo.name = NULL;
876 xfree(ConfigAdminInfo.email);
877 ConfigAdminInfo.email = NULL;
878 xfree(ConfigAdminInfo.description);
879 ConfigAdminInfo.description = NULL;
880
881 /* Clean out ConfigServerHide */
882 xfree(ConfigServerHide.flatten_links_file);
883 ConfigServerHide.flatten_links_file = NULL;
884 xfree(ConfigServerHide.hidden_name);
885 ConfigServerHide.hidden_name = NULL;
886
887 /* Clean out listeners */
888 listener_close_marked();
889 }
890
891 static void
892 conf_handle_tls(bool cold)
893 {
894 if (tls_new_credentials() == false)
895 {
896 if (cold == true)
897 {
898 ilog(LOG_TYPE_IRCD, "Error while initializing TLS");
899 exit(EXIT_FAILURE);
900 }
901 else
902 {
903 /* Failed to load new settings/certs, old ones remain active */
904 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
905 "Error reloading TLS settings, check the ircd log"); // report_crypto_errors logs this
906 }
907 }
908 }
909
910 /* read_conf_files()
911 *
912 * inputs - cold start YES or NO
913 * output - none
914 * side effects - read all conf files needed, ircd.conf kline.conf etc.
915 */
916 void
917 conf_read_files(bool cold)
918 {
919 char buf[IRCD_BUFSIZE];
920
921 conf_parser_ctx.boot = cold;
922 conf_parser_ctx.conf_file = fopen(ConfigGeneral.configfile, "r");
923
924 if (conf_parser_ctx.conf_file == NULL)
925 {
926 if (cold == true)
927 {
928 ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s",
929 ConfigGeneral.configfile, strerror(errno));
930 exit(EXIT_FAILURE);
931 }
932 else
933 {
934 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
935 "Unable to read configuration file '%s': %s",
936 ConfigGeneral.configfile, strerror(errno));
937 return;
938 }
939 }
940
941 /*
942 * We need to know the initial filename for the yyerror() to report
943 *
944 * FIXME: The full path is in conffilenamebuf first time since we
945 * don't know anything else
946 *
947 * - Gozem 2002-07-21
948 */
949 strlcpy(conffilebuf, ConfigGeneral.configfile, sizeof(conffilebuf));
950
951 if (cold == false)
952 conf_clear();
953
954 conf_read(conf_parser_ctx.conf_file);
955 fclose(conf_parser_ctx.conf_file);
956
957 log_iterate(log_reopen);
958 conf_handle_tls(cold);
959
960 isupport_add("NICKLEN", NULL, ConfigServerInfo.max_nick_length);
961 isupport_add("NETWORK", ConfigServerInfo.network_name, -1);
962
963 snprintf(buf, sizeof(buf), "beI:%u", ConfigChannel.max_bans);
964 isupport_add("MAXLIST", buf, -1);
965
966 isupport_add("MAXTARGETS", NULL, ConfigGeneral.max_targets);
967 isupport_add("CHANTYPES", "#", -1);
968
969 snprintf(buf, sizeof(buf), "#:%u", ConfigChannel.max_channels);
970 isupport_add("CHANLIMIT", buf, -1);
971
972 isupport_add("CHANNELLEN", NULL, CHANNELLEN);
973 isupport_add("TOPICLEN", NULL, ConfigServerInfo.max_topic_length);
974
975 snprintf(buf, sizeof(buf), "%s", "beI,k,l,cimnprstuCKLMNORST");
976 isupport_add("CHANMODES", buf, -1);
977 }
978
979 /* conf_add_class_to_conf()
980 *
981 * inputs - pointer to config item
982 * output - NONE
983 * side effects - Add a class pointer to a conf
984 */
985 void
986 conf_add_class_to_conf(struct MaskItem *conf, const char *name)
987 {
988 if (EmptyString(name) || (conf->class = class_find(name, true)) == NULL)
989 {
990 conf->class = class_default;
991
992 if (conf->type == CONF_CLIENT || conf->type == CONF_OPER)
993 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
994 "Warning *** Defaulting to default class for %s@%s",
995 conf->user, conf->host);
996 else
997 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
998 "Warning *** Defaulting to default class for %s",
999 conf->name);
1000 }
1001 }
1002
1003 /* yyerror()
1004 *
1005 * inputs - message from parser
1006 * output - NONE
1007 * side effects - message to opers and log file entry is made
1008 */
1009 void
1010 yyerror(const char *msg)
1011 {
1012 if (conf_parser_ctx.pass != 1)
1013 return;
1014
1015 const char *p = stripws(linebuf);
1016 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
1017 "\"%s\", line %u: %s: %s",
1018 conffilebuf, lineno, msg, p);
1019 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1020 conffilebuf, lineno, msg, p);
1021 }
1022
1023 void
1024 conf_error_report(const char *msg)
1025 {
1026 const char *p = stripws(linebuf);
1027 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
1028 "\"%s\", line %u: %s: %s",
1029 conffilebuf, lineno, msg, p);
1030 ilog(LOG_TYPE_IRCD, "\"%s\", line %u: %s: %s",
1031 conffilebuf, lineno, msg, p);
1032 }
1033
1034 /*
1035 * valid_tkline()
1036 *
1037 * inputs - pointer to ascii string to check
1038 * - whether the specified time is in seconds or minutes
1039 * output - -1 not enough parameters
1040 * - 0 if not an integer number, else the number
1041 * side effects - none
1042 * Originally written by Dianora (Diane, db@db.net)
1043 */
1044 uintmax_t
1045 valid_tkline(const char *data, const int minutes)
1046 {
1047 const unsigned char *p = (const unsigned char *)data;
1048 unsigned char tmpch = '\0';
1049 uintmax_t result = 0;
1050
1051 while ((tmpch = *p++))
1052 {
1053 if (!IsDigit(tmpch))
1054 return 0;
1055
1056 result *= 10;
1057 result += (tmpch & 0xF);
1058 }
1059
1060 /*
1061 * In the degenerate case where oper does a /quote kline 0 user@host :reason
1062 * i.e. they specifically use 0, I am going to return 1 instead as a return
1063 * value of non-zero is used to flag it as a temporary kline
1064 */
1065 if (result == 0)
1066 result = 1;
1067
1068 /*
1069 * If the incoming time is in seconds convert it to minutes for the purpose
1070 * of this calculation
1071 */
1072 if (minutes == 0)
1073 result = result / 60;
1074
1075 if (result > MAX_TDKLINE_TIME)
1076 result = MAX_TDKLINE_TIME;
1077
1078 result = result * 60; /* Turn it into seconds */
1079
1080 return result;
1081 }
1082
1083 /* valid_wild_card_simple()
1084 *
1085 * inputs - data to check for sufficient non-wildcard characters
1086 * outputs - 1 if valid, else 0
1087 * side effects - none
1088 */
1089 bool
1090 valid_wild_card_simple(const char *data)
1091 {
1092 const unsigned char *p = (const unsigned char *)data;
1093 unsigned char tmpch = '\0';
1094 unsigned int nonwild = 0, wild = 0;
1095
1096 while ((tmpch = *p++))
1097 {
1098 if (tmpch == '\\' && *p)
1099 {
1100 ++p;
1101 if (++nonwild >= ConfigGeneral.min_nonwildcard_simple)
1102 return true;
1103 }
1104 else if (!IsMWildChar(tmpch))
1105 {
1106 if (++nonwild >= ConfigGeneral.min_nonwildcard_simple)
1107 return true;
1108 }
1109 else
1110 ++wild;
1111 }
1112
1113 return wild == 0;
1114 }
1115
1116 /* valid_wild_card()
1117 *
1118 * input - pointer to client
1119 * - int flag, 0 for no warning oper 1 for warning oper
1120 * - count of following varargs to check
1121 * output - 0 if not valid, 1 if valid
1122 * side effects - NOTICE is given to client if warn is 1
1123 */
1124 bool
1125 valid_wild_card(int count, ...)
1126 {
1127 unsigned char tmpch = '\0';
1128 unsigned int nonwild = 0;
1129 va_list args;
1130
1131 /*
1132 * Now we must check the user and host to make sure there
1133 * are at least NONWILDCHARS non-wildcard characters in
1134 * them, otherwise assume they are attempting to kline
1135 * *@* or some variant of that. This code will also catch
1136 * people attempting to kline *@*.tld, as long as NONWILDCHARS
1137 * is greater than 3. In that case, there are only 3 non-wild
1138 * characters (tld), so if NONWILDCHARS is 4, the kline will
1139 * be disallowed.
1140 * -wnder
1141 */
1142
1143 va_start(args, count);
1144
1145 while (count--)
1146 {
1147 const unsigned char *p = va_arg(args, const unsigned char *);
1148 if (p == NULL)
1149 continue;
1150
1151 while ((tmpch = *p++))
1152 {
1153 if (!IsKWildChar(tmpch))
1154 {
1155 /*
1156 * If we find enough non-wild characters, we can
1157 * break - no point in searching further.
1158 */
1159 if (++nonwild >= ConfigGeneral.min_nonwildcard)
1160 {
1161 va_end(args);
1162 return true;
1163 }
1164 }
1165 }
1166 }
1167
1168 va_end(args);
1169 return false;
1170 }
1171
1172 /* XXX should this go into a separate file ? -Dianora */
1173 /* parse_aline
1174 *
1175 * input - pointer to cmd name being used
1176 * - pointer to client using cmd
1177 * - parc parameter count
1178 * - parv[] list of parameters to parse
1179 * - parse_flags bit map of things to test
1180 * - pointer to user or string to parse into
1181 * - pointer to host or NULL to parse into if non NULL
1182 * - pointer to optional tkline time or NULL
1183 * - pointer to target_server to parse into if non NULL
1184 * - pointer to reason to parse into
1185 *
1186 * output - 1 if valid, 0 if not valid
1187 * side effects - A generalised k/d/x etc. line parser,
1188 * "ALINE [time] user@host|string [ON] target :reason"
1189 * will parse returning a parsed user, host if
1190 * h_p pointer is non NULL, string otherwise.
1191 * if tkline_time pointer is non NULL a tk line will be set
1192 * to non zero if found.
1193 * if tkline_time pointer is NULL and tk line is found,
1194 * error is reported.
1195 * if target_server is NULL and an "ON" is found error
1196 * is reported.
1197 * if reason pointer is NULL ignore pointer,
1198 * this allows use of parse_a_line in unkline etc.
1199 *
1200 * - Dianora
1201 */
1202 bool
1203 parse_aline(const char *cmd, struct Client *client, int parc, char **parv, struct aline_ctx *aline)
1204 {
1205 static char default_reason[] = CONF_NOREASON;
1206 static char user[USERLEN * 2 + 1];
1207 static char host[HOSTLEN * 2 + 1];
1208
1209 ++parv;
1210 --parc;
1211
1212 if (aline->add == true && (aline->duration = valid_tkline(*parv, TK_MINUTES)))
1213 {
1214 ++parv;
1215 --parc;
1216 }
1217
1218 if (parc == 0)
1219 {
1220 sendto_one_numeric(client, &me, ERR_NEEDMOREPARAMS, cmd);
1221 return false;
1222 }
1223
1224 if (aline->simple_mask == true)
1225 {
1226 aline->mask = *parv;
1227 aline->user = NULL;
1228 aline->host = NULL;
1229 }
1230 else
1231 {
1232 struct split_nuh_item nuh;
1233
1234 nuh.nuhmask = *parv;
1235 nuh.nickptr = NULL;
1236 nuh.userptr = user;
1237 nuh.hostptr = host;
1238
1239 nuh.nicksize = 0;
1240 nuh.usersize = sizeof(user);
1241 nuh.hostsize = sizeof(host);
1242
1243 split_nuh(&nuh);
1244
1245 aline->mask = NULL;
1246 aline->user = user;
1247 aline->host = host;
1248 }
1249
1250 ++parv;
1251 --parc;
1252
1253 if (parc)
1254 {
1255 if (irccmp(*parv, "ON") == 0)
1256 {
1257 ++parv;
1258 --parc;
1259
1260 if (!HasOFlag(client, OPER_FLAG_REMOTEBAN))
1261 {
1262 sendto_one_numeric(client, &me, ERR_NOPRIVS, "remoteban");
1263 return false;
1264 }
1265
1266 if (parc == 0 || EmptyString(*parv))
1267 {
1268 sendto_one_numeric(client, &me, ERR_NEEDMOREPARAMS, cmd);
1269 return false;
1270 }
1271
1272 aline->server = *parv;
1273 ++parv;
1274 --parc;
1275 }
1276 else
1277 aline->server = NULL;
1278 }
1279
1280 if (aline->add == true)
1281 {
1282 if (parc == 0 || EmptyString(*parv))
1283 aline->reason = default_reason;
1284 else
1285 aline->reason = *parv;
1286 }
1287
1288 return true;
1289 }
1290
1291 /* match_conf_password()
1292 *
1293 * inputs - pointer to given password
1294 * - pointer to Conf
1295 * output - 1 or 0 if match
1296 * side effects - none
1297 */
1298 bool
1299 match_conf_password(const char *password, const struct MaskItem *conf)
1300 {
1301 const char *encr = NULL;
1302
1303 if (EmptyString(password) || EmptyString(conf->passwd))
1304 return false;
1305
1306 if (conf->flags & CONF_FLAGS_ENCRYPTED)
1307 encr = crypt(password, conf->passwd);
1308 else
1309 encr = password;
1310
1311 return encr && strcmp(encr, conf->passwd) == 0;
1312 }
1313
1314 /*
1315 * split_nuh
1316 *
1317 * inputs - pointer to original mask (modified in place)
1318 * - pointer to pointer where nick should go
1319 * - pointer to pointer where user should go
1320 * - pointer to pointer where host should go
1321 * output - NONE
1322 * side effects - mask is modified in place
1323 * If nick pointer is NULL, ignore writing to it
1324 * this allows us to use this function elsewhere.
1325 *
1326 * mask nick user host
1327 * ---------------------- ------- ------- ------
1328 * Dianora!db@db.net Dianora db db.net
1329 * Dianora Dianora * *
1330 * db.net * * db.net
1331 * OR if nick pointer is NULL
1332 * Dianora - * Dianora
1333 * Dianora! Dianora * *
1334 * Dianora!@ Dianora * *
1335 * Dianora!db Dianora db *
1336 * Dianora!@db.net Dianora * db.net
1337 * db@db.net * db db.net
1338 * !@ * * *
1339 * @ * * *
1340 * ! * * *
1341 */
1342 void
1343 split_nuh(struct split_nuh_item *const iptr)
1344 {
1345 char *p = NULL, *q = NULL;
1346
1347 if (iptr->nickptr)
1348 strlcpy(iptr->nickptr, "*", iptr->nicksize);
1349
1350 if (iptr->userptr)
1351 strlcpy(iptr->userptr, "*", iptr->usersize);
1352
1353 if (iptr->hostptr)
1354 strlcpy(iptr->hostptr, "*", iptr->hostsize);
1355
1356 if ((p = strchr(iptr->nuhmask, '!')))
1357 {
1358 *p = '\0';
1359
1360 if (iptr->nickptr && *iptr->nuhmask)
1361 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
1362
1363 if ((q = strchr(++p, '@')))
1364 {
1365 *q++ = '\0';
1366
1367 if (*p)
1368 strlcpy(iptr->userptr, p, iptr->usersize);
1369
1370 if (*q)
1371 strlcpy(iptr->hostptr, q, iptr->hostsize);
1372 }
1373 else
1374 {
1375 if (*p)
1376 strlcpy(iptr->userptr, p, iptr->usersize);
1377 }
1378 }
1379 else
1380 {
1381 /* No ! found so lets look for a user@host */
1382 if ((p = strchr(iptr->nuhmask, '@')))
1383 {
1384 /* if found a @ */
1385 *p++ = '\0';
1386
1387 if (*iptr->nuhmask)
1388 strlcpy(iptr->userptr, iptr->nuhmask, iptr->usersize);
1389
1390 if (*p)
1391 strlcpy(iptr->hostptr, p, iptr->hostsize);
1392 }
1393 else
1394 {
1395 /* No @ found */
1396 if (iptr->nickptr == NULL || strpbrk(iptr->nuhmask, ".:"))
1397 strlcpy(iptr->hostptr, iptr->nuhmask, iptr->hostsize);
1398 else
1399 strlcpy(iptr->nickptr, iptr->nuhmask, iptr->nicksize);
1400 }
1401 }
1402 }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.30