]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_policy.c
Add missing module version info.
[irc/quakenet/newserv.git] / trusts / trusts_policy.c
CommitLineData
543c86ce
GB
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdarg.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8
9#ifndef __USE_MISC
10#define __USE_MISC /* inet_aton */
11#endif
12
13#include <arpa/inet.h>
14#include <sys/un.h>
15#include <sys/poll.h>
16#include <errno.h>
17#include <fcntl.h>
18
c4610da5 19#include "../lib/version.h"
543c86ce
GB
20#include "../lib/hmac.h"
21#include "../core/events.h"
22#include "../core/schedule.h"
23#include "../core/nsmalloc.h"
cfe0e8e4 24#include "../core/hooks.h"
1961b117 25#include "../core/config.h"
cfe0e8e4 26#include "../control/control.h"
148db7b8 27#include "../lib/irc_string.h"
1961b117 28#include "../irc/irc.h"
a473a1be 29#include "../glines/glines.h"
cfe0e8e4
CP
30#include "trusts.h"
31
c4610da5
GB
32MODULE_VERSION("");
33
b3a88c21 34static int countext, enforcepolicy_irc, enforcepolicy_auth;
2129448c 35
543c86ce
GB
36#define TRUSTBUFSIZE 8192
37#define TRUSTPASSLEN 128
38#define NONCELEN 16
cfe0e8e4 39
543c86ce
GB
40typedef struct trustsocket {
41 int fd;
6a7133c8
GB
42 int authed;
43 char authuser[SERVERLEN+1];
543c86ce
GB
44 char buf[TRUSTBUFSIZE];
45 unsigned char nonce[NONCELEN];
46 int size;
6a7133c8 47 time_t connected;
543c86ce 48 time_t timeout;
6a7133c8
GB
49 int accepted;
50 int rejected;
543c86ce
GB
51
52 struct trustsocket *next;
53} trustsocket;
9097ab05 54
543c86ce 55static trustsocket *tslist;
6a7133c8 56static int listenerfd = -1;
543c86ce
GB
57static FILE *urandom;
58
59typedef struct trustaccount {
60 int used;
61 char server[SERVERLEN+1];
62 char password[TRUSTPASSLEN+1];
63} trustaccount;
64
65trustaccount trustaccounts[MAXSERVERS];
66
3c5c26a8 67static int checkconnectionth(const char *username, struct irc_in_addr *ip, trusthost *th, int hooknum, int usercountadjustment, char *message, size_t messagelen) {
543c86ce
GB
68 trustgroup *tg;
69
70 if(messagelen>0)
71 message[0] = '\0';
72
1b86e67d 73 if(!th || !trustsdbloaded)
543c86ce 74 return POLICY_SUCCESS;
cebc4cab 75
6e6e98da
GB
76 tg = th->group;
77
2129448c
CP
78 /*
79 * the purpose of this logic is to avoid spam like this:
80 * WARNING: tgX exceeded limit: 11 connected vs 10 max
81 * (goes back down to 10)
82 * WARNING: tgX exceeded limit: 11 connected vs 10 max
83 */
84
85 if(hooknum == HOOK_TRUSTS_NEWNICK) {
afe99911
GB
86 patricia_node_t *head, *node;
87 int nodecount = 0;
88
543c86ce 89 head = refnode(iptree, ip, th->nodebits);
afe99911
GB
90 PATRICIA_WALK(head, node)
91 {
92 nodecount += node->usercount;
93 }
94 PATRICIA_WALK_END;
95 derefnode(iptree, head);
96
6ca057fd 97 if(th->maxpernode && nodecount + usercountadjustment > th->maxpernode) {
7ee58107 98 controlwall(NO_OPER, NL_TRUSTS, "Hard connection limit exceeded on subnet: %s (group: %s): %d connected, %d max.", trusts_cidr2str(ip, th->nodebits), tg->name->content, nodecount + usercountadjustment, th->maxpernode);
543c86ce
GB
99 snprintf(message, messagelen, "Too many connections from your host (%s) - see http://www.quakenet.org/help/trusts/connection-limit for details.", IPtostr(*ip));
100 return POLICY_FAILURE_NODECOUNT;
afe99911
GB
101 }
102
6ca057fd 103 if(tg->trustedfor && tg->count + usercountadjustment > tg->trustedfor) {
2129448c
CP
104 if(tg->count > (long)tg->exts[countext]) {
105 tg->exts[countext] = (void *)(long)tg->count;
afe99911 106
7ee58107 107 controlwall(NO_OPER, NL_TRUSTS, "Hard connection limit exceeded (group %s): %d connected, %d max.", tg->name->content, tg->count + usercountadjustment, tg->trustedfor);
543c86ce
GB
108 snprintf(message, messagelen, "Too many connections from your trust (%s) - see http://www.quakenet.org/help/trusts/connection-limit for details.", IPtostr(*ip));
109 return POLICY_FAILURE_GROUPCOUNT;
148db7b8 110 }
543c86ce
GB
111
112 snprintf(message, messagelen, "Trust has %d out of %d allowed connections.", tg->count + usercountadjustment, tg->trustedfor);
148db7b8 113 }
afe99911 114
543c86ce 115 if((tg->flags & TRUST_ENFORCE_IDENT) && (username[0] == '~')) {
3c5c26a8 116 controlwall(NO_OPER, NL_TRUSTS, "Ident required: %s@%s (group: %s).", username, IPtostr(*ip), tg->name->content);
543c86ce
GB
117 snprintf(message, messagelen, "IDENTD required from your host (%s) - see http://www.quakenet.org/help/trusts/connection-limit for details.", IPtostr(*ip));
118 return POLICY_FAILURE_IDENTD;
1961b117
GB
119 }
120
148db7b8
CP
121 if(tg->maxperident > 0) {
122 int identcount = 0;
123 trusthost *th2;
124 nick *tnp;
125
126 for(th2=tg->hosts;th2;th2=th2->next) {
127 for(tnp=th2->users;tnp;tnp=nextbytrust(tnp)) {
543c86ce 128 if(!ircd_strcmp(tnp->ident, username))
148db7b8
CP
129 identcount++;
130 }
2129448c 131 }
148db7b8 132
6ca057fd 133 if(identcount + usercountadjustment > tg->maxperident) {
7ee58107 134 controlwall(NO_OPER, NL_TRUSTS, "Hard ident limit exceeded: %s@%s (group: %s): %d connected, %d max.", username, IPtostr(*ip), tg->name->content, identcount + usercountadjustment, tg->maxperident);
543c86ce
GB
135 snprintf(message, messagelen, "Too many connections from your username (%s@%s) - see http://www.quakenet.org/help/trusts/connection-limit for details.", username, IPtostr(*ip));
136 return POLICY_FAILURE_IDENTCOUNT;
1961b117 137 }
2129448c
CP
138 }
139 } else {
140 if(tg->count < tg->maxusage)
141 tg->exts[countext] = (void *)(long)tg->count;
142 }
543c86ce
GB
143
144 return POLICY_SUCCESS;
145}
146
3c5c26a8 147static int checkconnection(const char *username, struct irc_in_addr *ip, int hooknum, int cloneadjustment, char *message, size_t messagelen) {
543c86ce
GB
148 struct irc_in_addr ip_canonicalized;
149 ip_canonicalize_tunnel(&ip_canonicalized, ip);
150
2ba75e95 151 return checkconnectionth(username, &ip_canonicalized, th_getbyhost(&ip_canonicalized), hooknum, cloneadjustment, message, messagelen);
543c86ce
GB
152}
153
154static int trustdowrite(trustsocket *sock, char *format, ...) {
155 char buf[1024];
156 va_list va;
157 int r;
158
159 va_start(va, format);
160 r = vsnprintf(buf, sizeof(buf), format, va);
161 va_end(va);
162
163 if(r >= sizeof(buf))
164 r = sizeof(buf) - 1;
165
166 buf[r] = '\n';
167
168 if(write(sock->fd, buf, r + 1) != r + 1)
169 return 0;
170 return 1;
171}
172
173static int policycheck_auth(trustsocket *sock, const char *sequence_id, const char *username, const char *host) {
174 char message[512];
175 int verdict;
176 struct irc_in_addr ip;
177 unsigned char bits;
178
6a7133c8
GB
179 if(!ipmask_parse(host, &ip, &bits)) {
180 sock->accepted++;
543c86ce 181 return trustdowrite(sock, "PASS %s", sequence_id);
6a7133c8 182 }
543c86ce 183
3c5c26a8 184 verdict = checkconnection(username, &ip, HOOK_TRUSTS_NEWNICK, 1, message, sizeof(message));
543c86ce 185
b3a88c21
GB
186 if(!enforcepolicy_auth)
187 verdict = POLICY_SUCCESS;
188
543c86ce 189 if (verdict == POLICY_SUCCESS) {
6a7133c8
GB
190 sock->accepted++;
191
543c86ce
GB
192 if(message[0])
193 return trustdowrite(sock, "PASS %s %s", sequence_id, message);
194 else
195 return trustdowrite(sock, "PASS %s", sequence_id);
196 } else {
6a7133c8
GB
197 sock->rejected++;
198
3c5c26a8 199 controlwall(NO_OPER, NL_TRUSTS, "Rejected connection from %s@%s using IAuth: %s", username, host, message);
543c86ce
GB
200 return trustdowrite(sock, "KILL %s %s", sequence_id, message);
201 }
202}
203
204static int trustkillconnection(trustsocket *sock, char *reason) {
205 trustdowrite(sock, "QUIT %s", reason);
206 return 0;
207}
208
209static void trustfreeconnection(trustsocket *sock) {
210 trustsocket **pnext = &tslist;
211
212 for(trustsocket *ts=tslist;ts;ts=ts->next) {
213 if(ts == sock) {
214 deregisterhandler(sock->fd, 1);
215 *pnext = sock->next;
216 nsfree(POOL_TRUSTS, sock);
217 break;
218 }
219
220 pnext = &(sock->next);
221 }
222}
223
224static int handletrustauth(trustsocket *sock, char *server_name, char *mac) {
225 int i;
226 char *password = NULL;
227 unsigned char digest[16];
228 char noncehexbuf[NONCELEN * 2 + 1];
229 char hexbuf[sizeof(digest) * 2 + 1];
230
231 for(i=0;i<MAXSERVERS;i++) {
232 if(trustaccounts[i].used && strcmp(trustaccounts[i].server, server_name) == 0) {
233 password = trustaccounts[i].password;
234 break;
235 }
236 }
237
427f6077
GB
238 if (!password) {
239 controlwall(NO_OPER, NL_TRUSTS, "Invalid servername for policy socket: '%s'", server_name);
543c86ce 240 return trustkillconnection(sock, "Invalid servername.");
427f6077 241 }
543c86ce
GB
242
243 hmacmd5 h;
244 hmacmd5_init(&h, (unsigned char *)password, strlen(password));
245 hmacmd5_update(&h, (unsigned char *)hmac_printhex(sock->nonce, noncehexbuf, NONCELEN), NONCELEN * 2);
246 hmacmd5_final(&h, digest);
427f6077
GB
247 if(hmac_strcmp(mac, hmac_printhex(digest, hexbuf, sizeof(digest)))) {
248 controlwall(NO_OPER, NL_TRUSTS, "Invalid password for policy socket with servername '%s'.", server_name);
543c86ce 249 return trustkillconnection(sock, "Bad MAC.");
427f6077 250 }
543c86ce 251
6a7133c8
GB
252 sock->authed = 1;
253 strncpy(sock->authuser, server_name, SERVERLEN);
427f6077
GB
254
255 controlwall(NO_OPER, NL_TRUSTS, "Successful authentication for policy socket with servername '%s'.", server_name);
543c86ce
GB
256 return trustdowrite(sock, "AUTHOK");
257}
258
259#define MAXTOKENS 10
260static int handletrustline(trustsocket *sock, char *line) {
261 char *command, *p, *lastpos;
262 char *tokens[MAXTOKENS];
263 int tokensfound = -1;
264
265 for(command=lastpos=p=line;*p;p++) {
266 if(*p == ' ') {
267 *p = '\0';
268 if(tokensfound == MAXTOKENS)
269 return trustkillconnection(sock, "too many tokens");
270
271 if(tokensfound >= 0) {
272 tokens[tokensfound++] = lastpos;
273 } else {
274 tokensfound++;
275 }
276 lastpos = p + 1;
277 }
278 }
279 if(lastpos != p) {
280 if(tokensfound == MAXTOKENS)
281 return trustkillconnection(sock, "too many tokens");
282 tokens[tokensfound++] = lastpos;
283 }
284
6a7133c8 285 if(!sock->authed && !strcmp("AUTH", command)) {
543c86ce
GB
286 if(tokensfound != 2)
287 return trustkillconnection(sock, "incorrect arg count for command.");
288
289 return handletrustauth(sock, tokens[0], tokens[1]);
6a7133c8 290 } else if(sock->authed && !strcmp("CHECK", command)) {
543c86ce
GB
291 if(tokensfound != 3)
292 return trustkillconnection(sock, "incorrect arg count for command.");
293
294 policycheck_auth(sock, tokens[0], tokens[1], tokens[2]);
295 return 1;
296 } else {
297 Error("trusts_policy", ERR_WARNING, "Bad command: %s", command);
298 return 0;
299 }
300}
301
302static trustsocket *findtrustsocketbyfd(int fd) {
303 for(trustsocket *ts=tslist;ts;ts=ts->next)
304 if(ts->fd==fd)
305 return ts;
306
307 return NULL;
308}
309
310static int handletrustclient(trustsocket *sock) {
311 int r, remaining = TRUSTBUFSIZE - sock->size, i;
312 char *lastpos, *c;
313
314 if(!remaining) {
315 trustkillconnection(sock, "Buffer overflow.");
316 return 0;
317 }
318
319 r = read(sock->fd, sock->buf + sock->size, remaining);
320 if(r <= 0)
321 return 0;
322
323 sock->size+=r;
324 lastpos = sock->buf;
325
326 for(c=sock->buf,i=0;i<sock->size;i++,c++) {
327 if(*c != '\n')
328 continue;
329 *c = '\0';
330 if(!handletrustline(sock, lastpos))
331 return 0;
332
333 lastpos = c + 1; /* is this ok? */
334 }
335 sock->size-=lastpos - sock->buf;
336 memmove(sock->buf, lastpos, sock->size);
337
338 return 1;
339}
340
341static void processtrustclient(int fd, short events) {
342 trustsocket *sock = findtrustsocketbyfd(fd);
343
344 if(!sock)
345 return;
346
347 if(events & POLLIN)
348 if(!handletrustclient(sock))
349 trustfreeconnection(sock);
350}
351
352static void trustdotimeout(void *arg) {
353 time_t t = time(NULL);
6a7133c8 354 trustsocket **pnext, *next, *sock;
543c86ce 355
543c86ce
GB
356 pnext = &tslist;
357
6a7133c8 358 for(sock=tslist;sock;) {
543c86ce
GB
359 next = sock->next;
360
6a7133c8 361 if(!sock->authed && t >= sock->timeout) {
543c86ce
GB
362 trustkillconnection(sock, "Auth timeout.");
363 deregisterhandler(sock->fd, 1);
364 *pnext = sock->next;
365 nsfree(POOL_TRUSTS, sock);
366 } else {
367 pnext = &(sock->next);
368 }
369
370 sock=next;
371 }
372}
373
374static void processtrustlistener(int fd, short events) {
375 if(events & POLLIN) {
376 trustsocket *sock;
377 char buf[NONCELEN * 2 + 1];
378
379 int newfd = accept(fd, NULL, NULL), flags;
380 if(newfd == -1)
381 return;
382
383 flags = fcntl(newfd, F_GETFL, 0);
384 if(flags < 0) {
385 Error("trusts_policy", ERR_WARNING, "Unable to set socket non-blocking.");
386 close(newfd);
387 return;
388 }
389
390 if(fcntl(fd, F_SETFL, flags|O_NONBLOCK) < 0) {
391 Error("trusts_policy", ERR_WARNING, "Unable to set socket non-blocking.");
392 close(newfd);
393 return;
394 }
395
396 registerhandler(newfd, POLLIN|POLLERR|POLLHUP, processtrustclient);
397
398 sock = nsmalloc(POOL_TRUSTS, sizeof(trustsocket));
399 if(!sock) {
400 deregisterhandler(newfd, 1);
401 return;
402 }
403
404 sock->fd = newfd;
405 sock->next = tslist;
406 tslist = sock;
407
408 if(fread((char *)sock->nonce, 1, NONCELEN, urandom) != NONCELEN) {
409 Error("trusts_policy", ERR_WARNING, "Error getting random bytes.");
410 deregisterhandler(newfd, 1);
411 tslist = sock->next;
412 nsfree(POOL_TRUSTS, sock);
413 } else {
6a7133c8 414 sock->authed = 0;
543c86ce 415 sock->size = 0;
6a7133c8 416 sock->connected = time(NULL);
543c86ce 417 sock->timeout = time(NULL) + 30;
6a7133c8
GB
418 sock->accepted = 0;
419 sock->rejected = 0;
543c86ce
GB
420 if(!trustdowrite(sock, "AUTH %s", hmac_printhex(sock->nonce, buf, NONCELEN))) {
421 Error("trusts_policy", ERR_WARNING, "Error writing auth to fd %d.", newfd);
422 deregisterhandler(newfd, 1);
423 tslist = sock->next;
424 nsfree(POOL_TRUSTS, sock);
425 return;
426 }
427 }
428 }
429}
430
431static int createlistenersock(int port) {
432 struct sockaddr_in s;
433 int fd;
434 int optval;
435
436 memset(&s, 0, sizeof(struct sockaddr_in));
437 s.sin_family = AF_INET;
438 s.sin_addr.s_addr = INADDR_ANY;
439 s.sin_port = htons(port);
440
441 fd = socket(PF_INET, SOCK_STREAM, 0);
442 if(fd < 0) {
443 Error("trusts_policy", ERR_WARNING, "Unable to get socket for trustfd.");
444 return -1;
445 }
446
447 optval = 1;
448 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
449
450 if(bind(fd, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0) {
451 Error("trusts_policy", ERR_WARNING, "Unable to bind trustfd.");
452 close(fd);
453 return -1;
454 }
455
456 if(listen(fd, 5) < 0) {
457 Error("trusts_policy", ERR_WARNING, "Unable to listen on trustfd.");
458 close(fd);
459 return -1;
460 }
461
462 registerhandler(fd, POLLIN, processtrustlistener);
463
464 return fd;
465}
466
467static void policycheck_irc(int hooknum, void *arg) {
468 void **args = arg;
469 nick *np = args[0];
470 long moving = (long)args[1];
471 char message[512];
472 int verdict;
473
474 if(moving)
475 return;
476
3c5c26a8 477 verdict = checkconnectionth(np->ident, &np->p_nodeaddr, gettrusthost(np), hooknum, 0, message, sizeof(message));
543c86ce 478
b3a88c21
GB
479 if(!enforcepolicy_irc)
480 verdict = POLICY_SUCCESS;
3c5c26a8 481
543c86ce
GB
482 switch (verdict) {
483 case POLICY_FAILURE_NODECOUNT:
3c5c26a8 484 glinebynick(np, POLICY_GLINE_DURATION, message, GLINE_IGNORE_TRUST, "trusts_policy");
543c86ce
GB
485 break;
486 case POLICY_FAILURE_IDENTD:
3c5c26a8 487 glinebyip("~*", &np->p_ipaddr, 128, POLICY_GLINE_DURATION, message, GLINE_ALWAYS_USER|GLINE_IGNORE_TRUST, "trusts_policy");
543c86ce
GB
488 break;
489 case POLICY_FAILURE_IDENTCOUNT:
3c5c26a8 490 glinebynick(np, POLICY_GLINE_DURATION, message, GLINE_ALWAYS_USER|GLINE_IGNORE_TRUST, "trusts_policy");
543c86ce
GB
491 break;
492 }
cfe0e8e4
CP
493}
494
b3a88c21 495static int trusts_cmdtrustpolicyirc(void *source, int cargc, char **cargv) {
24954f63
GB
496 nick *sender = source;
497
498 if(cargc < 1) {
b3a88c21 499 controlreply(sender, "Use of glines for trust policy enforcement is currently %s.", enforcepolicy_irc?"enabled":"disabled");
24954f63
GB
500 return CMD_OK;
501 }
502
b3a88c21
GB
503 enforcepolicy_irc = atoi(cargv[0]);
504 controlwall(NO_OPER, NL_TRUSTS, "%s %s use of glines for trust policy enforcement.", controlid(sender), enforcepolicy_irc?"enabled":"disabled");
505 controlreply(sender, "Use of glines for trust policy enforcement is now %s.", enforcepolicy_irc?"enabled":"disabled");
24954f63
GB
506
507 return CMD_OK;
508}
509
b3a88c21
GB
510static int trusts_cmdtrustpolicyauth(void *source, int cargc, char **cargv) {
511 nick *sender = source;
512
513 if(cargc < 1) {
514 controlreply(sender, "Trust policy enforcement with IAuth is currently %s.", enforcepolicy_auth?"enabled":"disabled");
515 return CMD_OK;
516 }
517
518 enforcepolicy_auth = atoi(cargv[0]);
519 controlwall(NO_OPER, NL_TRUSTS, "%s %s trust policy enforcement with IAuth.", controlid(sender), enforcepolicy_auth?"enabled":"disabled");
520 controlreply(sender, "Trust policy enforcement with IAuth is now %s.", enforcepolicy_auth?"enabled":"disabled");
521
522 return CMD_OK;
523}
524
525
6a7133c8
GB
526static int trusts_cmdtrustsockets(void *source, int cargc, char **cargv) {
527 nick *sender = source;
528 time_t now;
529 trustsocket *sock;
530
531 time(&now);
532
533 controlreply(sender, "Server Connected for Accepted Rejected");
534
535 for(sock=tslist;sock;sock=sock->next)
536 controlreply(sender, "%-20s %20s %10d %15d", sock->authed?sock->authuser:"<not authenticated>", longtoduration(now - sock->connected, 0), sock->accepted, sock->rejected);
537
538 controlreply(sender, "-- End of list.");
539 return CMD_OK;
540}
541
427f6077 542void loadtrustaccounts(void) {
543c86ce 543 array *accts;
3affe49a 544
427f6077 545 memset(trustaccounts, 0, sizeof(trustaccounts));
543c86ce
GB
546
547 accts = getconfigitems("trusts_policy", "server");
548 if(!accts) {
549 Error("trusts_policy", ERR_INFO, "No servers added.");
550 } else {
551 sstring **servers = (sstring **)(accts->content);
552 int i;
553 for(i=0;i<accts->cursi;i++) {
554 char server[512];
555 char *pos;
556
557 if(i>=MAXSERVERS) {
558 Error("trusts_policy", ERR_INFO, "Too many servers specified.");
559 break;
560 }
427f6077 561
543c86ce 562 strncpy(server, servers[i]->content, sizeof(server));
427f6077 563
543c86ce 564 pos = strchr(server, ',');
427f6077 565
543c86ce
GB
566 if(!pos) {
567 Error("trusts_policy", ERR_INFO, "Server line is missing password: %s", server);
568 continue;
569 }
427f6077 570
543c86ce 571 *pos = '\0';
427f6077 572
543c86ce
GB
573 trustaccounts[i].used = 1;
574 strncpy(trustaccounts[i].server, server, SERVERLEN);
575 strncpy(trustaccounts[i].password, pos+1, TRUSTPASSLEN);
576 }
577 }
427f6077
GB
578}
579
580static void trustaccounts_rehash(int hooknum, void *arg) {
581 loadtrustaccounts();
582}
583
584void _init(void) {
585 sstring *m;
586 int trustport;
587
588 countext = registertgext("count");
589 if(countext == -1)
590 return;
591
b3a88c21
GB
592 m = getconfigitem("trusts_policy", "enforcepolicy_irc");
593 if(m)
594 enforcepolicy_irc = atoi(m->content);
595
596 m = getconfigitem("trusts_policy", "enforcepolicy_auth");
427f6077 597 if(m)
b3a88c21 598 enforcepolicy_auth = atoi(m->content);
427f6077
GB
599
600 m = getconfigitem("trusts_policy", "trustport");
601 if(m)
602 trustport = atoi(m->content);
603 else
604 trustport = DEFAULT_TRUSTPORT;
605
606 if(trustport)
607 listenerfd = createlistenersock(trustport);
608
609 loadtrustaccounts();
610
543c86ce 611 registerhook(HOOK_TRUSTS_NEWNICK, policycheck_irc);
427f6077
GB
612 registerhook(HOOK_TRUSTS_LOSTNICK, &policycheck_irc);
613 registerhook(HOOK_CORE_REHASH, trustaccounts_rehash);
24954f63 614
b3a88c21
GB
615 registercontrolhelpcmd("trustpolicyirc", NO_DEVELOPER, 1, trusts_cmdtrustpolicyirc, "Usage: trustpolicyirc ?1|0?\nEnables or disables policy enforcement (IRC). Shows current status when no parameter is specified.");
616 registercontrolhelpcmd("trustpolicyauth", NO_DEVELOPER, 1, trusts_cmdtrustpolicyauth, "Usage: trustpolicyauth ?1|0?\nEnables or disables policy enforcement (IAuth). Shows current status when no parameter is specified.");
6a7133c8 617 registercontrolhelpcmd("trustsockets", NO_DEVELOPER, 0, trusts_cmdtrustsockets, "Usage: trustsockets\nLists all currently active TRUST sockets.");
543c86ce
GB
618
619 schedulerecurring(time(NULL)+1, 0, 5, trustdotimeout, NULL);
620
621 urandom = fopen("/dev/urandom", "rb");
622 if(!urandom)
623 Error("trusts_policy", ERR_ERROR, "Couldn't open /dev/urandom.");
cfe0e8e4
CP
624}
625
626void _fini(void) {
6a7133c8
GB
627 trustsocket *sock, *next;
628
2129448c
CP
629 if(countext == -1)
630 return;
631
632 releasetgext(countext);
633
543c86ce
GB
634 deregisterhook(HOOK_TRUSTS_NEWNICK, policycheck_irc);
635 deregisterhook(HOOK_TRUSTS_LOSTNICK, policycheck_irc);
427f6077 636 deregisterhook(HOOK_CORE_REHASH, trustaccounts_rehash);
24954f63 637
b3a88c21
GB
638 deregistercontrolcmd("trustpolicyirc", trusts_cmdtrustpolicyirc);
639 deregistercontrolcmd("trustpolicyauth", trusts_cmdtrustpolicyauth);
6a7133c8 640 deregistercontrolcmd("trustsockets", trusts_cmdtrustsockets);
543c86ce 641
6a7133c8
GB
642 deleteallschedules(trustdotimeout);
643
543c86ce
GB
644 if (urandom)
645 fclose(urandom);
6a7133c8
GB
646
647 if (listenerfd != -1)
648 deregisterhandler(listenerfd, 1);
649
650 for(sock=tslist;sock;) {
651 next = sock->next;
652
653 trustkillconnection(sock, "Unloading module.");
654 trustfreeconnection(sock);
655
656 sock = next;
657 }
cfe0e8e4 658}