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