]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_slave.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / trusts / trusts_slave.c
CommitLineData
82a316e7
CP
1#include <stdlib.h>
2#include <stdarg.h>
3#include <stdio.h>
4#include <string.h>
5#include <strings.h>
35449aa5 6#include "../core/hooks.h"
82a316e7
CP
7#include "../core/config.h"
8#include "../core/error.h"
9#include "../control/control.h"
c4610da5 10#include "../lib/version.h"
82a316e7
CP
11#include "../lib/sha1.h"
12#include "../lib/hmac.h"
13#include "../lib/irc_string.h"
14#include "../core/schedule.h"
15#include "../server/server.h"
be70d6c5 16#include "../xsb/xsb.h"
35449aa5
CP
17#include "trusts.h"
18
c4610da5
GB
19MODULE_VERSION("");
20
82a316e7 21static int syncing, synced;
e854b1bf 22static sstring *smasterserver;
82a316e7
CP
23
24static unsigned int curlineno, totallines;
25static SHA1_CTX s;
26
27void trusts_replication_createtables(void);
28void trusts_replication_swap(void);
29void trusts_replication_complete(int);
30
e854b1bf
CP
31static int masterserver(void *source);
32
82a316e7
CP
33static void __abandonreplication(const char *fn, int line, char *error, ...) {
34 va_list ap;
35 char buf[512], buf2[600];
36
37 va_start(ap, error);
e854b1bf 38 vsnprintf(buf, sizeof(buf), error, ap);
82a316e7
CP
39 va_end(ap);
40
41 snprintf(buf2, sizeof(buf2), "Error replicating (function: %s, line: %d): %s", fn, line, buf);
42
43 Error("trusts_slave", ERR_ERROR, "%s", buf2);
35449aa5 44
f803c9ca 45 syncing = synced = 0;
82a316e7 46
2ab0a1e7 47 controlwall(NO_DEVELOPER, NL_TRUSTS, "Warning: %s", buf2);
35449aa5
CP
48}
49
82a316e7
CP
50#define abandonreplication(x, ...) __abandonreplication(__FUNCTION__, __LINE__, x , # __VA_ARGS__)
51
52void trusts_replication_complete(int error) {
53 if(error) {
54 abandonreplication("final replication stage: error %d", error);
55 return;
56 }
57 Error("trusts_slave", ERR_INFO, "Replication complete!");
58
59 if(!trusts_loaddb()) {
60 abandonreplication("couldn't load database");
35449aa5 61 return;
82a316e7
CP
62 }
63
64 synced = 1;
65}
66
67static char *extractline(char *buf, int reset, int update, int final) {
68 unsigned char n = '\n';
69 int chars = 0;
70 unsigned int lineno, id;
71 static unsigned int curid;
72
73 if(sscanf(buf, "%u %u %n", &id, &lineno, &chars) != 2) {
74 abandonreplication("bad number for sscanf result");
75 return NULL;
76 }
77
78 if(chars <= 0) {
79 abandonreplication("bad number of characters");
80 return NULL;
81 }
82
83 if(reset && (lineno != 1)) {
84 abandonreplication("bad initial line number");
85 return NULL;
86 }
87
88 if(update) {
89 if(reset) {
90 curlineno = 2;
91 curid = id;
92 SHA1Init(&s);
93 } else {
94 /* will happen if two are sent at once, but that's ok */
95 if(id != curid)
96 return NULL;
97
98 if(lineno != curlineno) {
e854b1bf 99 abandonreplication("unexpected line number (%u vs. %u)", lineno, curlineno);
82a316e7
CP
100 return NULL;
101 }
102 if(lineno > totallines) {
103 abandonreplication("too many lines");
82a316e7
CP
104 return NULL;
105 }
106
107 curlineno++;
108
109 }
110
111 if(!final) {
112 SHA1Update(&s, (unsigned char *)buf, strlen(buf));
113 SHA1Update(&s, &n, 1);
114 }
115 }
116
117 return &buf[chars];
118}
119
120/* trinit id lineno force totallines */
121static int xsb_trinit(void *source, int argc, char **argv) {
122 char *buf;
123 unsigned int forced;
124
e854b1bf
CP
125 if(!masterserver(source))
126 return CMD_ERROR;
127
82a316e7
CP
128 if(argc < 1) {
129 abandonreplication("bad number of args");
130 return CMD_ERROR;
131 }
132
133 buf = extractline(argv[0], 1, 0, 1);
134 if(!buf)
135 return CMD_ERROR;
136
137 if((sscanf(buf, "%u %u", &forced, &totallines) != 2)) {
138 abandonreplication("bad number for sscanf result");
139 return CMD_ERROR;
140 }
141
142 if(totallines < 2) {
143 abandonreplication("bad number of lines");
144 return CMD_ERROR;
145 }
146
e854b1bf 147 if(!forced && synced)
82a316e7
CP
148 return CMD_OK;
149
150 if(!extractline(argv[0], 1, 1, 0))
151 return CMD_ERROR;
152
153 trusts_replication_createtables();
154
155 syncing = 1;
156
157 Error("trusts_slave", ERR_INFO, "Replication in progress. . .");
158 return CMD_OK;
159}
160
161/* trdata id lines type data */
162static int xsb_trdata(void *source, int argc, char **argv) {
163 char *buf;
164
165 if(!syncing)
166 return CMD_OK;
167
e854b1bf
CP
168 if(!masterserver(source))
169 return CMD_ERROR;
170
82a316e7
CP
171 if(argc < 1) {
172 abandonreplication("bad number of args");
173 return CMD_ERROR;
174 }
175
176 buf = extractline(argv[0], 0, 1, 0);
177 if(!buf)
178 return CMD_ERROR;
179
180 if(buf[0] && (buf[1] == ' ')) {
181 if(buf[0] == 'G') {
182 trustgroup tg;
183 if(!parsetg(&buf[2], &tg, 0)) {
e854b1bf 184 abandonreplication("bad trustgroup line: %s", buf);
82a316e7
CP
185 return CMD_ERROR;
186 }
187 trustsdb_inserttg("replication_groups", &tg);
188
189 freesstring(tg.name);
190 freesstring(tg.createdby);
191 freesstring(tg.contact);
192 freesstring(tg.comment);
193
194 } else if(buf[0] == 'H') {
195 unsigned int tgid;
196 trusthost th;
197
198 if(!parseth(&buf[2], &th, &tgid, 0)) {
e854b1bf 199 abandonreplication("bad trusthost line: %s", buf);
82a316e7
CP
200 return CMD_ERROR;
201 }
202 trustsdb_insertth("replication_hosts", &th, tgid);
203 } else {
e854b1bf 204 abandonreplication("bad trust type: %c", buf[0]);
82a316e7 205
82a316e7
CP
206 return CMD_ERROR;
207 }
208 } else {
e854b1bf 209 abandonreplication("malformed line: %s", buf);
82a316e7
CP
210 }
211
212 return CMD_OK;
213}
214
215/* trfini id lines sha */
216static int xsb_trfini(void *source, int argc, char **argv) {
217 char *buf, digestbuf[SHA1_DIGESTSIZE * 2 + 1];
218 unsigned char digest[SHA1_DIGESTSIZE];
219
220 if(!syncing)
221 return CMD_OK;
222
e854b1bf
CP
223 if(!masterserver(source))
224 return CMD_ERROR;
225
82a316e7
CP
226 if(argc < 1) {
227 abandonreplication("bad number of args");
228 return CMD_ERROR;
229 }
230
231 buf = extractline(argv[0], 0, 1, 1);
232 if(!buf)
233 return CMD_ERROR;
234
235 if((totallines + 1) != curlineno) {
e854b1bf 236 abandonreplication("wrong number of lines received: %u vs. %u", totallines, curlineno - 1);
82a316e7
CP
237 return CMD_ERROR;
238 }
239
240 SHA1Final(digest, &s);
0bd91417 241 if(hmac_strcmp(hmac_printhex(digest, digestbuf, SHA1_DIGESTSIZE), buf)) {
82a316e7 242 abandonreplication("digest mismatch");
82a316e7
CP
243 return CMD_ERROR;
244 }
35449aa5 245
82a316e7
CP
246 Error("trusts_slave", ERR_INFO, "Data verification successful.");
247
248 trusts_replication_swap();
249
250 synced = 1;
e854b1bf 251 syncing = 0;
82a316e7
CP
252
253 return CMD_OK;
254}
255
256static int xsb_traddgroup(void *source, int argc, char **argv) {
257 trustgroup tg, *otg;
258
259 if(!synced)
260 return CMD_OK;
261
e854b1bf
CP
262 if(!masterserver(source))
263 return CMD_ERROR;
264
82a316e7
CP
265 if(argc < 1) {
266 abandonreplication("bad number of arguments");
267 return CMD_ERROR;
268 }
269
270 if(!parsetg(argv[0], &tg, 0)) {
e854b1bf 271 abandonreplication("bad trustgroup line: %s", argv[0]);
82a316e7
CP
272 return CMD_ERROR;
273 }
274
275 otg = tg_copy(&tg);
276
277 freesstring(tg.name);
278 freesstring(tg.createdby);
279 freesstring(tg.contact);
280 freesstring(tg.comment);
281
282 if(!otg) {
283 abandonreplication("unable to add trustgroup");
284 return CMD_ERROR;
285 }
286
287 return CMD_OK;
288}
289
290static int xsb_traddhost(void *source, int argc, char **argv) {
291 unsigned int tgid;
292 trusthost th;
293
294 if(!synced)
295 return CMD_OK;
296
e854b1bf
CP
297 if(!masterserver(source))
298 return CMD_ERROR;
299
82a316e7
CP
300 if(argc < 1) {
301 abandonreplication("bad number of arguments");
302 return CMD_ERROR;
303 }
304
305 if(!parseth(argv[0], &th, &tgid, 0)) {
e854b1bf 306 abandonreplication("bad trusthost line: %s", argv[0]);
82a316e7
CP
307 return CMD_ERROR;
308 }
309
2ab0a1e7 310 th.group = tg_getbyid(tgid);
82a316e7
CP
311 if(!th.group) {
312 abandonreplication("unable to lookup trustgroup");
313 return CMD_ERROR;
314 }
315
316 if(!th_copy(&th)) {
317 abandonreplication("unable to add trusthost");
318 return CMD_ERROR;
319 }
320
321 return CMD_OK;
322}
323
324static int xsb_trdelhost(void *source, int argc, char **argv) {
2ab0a1e7
CP
325 unsigned int id;
326 trusthost *th;
327
82a316e7
CP
328 if(!synced)
329 return CMD_OK;
330
e854b1bf
CP
331 if(!masterserver(source))
332 return CMD_ERROR;
333
82a316e7
CP
334 if(argc < 1) {
335 abandonreplication("bad number of arguments");
336 return CMD_ERROR;
337 }
338
2ab0a1e7
CP
339 id = strtoul(argv[0], NULL, 10);
340 if(!id) {
341 abandonreplication("unable to convert id to integer");
342 return CMD_ERROR;
343 }
344
345 th = th_getbyid(id);
346 if(!th) {
347 abandonreplication("unable to lookup id");
348 return CMD_ERROR;
349 }
350
351 th_delete(th);
352
82a316e7
CP
353 return CMD_OK;
354}
355
356static int xsb_trdelgroup(void *source, int argc, char **argv) {
2ab0a1e7
CP
357 unsigned int id;
358 trustgroup *tg;
359
82a316e7
CP
360 if(!synced)
361 return CMD_OK;
362
e854b1bf
CP
363 if(!masterserver(source))
364 return CMD_ERROR;
365
82a316e7
CP
366 if(argc < 1) {
367 abandonreplication("bad number of arguments");
368 return CMD_ERROR;
369 }
370
2ab0a1e7
CP
371 id = strtoul(argv[0], NULL, 10);
372 if(!id) {
373 abandonreplication("unable to convert id to integer");
374 return CMD_ERROR;
375 }
376
377 tg = tg_getbyid(id);
378 if(!tg) {
379 abandonreplication("unable to lookup id");
380 return CMD_ERROR;
381 }
382
383 tg_delete(tg);
384
385 return CMD_OK;
386}
387
388static int xsb_trmodifygroup(void *source, int argc, char **argv) {
389 trustgroup tg, *otg;
390
391 if(!synced)
392 return CMD_OK;
393
394 if(!masterserver(source))
395 return CMD_ERROR;
396
397 if(argc < 1) {
398 abandonreplication("bad number of arguments");
399 return CMD_ERROR;
400 }
401
402 if(!parsetg(argv[0], &tg, 0)) {
403 abandonreplication("bad trustgroup line: %s", argv[0]);
404 return CMD_ERROR;
405 }
406
407 otg = tg_getbyid(tg.id);
408
409 if(otg && !tg_modify(otg, &tg)) {
410 abandonreplication("unable to modify database");
411 return CMD_ERROR;
412 }
413
414 freesstring(tg.name);
415 freesstring(tg.createdby);
416 freesstring(tg.contact);
417 freesstring(tg.comment);
418
419 if(!otg) {
420 abandonreplication("unable to lookup id");
421 return CMD_ERROR;
422 }
423
424 tg_update(otg);
425
82a316e7
CP
426 return CMD_OK;
427}
428
058f68c5
GB
429static int xsb_trmodifyhost(void *source, int argc, char **argv) {
430 trustgroup *tg;
431 trusthost th, *oth;
432 unsigned int groupid;
433
434 if(!synced)
435 return CMD_OK;
436
437 if(!masterserver(source))
438 return CMD_ERROR;
439
440 if(argc < 1) {
441 abandonreplication("bad number of arguments");
442 return CMD_ERROR;
443 }
444
445 if(!parseth(argv[0], &th, &groupid, 0)) {
446 abandonreplication("bad trusthost line: %s", argv[0]);
447 return CMD_ERROR;
448 }
449
450 tg = tg_getbyid(groupid);
451
452 for(oth=tg->hosts;oth;oth=oth->next) {
453 if(ipmask_check(&oth->ip, &th.ip, th.bits) && th.bits == oth->bits)
454 break;
455 }
456
457 if(oth && !th_modify(oth, &th)) {
458 abandonreplication("unable to modify database");
459 return CMD_ERROR;
460 }
461
462 if(!oth) {
463 abandonreplication("unable to lookup host");
464 return CMD_ERROR;
465 }
466
467 th_update(oth);
468
469 return CMD_OK;
470}
471
e854b1bf 472static int loaded, masternumeric = -1;
be70d6c5
CP
473static void *syncsched;
474
e854b1bf
CP
475static int masterserver(void *source) {
476 nick *np = source;
477 int home = homeserver(np->numeric);
478
479 if(home < 0)
480 return 0;
481
482 if(home != masternumeric) {
483 Error("trusts_slave", ERR_WARNING, "Command from server that isn't a master: %s", serverlist[home].name->content);
484 return 0;
485 }
486
487 return 1;
488}
489
be70d6c5 490static void checksynced(void *arg) {
e854b1bf
CP
491 if(!synced && !syncing)
492 xsb_broadcast("trrequeststart", NULL, "%s", "");
be70d6c5
CP
493}
494
82a316e7
CP
495static int trusts_cmdtrustresync(void *source, int argc, char **argv) {
496 nick *np = source;
497
e854b1bf 498 syncing = synced = 0;
82a316e7 499
be70d6c5 500 checksynced(NULL);
82a316e7
CP
501 controlreply(np, "Synchronisation request sent.");
502
503 return CMD_OK;
504}
505
82a316e7 506static void __serverlinked(int hooknum, void *arg) {
e854b1bf 507 int servernum = (int)(long)arg;
82a316e7 508
e854b1bf
CP
509 if(!ircd_strcmp(serverlist[servernum].name->content, smasterserver->content)) {
510 masternumeric = servernum;
82a316e7 511 syncing = synced = 0;
be70d6c5 512 checksynced(NULL);
82a316e7 513 }
35449aa5
CP
514}
515
516void _init(void) {
82a316e7 517 sstring *m;
35449aa5 518
82a316e7
CP
519 m = getconfigitem("trusts", "master");
520 if(m && (atoi(m->content) != 0)) {
521 Error("trusts_slave", ERR_ERROR, "Not a slave server, not loaded.");
522 return;
523 }
524
e854b1bf
CP
525 smasterserver = getcopyconfigitem("trusts", "masterserver", "", 255);
526 if(!smasterserver || !smasterserver->content || !smasterserver->content[0]) {
82a316e7 527 Error("trusts_slave", ERR_ERROR, "No master server defined.");
e854b1bf 528 freesstring(smasterserver);
82a316e7
CP
529 return;
530 }
531
f139c388
CP
532 masternumeric = findserver(smasterserver->content);
533
82a316e7
CP
534 loaded = 1;
535
536 registercontrolhelpcmd("trustresync", NO_DEVELOPER, 0, trusts_cmdtrustresync, "Usage: trustresync");
537
538 xsb_addcommand("trinit", 1, xsb_trinit);
539 xsb_addcommand("trdata", 1, xsb_trdata);
540 xsb_addcommand("trfini", 1, xsb_trfini);
541 xsb_addcommand("traddhost", 1, xsb_traddhost);
542 xsb_addcommand("traddgroup", 1, xsb_traddgroup);
543 xsb_addcommand("trdelhost", 1, xsb_trdelhost);
544 xsb_addcommand("trdelgroup", 1, xsb_trdelgroup);
2ab0a1e7 545 xsb_addcommand("trmodifygroup", 1, xsb_trmodifygroup);
058f68c5 546 xsb_addcommand("trmodifyhost", 1, xsb_trmodifyhost);
82a316e7
CP
547
548 registerhook(HOOK_SERVER_LINKED, __serverlinked);
549 syncsched = schedulerecurring(time(NULL)+5, 0, 60, checksynced, NULL);
550
551 if(trusts_fullyonline())
be70d6c5 552 checksynced(NULL);
35449aa5
CP
553}
554
555void _fini(void) {
82a316e7
CP
556 if(!loaded)
557 return;
558
e854b1bf 559 freesstring(smasterserver);
82a316e7
CP
560
561 deregistercontrolcmd("trustresync", trusts_cmdtrustresync);
562
563 xsb_delcommand("trinit", xsb_trinit);
564 xsb_delcommand("trdata", xsb_trdata);
565 xsb_delcommand("trfini", xsb_trfini);
566 xsb_delcommand("traddhost", xsb_traddhost);
567 xsb_delcommand("traddgroup", xsb_traddgroup);
568 xsb_delcommand("trdelhost", xsb_trdelhost);
569 xsb_delcommand("trdelgroup", xsb_trdelgroup);
2ab0a1e7 570 xsb_delcommand("trmodifygroup", xsb_trmodifygroup);
058f68c5 571 xsb_delcommand("trmodifyhost", xsb_trmodifyhost);
82a316e7
CP
572
573 deregisterhook(HOOK_SERVER_LINKED, __serverlinked);
574
575 deleteschedule(syncsched, checksynced, NULL);
35449aa5 576
82a316e7 577 trusts_closedb(0);
35449aa5 578}