Remove spy hooks.
[seven.git] / src / s_newconf.c
blobd294443f8aee78b84a47729058f3938d3d17aeed
1 /*
2 * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
3 * s_newconf.c - code for dealing with conf stuff
5 * Copyright (C) 2004 Lee Hardy <lee@leeh.co.uk>
6 * Copyright (C) 2004-2005 ircd-ratbox development team
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
12 * 1.Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * 2.Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3.The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
32 * $Id: s_newconf.c 147 2006-11-13 12:35:45Z spb $
35 #include "stdinc.h"
36 #include "ircd_defs.h"
37 #include "common.h"
38 #include "s_conf.h"
39 #include "s_newconf.h"
40 #include "tools.h"
41 #include "client.h"
42 #include "memory.h"
43 #include "s_serv.h"
44 #include "send.h"
45 #include "hostmask.h"
46 #include "newconf.h"
47 #include "hash.h"
48 #include "balloc.h"
49 #include "event.h"
50 #include "sprintf_irc.h"
52 dlink_list shared_conf_list;
53 dlink_list cluster_conf_list;
54 dlink_list oper_conf_list;
55 dlink_list hubleaf_conf_list;
56 dlink_list server_conf_list;
57 dlink_list xline_conf_list;
58 dlink_list resv_conf_list; /* nicks only! */
59 dlink_list nd_list; /* nick delay */
60 dlink_list tgchange_list;
62 patricia_tree_t *tgchange_tree;
64 static BlockHeap *nd_heap = NULL;
66 static void expire_temp_rxlines(void *unused);
67 static void expire_nd_entries(void *unused);
69 void
70 init_s_newconf(void)
72 tgchange_tree = New_Patricia(PATRICIA_BITS);
73 nd_heap = BlockHeapCreate(sizeof(struct nd_entry), ND_HEAP_SIZE);
74 eventAddIsh("expire_nd_entries", expire_nd_entries, NULL, 30);
75 eventAddIsh("expire_temp_rxlines", expire_temp_rxlines, NULL, 60);
78 void
79 clear_s_newconf(void)
81 struct server_conf *server_p;
82 dlink_node *ptr;
83 dlink_node *next_ptr;
85 DLINK_FOREACH_SAFE(ptr, next_ptr, shared_conf_list.head)
87 /* ptr here is ptr->data->node */
88 dlinkDelete(ptr, &shared_conf_list);
89 free_remote_conf(ptr->data);
92 DLINK_FOREACH_SAFE(ptr, next_ptr, cluster_conf_list.head)
94 dlinkDelete(ptr, &cluster_conf_list);
95 free_remote_conf(ptr->data);
98 DLINK_FOREACH_SAFE(ptr, next_ptr, hubleaf_conf_list.head)
100 dlinkDelete(ptr, &hubleaf_conf_list);
101 free_remote_conf(ptr->data);
104 DLINK_FOREACH_SAFE(ptr, next_ptr, oper_conf_list.head)
106 free_oper_conf(ptr->data);
107 dlinkDestroy(ptr, &oper_conf_list);
110 DLINK_FOREACH_SAFE(ptr, next_ptr, server_conf_list.head)
112 server_p = ptr->data;
114 if(!server_p->servers)
116 dlinkDelete(ptr, &server_conf_list);
117 free_server_conf(ptr->data);
119 else
120 server_p->flags |= SERVER_ILLEGAL;
124 void
125 clear_s_newconf_bans(void)
127 struct ConfItem *aconf;
128 dlink_node *ptr, *next_ptr;
130 DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
132 aconf = ptr->data;
134 if(aconf->hold)
135 continue;
137 free_conf(aconf);
138 dlinkDestroy(ptr, &xline_conf_list);
141 DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
143 aconf = ptr->data;
145 /* temporary resv */
146 if(aconf->hold)
147 continue;
149 free_conf(aconf);
150 dlinkDestroy(ptr, &resv_conf_list);
153 clear_resv_hash();
156 struct remote_conf *
157 make_remote_conf(void)
159 struct remote_conf *remote_p = MyMalloc(sizeof(struct remote_conf));
160 return remote_p;
163 void
164 free_remote_conf(struct remote_conf *remote_p)
166 s_assert(remote_p != NULL);
167 if(remote_p == NULL)
168 return;
170 MyFree(remote_p->username);
171 MyFree(remote_p->host);
172 MyFree(remote_p->server);
173 MyFree(remote_p);
177 find_shared_conf(const char *username, const char *host,
178 const char *server, int flags)
180 struct remote_conf *shared_p;
181 dlink_node *ptr;
183 DLINK_FOREACH(ptr, shared_conf_list.head)
185 shared_p = ptr->data;
187 if(match(shared_p->username, username) &&
188 match(shared_p->host, host) &&
189 match(shared_p->server, server))
191 if(shared_p->flags & flags)
192 return YES;
193 else
194 return NO;
198 return NO;
201 void
202 propagate_generic(struct Client *source_p, const char *command,
203 const char *target, int cap, const char *format, ...)
205 char buffer[BUFSIZE];
206 va_list args;
208 va_start(args, format);
209 ircvsnprintf(buffer, sizeof(buffer), format, args);
210 va_end(args);
212 sendto_match_servs(source_p, target, cap, NOCAPS,
213 "%s %s %s",
214 command, target, buffer);
215 sendto_match_servs(source_p, target, CAP_ENCAP, cap,
216 "ENCAP %s %s %s",
217 target, command, buffer);
220 void
221 cluster_generic(struct Client *source_p, const char *command,
222 int cltype, int cap, const char *format, ...)
224 char buffer[BUFSIZE];
225 struct remote_conf *shared_p;
226 va_list args;
227 dlink_node *ptr;
229 va_start(args, format);
230 ircvsnprintf(buffer, sizeof(buffer), format, args);
231 va_end(args);
233 DLINK_FOREACH(ptr, cluster_conf_list.head)
235 shared_p = ptr->data;
237 if(!(shared_p->flags & cltype))
238 continue;
240 sendto_match_servs(source_p, shared_p->server, cap, NOCAPS,
241 "%s %s %s",
242 command, shared_p->server, buffer);
243 sendto_match_servs(source_p, shared_p->server, CAP_ENCAP, cap,
244 "ENCAP %s %s %s",
245 shared_p->server, command, buffer);
249 struct oper_conf *
250 make_oper_conf(void)
252 struct oper_conf *oper_p = MyMalloc(sizeof(struct oper_conf));
253 return oper_p;
256 void
257 free_oper_conf(struct oper_conf *oper_p)
259 s_assert(oper_p != NULL);
260 if(oper_p == NULL)
261 return;
263 MyFree(oper_p->username);
264 MyFree(oper_p->host);
265 MyFree(oper_p->name);
267 if(oper_p->passwd)
269 memset(oper_p->passwd, 0, strlen(oper_p->passwd));
270 MyFree(oper_p->passwd);
273 #ifdef HAVE_LIBCRYPTO
274 MyFree(oper_p->rsa_pubkey_file);
276 if(oper_p->rsa_pubkey)
277 RSA_free(oper_p->rsa_pubkey);
278 #endif
280 MyFree(oper_p);
283 struct oper_conf *
284 find_oper_conf(const char *username, const char *host, const char *locip, const char *name)
286 struct oper_conf *oper_p;
287 struct irc_sockaddr_storage ip, cip;
288 char addr[HOSTLEN+1];
289 int bits, cbits;
290 dlink_node *ptr;
292 parse_netmask(locip, (struct sockaddr *)&cip, &cbits);
294 DLINK_FOREACH(ptr, oper_conf_list.head)
296 oper_p = ptr->data;
298 /* name/username doesnt match.. */
299 if(irccmp(oper_p->name, name) || !match(oper_p->username, username))
300 continue;
302 strlcpy(addr, oper_p->host, sizeof(addr));
304 if(parse_netmask(addr, (struct sockaddr *)&ip, &bits) != HM_HOST)
306 if(ip.ss_family == cip.ss_family &&
307 comp_with_mask_sock((struct sockaddr *)&ip, (struct sockaddr *)&cip, bits))
308 return oper_p;
311 /* we have to compare against the host as well, because its
312 * valid to set a spoof to an IP, which if we only compare
313 * in ip form to sockhost will not necessarily match --anfl
315 if(match(oper_p->host, host))
316 return oper_p;
319 return NULL;
322 struct oper_flags oper_flagtable[] =
324 { OPER_ADMIN, 'A', 'a' },
325 { OPER_REMOTEBAN, 'B', 'b' },
326 { OPER_KILL, 'C', 'c' },
327 { OPER_DIE, 'D', 'd' },
328 { OPER_EXPERIMENTAL, 'E', 'e' },
329 { OPER_STAFFER, 'F', 'f' },
330 { OPER_GRANT, 'G', 'g' },
331 { OPER_REHASH, 'H', 'h' },
332 { OPER_KLINE, 'K', 'k' },
333 { OPER_OPERWALL, 'L', 'l' },
334 { OPER_CMODES, 'M', 'm' },
335 { OPER_MASSNOTICE, 'N', 'n' },
336 { OPER_OVERRIDE, 'O', 'o' },
337 { OPER_RESV, 'Q', 'q' },
338 { OPER_ROUTING, 'R', 'r' },
339 { OPER_AUSPEX, 'S', 's' },
340 { OPER_HELPER, 'T', 't' },
341 { OPER_UNKLINE, 'U', 'u' },
342 { OPER_WALLOPS, 'W', 'w' },
343 { OPER_XLINE, 'X', 'x' },
344 { 0, '\0', '\0' }
347 const char *
348 get_oper_privs(int flags)
350 static char buf[20];
351 char *p;
352 int i;
354 p = buf;
356 for(i = 0; oper_flagtable[i].flag; i++)
358 if(flags & oper_flagtable[i].flag)
359 *p++ = oper_flagtable[i].has;
360 else
361 *p++ = oper_flagtable[i].hasnt;
364 *p = '\0';
366 return buf;
369 struct server_conf *
370 make_server_conf(void)
372 struct server_conf *server_p = MyMalloc(sizeof(struct server_conf));
373 server_p->aftype = AF_INET;
374 return server_p;
377 void
378 free_server_conf(struct server_conf *server_p)
380 s_assert(server_p != NULL);
381 if(server_p == NULL)
382 return;
384 if(!EmptyString(server_p->passwd))
386 memset(server_p->passwd, 0, strlen(server_p->passwd));
387 MyFree(server_p->passwd);
390 if(!EmptyString(server_p->spasswd))
392 memset(server_p->spasswd, 0, strlen(server_p->spasswd));
393 MyFree(server_p->spasswd);
396 MyFree(server_p->name);
397 MyFree(server_p->host);
398 MyFree(server_p->class_name);
399 MyFree(server_p);
402 void
403 add_server_conf(struct server_conf *server_p)
405 if(EmptyString(server_p->class_name))
407 DupString(server_p->class_name, "default");
408 server_p->class = default_class;
409 return;
412 server_p->class = find_class(server_p->class_name);
414 if(server_p->class == default_class)
416 conf_report_error("Warning connect::class invalid for %s",
417 server_p->name);
419 MyFree(server_p->class_name);
420 DupString(server_p->class_name, "default");
423 if(strchr(server_p->host, '*') || strchr(server_p->host, '?'))
424 return;
427 struct server_conf *
428 find_server_conf(const char *name)
430 struct server_conf *server_p;
431 dlink_node *ptr;
433 DLINK_FOREACH(ptr, server_conf_list.head)
435 server_p = ptr->data;
437 if(ServerConfIllegal(server_p))
438 continue;
440 if(match(name, server_p->name))
441 return server_p;
444 return NULL;
447 void
448 attach_server_conf(struct Client *client_p, struct server_conf *server_p)
450 /* already have an attached conf */
451 if(client_p->localClient->att_sconf)
453 /* short circuit this special case :) */
454 if(client_p->localClient->att_sconf == server_p)
455 return;
457 detach_server_conf(client_p);
460 CurrUsers(server_p->class)++;
462 client_p->localClient->att_sconf = server_p;
463 server_p->servers++;
466 void
467 detach_server_conf(struct Client *client_p)
469 struct server_conf *server_p = client_p->localClient->att_sconf;
471 if(server_p == NULL)
472 return;
474 client_p->localClient->att_sconf = NULL;
475 server_p->servers--;
476 CurrUsers(server_p->class)--;
478 if(ServerConfIllegal(server_p) && !server_p->servers)
480 /* the class this one is using may need destroying too */
481 if(MaxUsers(server_p->class) < 0 && CurrUsers(server_p->class) <= 0)
482 free_class(server_p->class);
484 dlinkDelete(&server_p->node, &server_conf_list);
485 free_server_conf(server_p);
489 void
490 set_server_conf_autoconn(struct Client *source_p, char *name, int newval)
492 struct server_conf *server_p;
494 if((server_p = find_server_conf(name)) != NULL)
496 if(newval)
497 server_p->flags |= SERVER_AUTOCONN;
498 else
499 server_p->flags &= ~SERVER_AUTOCONN;
501 sendto_realops_snomask(SNO_GENERAL, L_ALL,
502 "%s has changed AUTOCONN for %s to %i",
503 get_oper_name(source_p), name, newval);
505 else
506 sendto_one(source_p, ":%s NOTICE %s :Can't find %s",
507 me.name, source_p->name, name);
510 struct ConfItem *
511 find_xline(const char *gecos, int counter)
513 struct ConfItem *aconf;
514 dlink_node *ptr;
516 DLINK_FOREACH(ptr, xline_conf_list.head)
518 aconf = ptr->data;
520 if(match_esc(aconf->name, gecos))
522 if(counter)
523 aconf->port++;
524 return aconf;
528 return NULL;
531 struct ConfItem *
532 find_nick_resv(const char *name)
534 struct ConfItem *aconf;
535 dlink_node *ptr;
537 DLINK_FOREACH(ptr, resv_conf_list.head)
539 aconf = ptr->data;
541 if(match_esc(aconf->name, name))
543 aconf->port++;
544 return aconf;
548 return NULL;
551 /* clean_resv_nick()
553 * inputs - nick
554 * outputs - 1 if nick is vaild resv, 0 otherwise
555 * side effects -
558 clean_resv_nick(const char *nick)
560 char tmpch;
561 int as = 0;
562 int q = 0;
563 int ch = 0;
565 if(*nick == '-' || IsDigit(*nick))
566 return 0;
568 while ((tmpch = *nick++))
570 if(tmpch == '?' || tmpch == '@' || tmpch == '#')
571 q++;
572 else if(tmpch == '*')
573 as++;
574 else if(IsNickChar(tmpch))
575 ch++;
576 else
577 return 0;
580 if(!ch && as)
581 return 0;
583 return 1;
586 /* valid_wild_card_simple()
588 * inputs - "thing" to test
589 * outputs - 1 if enough wildcards, else 0
590 * side effects -
593 valid_wild_card_simple(const char *data)
595 const char *p;
596 char tmpch;
597 int nonwild = 0;
599 /* check the string for minimum number of nonwildcard chars */
600 p = data;
602 while((tmpch = *p++))
604 /* found an escape, p points to the char after it, so skip
605 * that and move on.
607 if(tmpch == '\\')
609 p++;
611 else if(!IsMWildChar(tmpch))
613 /* if we have enough nonwildchars, return */
614 if(++nonwild >= ConfigFileEntry.min_nonwildcard_simple)
615 return 1;
619 return 0;
622 time_t
623 valid_temp_time(const char *p)
625 time_t result = 0;
627 while(*p)
629 if(IsDigit(*p))
631 result *= 10;
632 result += ((*p) & 0xF);
633 p++;
635 else
636 return -1;
639 if(result > (60 * 24 * 7 * 52))
640 result = (60 * 24 * 7 * 52);
642 return(result * 60);
645 static void
646 expire_temp_rxlines(void *unused)
648 struct ConfItem *aconf;
649 dlink_node *ptr;
650 dlink_node *next_ptr;
651 int i;
653 HASH_WALK_SAFE(i, R_MAX, ptr, next_ptr, resvTable)
655 aconf = ptr->data;
657 if(aconf->hold && aconf->hold <= CurrentTime)
659 if(ConfigFileEntry.tkline_expire_notices)
660 sendto_realops_snomask(SNO_GENERAL, L_ALL,
661 "Temporary RESV for [%s] expired",
662 aconf->name);
664 free_conf(aconf);
665 dlinkDestroy(ptr, &resvTable[i]);
668 HASH_WALK_END
670 DLINK_FOREACH_SAFE(ptr, next_ptr, resv_conf_list.head)
672 aconf = ptr->data;
674 if(aconf->hold && aconf->hold <= CurrentTime)
676 if(ConfigFileEntry.tkline_expire_notices)
677 sendto_realops_snomask(SNO_GENERAL, L_ALL,
678 "Temporary RESV for [%s] expired",
679 aconf->name);
680 free_conf(aconf);
681 dlinkDestroy(ptr, &resv_conf_list);
685 DLINK_FOREACH_SAFE(ptr, next_ptr, xline_conf_list.head)
687 aconf = ptr->data;
689 if(aconf->hold && aconf->hold <= CurrentTime)
691 if(ConfigFileEntry.tkline_expire_notices)
692 sendto_realops_snomask(SNO_GENERAL, L_ALL,
693 "Temporary X-line for [%s] expired",
694 aconf->name);
695 free_conf(aconf);
696 dlinkDestroy(ptr, &xline_conf_list);
701 unsigned long
702 get_nd_count(void)
704 return(dlink_list_length(&nd_list));
708 void
709 add_nd_entry(const char *name)
711 struct nd_entry *nd;
713 if(hash_find_nd(name) != NULL)
714 return;
716 nd = BlockHeapAlloc(nd_heap);
718 strlcpy(nd->name, name, sizeof(nd->name));
719 nd->expire = CurrentTime + ConfigFileEntry.nick_delay;
721 /* this list is ordered */
722 dlinkAddTail(nd, &nd->lnode, &nd_list);
723 add_to_nd_hash(name, nd);
726 void
727 free_nd_entry(struct nd_entry *nd)
729 dlinkDelete(&nd->lnode, &nd_list);
730 dlinkDelete(&nd->hnode, &ndTable[nd->hashv]);
731 BlockHeapFree(nd_heap, nd);
734 void
735 expire_nd_entries(void *unused)
737 struct nd_entry *nd;
738 dlink_node *ptr;
739 dlink_node *next_ptr;
741 DLINK_FOREACH_SAFE(ptr, next_ptr, nd_list.head)
743 nd = ptr->data;
745 /* this list is ordered - we can stop when we hit the first
746 * entry that doesnt expire..
748 if(nd->expire > CurrentTime)
749 return;
751 free_nd_entry(nd);
755 void
756 add_tgchange(const char *host)
758 tgchange *target;
759 patricia_node_t *pnode;
761 if(find_tgchange(host))
762 return;
764 target = MyMalloc(sizeof(tgchange));
765 pnode = make_and_lookup(tgchange_tree, host);
767 pnode->data = target;
768 target->pnode = pnode;
770 DupString(target->ip, host);
771 target->expiry = CurrentTime + (60*60*12);
773 dlinkAdd(target, &target->node, &tgchange_list);
776 tgchange *
777 find_tgchange(const char *host)
779 patricia_node_t *pnode;
781 if((pnode = match_exact_string(tgchange_tree, host)))
782 return pnode->data;
784 return NULL;